feat(editor): add opt-in vi-style modal editing#118
Open
laurigates wants to merge 1 commit into
Open
Conversation
Implements vi-style editing for the query editor (issue ynqa#80). Disabled by default — set `enable = true` under `[editor.vi]` to turn it on — so existing emacs-style keybindings are unchanged for everyone else. The modal logic lives in a self-contained `vi` module as a pure transformation over `(text, cursor)`, decoupled from the promkit text editor and fully unit tested. The query editor applies the engine's outcomes via the widget's existing primitives. NORMAL mode routes through the engine; INSERT mode falls through to the original text-editing path, so typing, completion, and the configured keybinds keep working unchanged. A configurable NORMAL-mode prefix makes the current mode visible. Supported in NORMAL mode: - Motions: h l 0 $ ^ w W b B e E f F t T gg G - Operators: d c y with those motions, plus linewise dd cc yy - Edits: x X D C s S r ~ p P - Counts (e.g. 3w, d2w) and undo (u) / redo (Ctrl+R) The query buffer is single-line, so linewise commands act on the whole line and o/O/./multi-line motions are intentionally unsupported. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
This was referenced Jun 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This implements the vi-style editing requested in #80 as an opt-in feature
for the query editor. It is disabled by default, so the existing
emacs-style keybindings are completely unchanged for current users. Enable it
with:
When enabled, the editor starts in NORMAL mode and the prefix (
❮❮bydefault, configurable via
normal_prefix) indicates the current mode. Pressi/a/I/Ato enter INSERT mode — where typing, Tab completion, and theconfigured keybinds all work exactly as before — and
Escto return to NORMALmode.
What's supported (NORMAL mode)
hl0$^wWbBeEf{char}F{char}t{char}T{char}ggGiIaAd/c/y+ motion, and linewiseddccyyxXDCsSr{char}~pP(from the last delete/yank)3w,d2w,5xu/Ctrl+RThe
cw/cWquirk (acts likece/cEon a non-blank) is implemented.Design
src/vi.rsmodule, written asa pure transformation over
(text, cursor)that returns anOutcomethequery editor applies. This keeps it decoupled from the promkit text widget
and fully unit-testable — 29 tests cover the motions, operators, counts,
find, paste, and edge cases (empty buffer, bounds).
existing text-editing path, so completion and the emacs keybinds are reused
rather than reimplemented.
[editor.vi]is#[serde(default)], so configuration files written beforethis change continue to load (covered by a test).
Scope / limitations
The query buffer is single-line, so linewise commands (
dd,cc,yy) act onthe whole line, and
o/O/.-repeat/multi-line motions are intentionally outof scope. Happy to adjust the keymap, defaults, or scope to fit your
preferences — this is meant as a starting point for #80.
Testing
Mirrors CI (
.github/workflows/ci.yml):cargo fmt --all -- --check— cleancargo clippy— cleancargo test— all green (29 new vi tests + 2 new config tests)cargo build --bins/--examples— okAddresses #80.