Skip to content

feat(editor): vim-style search & replace in the query buffer - #59

Merged
killertux merged 1 commit into
mainfrom
feat/search-replace
Jun 11, 2026
Merged

feat(editor): vim-style search & replace in the query buffer#59
killertux merged 1 commit into
mainfrom
feat/search-replace

Conversation

@killertux

Copy link
Copy Markdown
Owner

What

Adds vim-style search and replace to the query editor, plus version bump to 0.18.0.

:s substitute — :[range]s/pattern/replacement/flags

  • Ranges: current line (:s/…), whole buffer (:%s/…), line addresses (:3,7s/…), ./$ addresses, and visual selection (:'<,'>s/…). Pressing : in Visual mode now pre-fills '<,'>.
  • Flags: g (all matches per line), i (ignore case), c (interactive confirm).
  • Patterns use the Rust regex crate. Replacement supports $1/${name} and the vim forms \1, & (whole match), \& (literal &). A literal $ is $$.
  • Alternate separators (:s#a#b#), escaped separators (:s/a\/b/c/), and :s//new/ reusing the last pattern.
  • Vim-faithful feedback: cursor lands on the last changed line, status reads N substitutions on M lines, and a missing match reports Pattern not found: <pat>.

Interactive confirm (c flag)

:%s/foo/bar/gc opens a bottom-bar prompt highlighting each match: y replace, n skip, a all, l last, q/Esc stop. Matches are scanned live so column shifts after each replacement stay correct.

/ search UX

Keeps edtui's built-in search engine but adds the missing feedback: the /pattern echoes in the bottom bar while typing, all matches highlight live, and a plain Esc in Normal mode clears them (:nohlsearch).

Undo

The entire substitution — including a full interactive confirm session — is a single u, via an edtui capture snapshot taken before mutation (pinned by a regression test).

Implementation

  • New pure engine src/substitute.rs (parse/translate/resolve/apply, ~25 unit tests).
  • Live-scan confirm state src/state/substitute_confirm.rs.
  • Dispatch in src/action/substitute.rs; command hook in src/command.rs; key + bottom-bar wiring in src/event.rs / src/ui/bottom_bar.rs; :help section added.
  • New regex dependency.

Testing

  • cargo fmt --check, cargo clippy, and the full suite (655 tests) all pass.
  • Smoke-tested in the running TUI: all range forms, the gc confirm walk, empty-pattern reuse, the not-found error, alternate separators, Visual-mode prefill + selection scoping, single-step undo, and invalid-regex errors.

Add `:[range]s/pattern/replacement/flags` substitute plus `/` search UX:

- Ranges: current line, `%`, `N,M`, `.`/`$` addresses, and `'<,'>`
  (pressing `:` in Visual mode pre-fills the selection range).
- Flags: `g` (all per line), `i` (ignore case), `c` (interactive
  y/n/a/l/q confirm with per-match highlighting).
- Rust regex patterns; replacement supports `$1`/`${name}` plus the vim
  forms `\1`, `&` (whole match), `\&`. Alternate separators (`:s#a#b#`),
  escaped separators, and `:s//new/` reusing the last pattern.
- `/` search now echoes `/pattern` in the bottom bar and highlights all
  matches; plain `Esc` in Normal mode clears them (`:nohlsearch`).
- The whole substitution (including a full confirm session) is a single
  undo step via an edtui capture snapshot.

Bump version to 0.18.0.
@killertux
killertux merged commit 1fedd1c into main Jun 11, 2026
3 checks passed
@killertux
killertux deleted the feat/search-replace branch June 11, 2026 18:01
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