diff --git a/users/sterni/acme/mkbqnkeyboard.bqn b/users/sterni/acme/mkbqnkeyboard.bqn new file mode 100755 index 000000000..e255ca27c --- /dev/null +++ b/users/sterni/acme/mkbqnkeyboard.bqn @@ -0,0 +1,67 @@ +#!/usr/bin/env BQN +# SPDX-FileCopyrightText: Copyright © 2024-2025 by sterni +# SPDX-License-Identifier: MIT +# +# Generate Compose Sequences for /lib/keyboard that enable entering BQN specific +# Unicode characters using their familiar key combinations in Plan 9 programs. + +# TODO(sterni): move these helper functions somewhere reusable +LogBase ← ÷˜○•math.Log10 +Digs ← (⌊ 1⊸+)∘LogBase +DivMod ← ⌊∘÷˜⋈| +hd←"0123456789ABCDEF" +ToHex ← {hd⊏˜(16⊸DivMod⟜⊑ ∾ 1⊸↓)⍟(-⟜1 𝕨⊸⌈⟜(16⊸Digs)) 𝕩} # 𝕨 is the min amount of digits +FromHex ← {+´(16⋆⌽↕≠𝕩)×hd⊐𝕩} +IsAscii ← 127⊸≥-⟜@ + +# Parse CLI +opts ← { + flags‿args ← 2↑'-' ((≠⟜⊑)¨⊔⊢) 𝕩 + # TODO(sterni): support multiple flags in one argument, e.g. -si + ⟨sort,help,inPlace⟩ ⇐ flags∊˜⟨"-s","-h","-i"⟩ + + argCount ← 2 + {𝕤 + •Out "Usage: "∾•name∾" [-s] [-i] /path/to/inputrc /path/to/lib/keyboard + + -i Modify lib/keyboard in place. If not given, print to stdout. + -s Sort output by Unicode Codepoint." + •Exit ¬help + }⍟(help∨argCount≠≠args) @ + + inputrcPath‿keyboardPath ⇐ •wdpath⊸•file.At¨args + WriteOutput ⇐ inPlace◶⟨•out¨,keyboardPath⊸•fLines⟩ +} •args + +# Main Program + +# Read inputrc, dropping comment and empty lines. Also drop the rule for \\. +# Since Plan9 requires an explicit keypress before entering a compose sequence, +# we don't need to add a way to type \ (or any ASCII character for that matter). +# This simplifies the parser below since we don't need to unescape anything. +inputrc←1↓(("#"⊸≢⟜(1⊸↑)∧0⊸≠∘≠)¨/⊢)•FLines opts.inputrcPath +# After removing all backslashes, the ASCII character used representing the used +# key and the resulting codepoint have a consistent position in the lines. +# Remove all ASCII chars in a second step. +# map contains pairs of ⟨BQN char, key used to type it as an ASCII char⟩ +map←(¬∘IsAscii∘⊑¨/⊢)5‿1⊸⊏¨'\'(≠/⊢)¨inputrc + +# Render the first three fields of lib/keyboard: +# ⟨Codepoint (Hex), Compose Sequence, Resulting Character⟩ +newfields←{𝕊 c‿k: ⟨4 ToHex c-@,"\"∾k,c⟩}¨map +# In the file, the fields need be padded to a specific length… +fieldsz←6‿12‿0⌈⌈´˘⍉≠¨>newfields +# … and there's a fourth name field separated by a tab. +# We don't make an effort to add a per character description there (yet). +tab←@+9 +newlines←((tab∾"BQN char") ∾´fieldsz⊸(↑¨))¨ newfields + +# Due to the consistent spacing we can just compute the sort order on the +# resulting character at index 18. +Sort ← (⍋ 18⊸⊑¨)⊏⊢ + +# Deduplicate output before writing, so the script can be executed multiple +# times or after inputrc has been changed without introducing duplicates. Since +# we duplicate on entire lines, existing alternative compose sequences aren't +# removed. +opts.WriteOutput ⍷ Sort⍟opts.sort (•FLines opts.keyboardPath)∾newlines diff --git a/users/sterni/acme/plan9port/default.nix b/users/sterni/acme/plan9port/default.nix index a456690dd..94002f35d 100644 --- a/users/sterni/acme/plan9port/default.nix +++ b/users/sterni/acme/plan9port/default.nix @@ -7,10 +7,18 @@ let (lib.mapAttrsToList (name: _: dir + "/${name}") (builtins.readDir dir)); + + mkbqnkeyboard' = pkgs.writeShellScript "mkbqnkeyboard'" '' + exec ${pkgs.cbqn}/bin/BQN ${../mkbqnkeyboard.bqn} -s -i \ + "${pkgs.srcOnly pkgs.mbqn}/editors/inputrc" "$1" + ''; in pkgs.plan9port.overrideAttrs (old: { patches = old.patches or [ ] ++ patchesFromDir ./.; + postPatch = old.postPatch or "" + '' + ${mkbqnkeyboard'} lib/keyboard + ''; nativeBuildInputs = old.nativeBuildInputs or [ ] ++ [ pkgs.buildPackages.makeWrapper diff --git a/users/sterni/acme/plan9port/latin1-increase-compose-capacity.patch b/users/sterni/acme/plan9port/latin1-increase-compose-capacity.patch new file mode 100644 index 000000000..9f407080d --- /dev/null +++ b/users/sterni/acme/plan9port/latin1-increase-compose-capacity.patch @@ -0,0 +1,16 @@ +All BQN character compose sequence use the same leading character (\). Since there +are about 80 of them, the standard lookup table size is not enough. + +diff --git a/src/cmd/devdraw/latin1.c b/src/cmd/devdraw/latin1.c +index 87c0be45..c8e79e33 100644 +--- a/src/cmd/devdraw/latin1.c ++++ b/src/cmd/devdraw/latin1.c +@@ -10,7 +10,7 @@ static struct cvlist + { + char *ld; /* must be seen before using this conversion */ + char *si; /* options for last input characters */ +- Rune so[60]; /* the corresponding Rune for each si entry */ ++ Rune so[100]; /* the corresponding Rune for each si entry */ + } latintab[] = { + #include "latin1.h" + 0, 0, { 0 }