feat(sterni/acme/plan9port): allow entering BQN chars via compose
plan9port completely ignores XCompose because it has its own compose mechanism (which is mapped to the same key). The sequences are defined in /lib/keyboard and need to be compiled in. Support for the BQN unicode characters is achieved by generating the necessary lines for /lib/keyboard from the .inputrc (for GNU readline) that is part of mlochbaum/BQN (simply because that file is somewhat parseable and stores the sequences in ASCII, contrary to .XCompose). This is implemented by a small BQN script which is executed in postPatch. All usual sequences are supported except those that map to the second ASCII character of the sequence. These exist to keep certain characters typeable in other input system. Thanks to the explicit compose key, Plan 9 doesn't have this problem. Change-Id: I590c03fd69a2aae3cbbbd39ebcbce6cec0418b50 Reviewed-on: https://cl.tvl.fyi/c/depot/+/13034 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI Autosubmit: sterni <sternenseemann@systemli.org>
This commit is contained in:
parent
3b9d5a02ce
commit
9743fbf6b7
3 changed files with 91 additions and 0 deletions
67
users/sterni/acme/mkbqnkeyboard.bqn
Executable file
67
users/sterni/acme/mkbqnkeyboard.bqn
Executable file
|
|
@ -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
|
||||||
|
|
@ -7,10 +7,18 @@ let
|
||||||
(lib.mapAttrsToList
|
(lib.mapAttrsToList
|
||||||
(name: _: dir + "/${name}")
|
(name: _: dir + "/${name}")
|
||||||
(builtins.readDir dir));
|
(builtins.readDir dir));
|
||||||
|
|
||||||
|
mkbqnkeyboard' = pkgs.writeShellScript "mkbqnkeyboard'" ''
|
||||||
|
exec ${pkgs.cbqn}/bin/BQN ${../mkbqnkeyboard.bqn} -s -i \
|
||||||
|
"${pkgs.srcOnly pkgs.mbqn}/editors/inputrc" "$1"
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
|
|
||||||
pkgs.plan9port.overrideAttrs (old: {
|
pkgs.plan9port.overrideAttrs (old: {
|
||||||
patches = old.patches or [ ] ++ patchesFromDir ./.;
|
patches = old.patches or [ ] ++ patchesFromDir ./.;
|
||||||
|
postPatch = old.postPatch or "" + ''
|
||||||
|
${mkbqnkeyboard'} lib/keyboard
|
||||||
|
'';
|
||||||
|
|
||||||
nativeBuildInputs = old.nativeBuildInputs or [ ] ++ [
|
nativeBuildInputs = old.nativeBuildInputs or [ ] ++ [
|
||||||
pkgs.buildPackages.makeWrapper
|
pkgs.buildPackages.makeWrapper
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
Loading…
Add table
Add a link
Reference in a new issue