Skip to content

feat(keys): configurable vim-style keybindings - #59

Merged
Rfluid merged 1 commit into
mainfrom
feat/keybindings
Sep 24, 2026
Merged

Rfluid merged 1 commit into
mainfrom
feat/keybindings

Conversation

@Rfluid

@Rfluid Rfluid commented Sep 24, 2026

Copy link
Copy Markdown
Owner

Summary

Adds keyboard shortcuts to the modal: vim-style defaults, a user override file (~/.config/aura/keybindings.toml) with warnings for bad entries, a master switch in config.toml, and an aura keys CLI that mirrors aura config.

Keymap

  • Defaults:

    Keys Does
    j/k, ctrl-d/ctrl-u, ctrl-f/ctrl-b, g g/G Scroll
    h/l, tab, g t/g T, 1–9 Section tabs
    H/L, [/] Previous / next agent or plugin
    m Switch agents ↔ plugins
    p/P Cycle the period
    r Refresh
    , Settings
    . More menu
    ? Help
    q Close the window
    esc Close the open overlay (then the window)
  • Contexts: [global] applies everywhere. [overlay] applies while a menu, the settings panel or the help is open, and wins over [global] for the same keys.

  • Overrides: "none" unbinds a key. use_defaults = false starts from an empty keymap.

  • Loading never fails. A bad entry is skipped with a warning; the rest still applies. Aura warns about:

    • invalid TOML (the whole file falls back to the defaults)
    • unknown tables or actions, with a "did you mean"
    • bad keystrokes, and values that aren't strings
    • the same key written two ways (G / shift-g)
    • unbinding a key that has no binding
    • a key that starts a longer sequence (g alongside g g)
    • taking over the text-selection keys (ctrl-c, ctrl-a, shift+arrows)
  • Where warnings show up: a header chip with the count, the top of the ? help overlay, stderr (once per distinct set), aura keys validate (exits 1), and aura doctor.

  • Off switch: [keybindings] enabled = false in config.toml turns every shortcut off. Escape still closes the window.

  • Reloading: the keymap is re-read on every open and every refresh, with no restart needed.

CLI: aura keys (alias aura keybindings)

Command Does
path Print the file path
list [--context] Effective keymap, where each binding came from, and warnings
describe [action|keys] List every action, or explain one action or keystroke
get <keys> What a keystroke does
set <keys> <action> / unbind <keys> Bind or unbind a keystroke
reset <keys>, --action, --all Drop overrides so the defaults apply again
wizard Step through every action interactively
merge <file|-> Merge another keymap in; --prefer theirs|ours, --check
export Print the full effective keymap as a standalone file
init [--full] Write a starter file
document Rewrite the file with a description on every entry
validate Report problems; exit 1 if any
edit Open the file in $EDITOR

Read commands take --format json. The write commands go through KeymapFile, which edits with toml_edit, so they keep the user's comments and layout.

Implementation notes

  • aura-core/src/keymap/ holds the parser, defaults, merge logic and warnings (mod.rs) and the file editor (file.rs). Neither has any UI code; the CLI and the modal share them.
  • aura/src/keys.rs defines one GPUI action per KeyAction, wired through an exhaustive match so an unwired action won't compile.
  • Focus: the modal root now holds a FocusHandle, because GPUI dispatches bindings only from a focused element. This reverses the "no focus handles" note in docs/plans/selectable-text.md. Nothing else in the modal is focusable, and a click anywhere puts focus back on the root.
  • Binding order: [global] and [overlay] are key contexts on the same root element, so GPUI can't rank them by depth and falls back to insertion order. Overlay bindings are therefore installed last.
  • Other changes:
    • New toml_edit dependency in aura-core. It was already in the lockfile transitively, so nothing new is downloaded.
    • CLI runs restore default SIGPIPE handling, so aura … | head exits quietly instead of panicking.

Testing

  • cargo clippy --workspace --all-targets -D warnings, cargo fmt --check and cargo test --workspace pass. There are 24 new keymap unit tests: parsing, merge, warnings, and the file editor (format preservation, wizard key-set semantics, merge, document, export round-trip).
  • Every aura keys command was tried by hand against separate test config directories.
  • Not yet checked in the running GUI:
    • Keys work right after the window opens (X11 / Wayland / macOS / Windows)
    • Clicking and dragging still selects text with the root holding focus
    • ?, G and shift-tab match on non-US keyboard layouts
    • The help overlay scrolls when the window is short

Docs: docs/keybindings.md (new), plus updates to docs/configuration.md, docs/cli.md and the README.

Add keyboard shortcuts to the modal, driven by a keymap that users can
customize in `~/.config/aura/keybindings.toml` and manage from the CLI.

Keymap (aura-core `keymap`):
- Action catalogue (scroll, navigate, commands) and vim-style defaults:
  j/k, ctrl-d/u, ctrl-f/b, gg/G, h/l + tab + gt/gT, 1-9, H/L + [/],
  m, p/P, r, `,`, `.`, `?`, q, esc.
- `[global]` and `[overlay]` contexts, `"none"` to unbind, and
  `use_defaults = false` to start from an empty keymap.
- Loading never fails. Bad entries are skipped with warnings: invalid
  TOML, unknown table or action (with a "did you mean"), bad keystroke,
  non-string value, duplicate spellings (`G` / `shift-g`), no-op
  unbinds, prefix conflicts (`g` vs `g g`), and bindings that take over
  the text-selection keys (ctrl-c, ctrl-a, shift+arrows).
- `KeymapFile`: format-preserving edits via toml_edit (bind, remove,
  clear, set_action_keys, restore_action, merge, document), so CLI
  writes keep the user's comments and layout.

Modal:
- The root element holds a FocusHandle and the `Aura` / `overlay` key
  contexts; one GPUI action per KeyAction, wired exhaustively.
- Escape clears a selection, then closes the open overlay, then closes
  the window. `q` closes the window. `quit` is available but unbound.
- `?` opens a help overlay generated from the live keymap, with any
  keymap warnings at the top. A header chip shows the warning count, and
  settings gains a Keybindings entry.
- The keymap is reloaded on every open and every refresh.
- `[keybindings] enabled` in config.toml (default true) turns every
  shortcut off; the existing Escape observer covers that case.

CLI (`aura keys`, alias `aura keybindings`):
- path, list, describe (actions or a keystroke), get, set, unbind,
  reset (keys / --action / --all), wizard, merge (--prefer, --check,
  stdin), export, init (--full), document, validate, edit.
- `aura doctor` reports the keybindings file and its warnings.
- Restore default SIGPIPE for CLI runs, so `aura … | head` exits
  quietly instead of panicking.

Docs: new docs/keybindings.md; configuration.md, cli.md and the README
updated.
@Rfluid
Rfluid merged commit d29cf62 into main Sep 24, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant