Skip to content

Add user-configurable keybindings#420

Open
masmu wants to merge 1 commit into
walles:masterfrom
masmu:feature/user-keybindings
Open

Add user-configurable keybindings#420
masmu wants to merge 1 commit into
walles:masterfrom
masmu:feature/user-keybindings

Conversation

@masmu

@masmu masmu commented May 22, 2026

Copy link
Copy Markdown
Contributor

Users can now customize keyboard shortcuts by placing a keybindings file at
~/.config/moor/keybindings (or $XDG_CONFIG_HOME/moor/keybindings).

Usage

Print the built-in defaults as a ready-to-edit starting point:

moor --print-default-keybindings > ~/.config/moor/keybindings

Point moor at a specific file (errors are fatal):

moor --keybindings ~/my-keybindings somefile.txt

File format

# Lines starting with # are comments; blank lines are ignored.
# Format: <key>  <action>
# Keys: a-z, A-Z, 0-9, special chars, ctrl-a…ctrl-z, escape, enter,
#       backspace, delete, up/down/left/right, home, end, pageup/pagedown,
#       alt-up/down/left/right, space
# Use 'noaction' to disable a key.

[viewing]
escape  quit
q       quit
j       scroll-down
k       scroll-up
/       search-forward
# ... one section per mode: viewing, search, filter, goto-line,
#     colon-command, mark, jump-to-mark, input

[input]
ctrl-a  cursor-home
ctrl-e  cursor-end
ctrl-k  delete-to-end

By default the file is overlaid on top of the defaults: only the keys you
list change, everything else stays as-is. Add !clear at the top to start
from a blank slate instead.

Error handling

How the file was found Parse error Unknown key/action
--keybindings (explicit) Fatal error before startup Fatal error
Default path Warning to stderr, continue with partial bindings Warning to stderr

Implementation notes

  • All per-mode switch key / switch char blocks are replaced by a
    table-driven dispatch through ModeBindings, with common scroll/quit/edit
    actions factored into a single executeCommonAction method on *Pager.

What doesn't change

Default key bindings are identical to before. Users who don't create a config
file see no difference in behavior.

Related issues

@walles

walles commented May 22, 2026

Copy link
Copy Markdown
Owner

I honestly don't know what to do with this.

Reviewing 2810 lines of code is a lot of work, and I'd need to do that since I'm the one who'd have to maintain this if merged.

Any suggestions?

@masmu

masmu commented May 22, 2026

Copy link
Copy Markdown
Contributor Author

I think it's not too bad. A lot of the added lines are tests (+1311).
In keybindings.go (+663) half of the lines are constants, definitions and keybindings_parser.go (+141) is just one straight forward function.
The rest of the diff is evenly distributed and the numbers for additions and removals almost cancel each other out. So the bare numbers look more terrifying than it actually is.
And all the pagermode-*.go do not look much different from what they were before.

My motivation comes from still looking for a not ancient pager with key binding support. That is a feature with a bigger audience then people might think, probably people like me who never got over / for starting a search. It feels like you are screwed just by not using an English keyboard. And this affects potentially a lot of people, so this is also a chance to grow the project.

You might want to start by looking at keybindings.go, then pager.go and finally just all the pagermode-*.go files to see if you like the approach and the code.

@masmu masmu force-pushed the feature/user-keybindings branch 2 times, most recently from acdb997 to 8f5c75e Compare May 23, 2026 18:36
Users can now customise all key bindings by placing a file at
~/.config/moor/keybindings (or any path passed via --keybindings).
The file uses a simple INI-style format with one [section] per pager
mode. A !clear directive wipes the built-in defaults for a clean
slate.

New flags:
  --keybindings <file>          Load keybindings from a specific file
  --print-default-keybindings   Print the built-in bindings to stdout,
                                ready to use as a starting template

Each mode's key lookup falls back through a defined chain: the mode's
own bindings are checked first, then (for not-found mode) the viewing
bindings, and common actions are available everywhere.

Implementation notes:
- All pager modes carry a ModeBindings reference and dispatch through
  it instead of hard-wired key checks.
- scrollToNextSearchHit / scrollToPreviousSearchHit now take an
  explicit wrapAround bool instead of inspecting p.mode, removing
  the mode-awareness from search logic. isNotFound() is gone.
- Status bar hints in viewing and goto-line modes are generated via
  keyForAction so they reflect whatever the user has bound.
@masmu masmu force-pushed the feature/user-keybindings branch from 8f5c75e to 86787c8 Compare May 27, 2026 23:02
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.

Keybindings to less / vim search: exit using ^C

2 participants