aboutsummaryrefslogtreecommitdiffstats
path: root/HANDOVER.md
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-15 11:45:56 +0200
committeruser <user@clank>2026-08-15 11:45:56 +0200
commite9dddc549de1ecd068fa152bf735a72d3a3d03c9 (patch)
treed2c9cef53917a0c444bcd05e03343e31487b9fcb /HANDOVER.md
parentsl0ppty: the prefix badge names the key you actually bound (diff)
downloadslosh-e9dddc549de1ecd068fa152bf735a72d3a3d03c9.tar.gz
slosh-e9dddc549de1ecd068fa152bf735a72d3a3d03c9.tar.xz
slosh-e9dddc549de1ecd068fa152bf735a72d3a3d03c9.zip
sl0ppty: bindings that need no leader
Every binding needed the prefix first, which is the safe design and the reason a leader exists: a multiplexer that takes chords away from the programs inside it is a multiplexer you fight. But it is the user's keyboard. Somebody who wants ctrl+alt+arrow to move between panes should be allowed to have it, including the part where that chord stops reaching vim. keys { direct { bind "ctrl+alt+left" "focus-left" bind "ctrl+alt+right" "focus-right" } } A block rather than a flag on each line, because these take a chord away from every program in every pane, and that is worth seeing at a glance -- and worth having somewhere to write the warning down, which the config now does in full: prefer chords no program wants, a bare letter certainly is not one, `none` gives it back. Three ordering decisions hold it together, none of them obvious from reading the code, all three tested: - the direct lookup happens *last* in the key path -- after the rename editor, the finder, the cheatsheet, and the prefix itself. An overlay still owns the keyboard, and a direct binding cannot shadow the leader, which would make the leader unusable with no way back. There is a test that tries exactly that and finds the prefix still working. - `direct` is part of a binding's identity rather than a property of it. `x` after the leader and `x` on its own are two bindings; binding one must not silently redefine the other. - the after-the-leader lookup falls through to direct bindings, so pressing the prefix first never makes a binding stop working. A rule you have to keep track of is a rule that will catch you out. The cheatsheet lists them under "without the leader", apart from the rest, because the caption at the top of it says "<prefix> then:" and these are precisely the ones that is not true of. The tests state the bargain rather than just the mechanism: the chord fires with no leader, and what it fires on, the program never sees -- asserted with `cat -v`, so a keystroke arriving in the pane is visible on screen rather than an invisible control byte that would prove nothing either way.
Diffstat (limited to 'HANDOVER.md')
-rw-r--r--HANDOVER.md20
1 files changed, 20 insertions, 0 deletions
diff --git a/HANDOVER.md b/HANDOVER.md
index 1950872..ea82bb5 100644
--- a/HANDOVER.md
+++ b/HANDOVER.md
@@ -235,6 +235,26 @@ repeating:
background differs from the configured one shifts slightly. Documented next
to `modal_scrim` rather than hidden.
+## Leader-less bindings
+
+`keys { direct { bind ... } }` fires without the prefix. Three ordering facts
+hold it together, and all three are tested because none is obvious from the
+code:
+
+- direct lookup happens **last** in the key path, after the rename editor, the
+ finder, the cheatsheet and the prefix itself. So an overlay still owns the
+ keyboard, and a direct binding cannot shadow the leader — which would make
+ the leader unusable with no way back.
+- `direct` is part of a binding's **identity**, not a property of it: `x`
+ after the leader and `x` on its own are two bindings, and binding one must
+ not silently redefine the other.
+- `config_lookup()` (the after-the-leader path) falls through to direct
+ bindings, so pressing the prefix first never makes a binding stop working.
+ A rule anybody has to keep track of is a rule that will surprise them.
+
+The cheatsheet lists them in their own section, because the caption at the top
+says "<prefix> then:" and these are exactly the ones that is not true of.
+
## Things left on the table
- **A `reload` keybinding.** The config watcher made it less pressing.