diff options
Diffstat (limited to 'AGENTS.md')
| -rw-r--r-- | AGENTS.md | 36 |
1 files changed, 35 insertions, 1 deletions
@@ -169,7 +169,7 @@ tracked config says so, and in no repo: | `~/.localprofile` | interactive setup: aliases, prompt, anything that forks | `config/profile`, last | | `~/.config/ssh/config-local` | ssh, this host only. See `config/ssh/config-local-example` | `config/ssh/entry`, before the shared defaults | | `~/.config/git/config-local` | git, this host only -- the work identity, `includeIf` blocks. See `config/git/config-local-example` | `config/git/config`, after the `[user]` block above it, and git takes the last value | -| `~/.config/hammerspoon/local.lua` | Hammerspoon: rebinding a hotkey set here shadows it. `require("dotlib")` for the same helpers init.lua uses. See `config/hammerspoon/local-example.lua` | `config/hammerspoon/init.lua`, last, in a `pcall` | +| `~/.config/hammerspoon/local.lua` | Hammerspoon: rebinding a hotkey set here shadows it, and `capslock_off()` gives this machine its Caps Lock back. `require("dotlib")` for the same helpers init.lua uses. See `config/hammerspoon/local-example.lua` | `config/hammerspoon/init.lua`, last, in a `pcall` | | `~/.config/ghostty-local` | Ghostty: later values replace earlier ones, `keybind` accumulates. See `config/ghostty/ghostty-local-example` | `config/ghostty/config`, last, as an optional `config-file` | | `~/.local/share/alacritty/local.toml` | Alacritty | imported by `config/alacritty/alacritty.toml` | | `~/.config/dot/skip` | which `link/` parts this machine does not want, one name per line | `link/lib.sh`, as each part starts | @@ -356,6 +356,40 @@ Key environment features: - Custom aliases and utility functions - Performance profiling capabilities +### Keyboard + +Caps Lock sends F20 on every Mac running the Hammerspoon config. +`dotlib.capslock_f20()`, called early from `config/hammerspoon/init.lua`, does +it with `hidutil`: the remap happens in the IOKit HID driver, below the window +server, so the key is F20 to everything -- other apps, System Settings +shortcuts, a password field, a VM. An `hs.eventtap` cannot reach Caps Lock at +all, which is why `hs.hid` exists as a separate IOKit module, and why this is +not a hotkey. + +`hidutil property --set` only touches the keyboards attached at that moment, so +three things re-apply it: the call at startup, watchers for USB attach and +system wake, and an `hs.eventtap` on `flagsChanged`. The tap is the general +answer -- a mapped keyboard cannot produce a Caps Lock event, so an event +arriving at all is proof of a keyboard that was missed, and the fault triggers +its own repair. That press is spent repairing and toggles Caps Lock for an +instant, cleared with `hs.hid.capslock.set(false)` -- also the only way to clear +a stuck Caps Lock once the key itself sends F20. Re-posting the press as a +synthetic F20 was tried and dropped: an `hs.hotkey` bound to `f20` did not fire +for a posted event. The watchers are there to catch the two common cases -- +plugging a keyboard in, waking the machine -- before any key is pressed, which +is why the repair press is rare. Caps Lock is `alphaShift` in the raw CGEvent flags and is absent from +`event:getFlags()`, which covers only cmd/alt/shift/ctrl/fn. + +There is no launchd job and no `link/` part for this. The remap lives and dies +with Hammerspoon, which already owns the keyboard on these machines. + +Nothing is bound to `f20` here; bind it like any other key. One machine gives +the key back with `require("dotlib").capslock_off()` in its `local.lua` -- +shadowing cannot work, because the remap has already run by the time +`local.lua` loads. `hs -c 'hs.inspect(require("dotlib").capslock_status())'` +reports whether the watchers and the tap are still up; that needs `hs.ipc`, +which `init.lua` requires for exactly this kind of check. + ### Utility Scripts The `bin/` directory contains various utility scripts for: - Theme management (`theme`) |
