feat: add Visual change with grouped replacement undo

This commit is contained in:
Valdemar Lorenzen
2026-10-06 13:18:57 +02:00
parent f775ff3b59
commit 53fcd7a1f2
7 changed files with 185 additions and 16 deletions
+7 -2
View File
@@ -25,7 +25,7 @@ Without a file, vamp opens an unnamed buffer. A nonexistent file opens an empty
| Normal | `x`/Delete delete; `u` undo; `U` (Shift+u) redo; `:` enter command mode |
| Normal | `/` opens search; `n` finds the next match; `N` (Shift+n) finds the previous match |
| Normal | `v` starts Visual selection; `p`/`P` paste internal clipboard after/before the cursor |
| Visual | Cursor/word motions and `n`/`N` extend selection; `y` copies; `d`/`x`/Delete cuts; `v`/Esc cancels |
| Visual | Cursor/word motions and `n`/`N` extend selection; `y` copies; `d`/`x`/Delete cuts; `c` changes selection; `v`/Esc cancels |
| Insert | Type, Enter, Tab, Backspace/Delete, arrows, Home/End; Esc returns to normal |
| Command | Enter executes; Backspace edits; Esc cancels |
| Search | Type a literal query; Enter finds the next match; Backspace edits; Esc cancels |
@@ -42,6 +42,10 @@ Visual selection is characterwise and inclusive of both endpoints, normalized wh
Copy and cut return to Normal mode at the selection start; cancellation keeps the focus cursor. Both clamp the cursor to a valid Normal-mode position. `p`/`P` paste after/before the current grapheme, including multiline text. The cursor lands on the last inserted grapheme, or the new row's start when the clipboard ends in a newline. Cut and each paste are separate undo actions. Copy, selection movement, and cancellation do not add history or clear redo. Undo/redo restore text and cursor, not the selection or clipboard.
Visual-mode `c` removes the selection into the internal clipboard and enters Insert mode at its start. Deletion and subsequent replacement typing form one undo action when Insert mode is exited, including through explicit command execution. Esc without typing commits the deletion alone. An identical replacement creates no history entry and preserves redo. Changing an empty final-row selection enters Insert mode without overwriting the clipboard.
Bracketed paste retains its existing separate undo group, distinct from typing before/after it. A rejected paste leaves the pending change intact. Normal-mode operator grammar such as `cw` is not supported; `c` types literal text in Insert mode.
The clipboard is internal to the editor session and independent of the system clipboard. Empty clipboard paste does not edit text; copying/cutting an empty final-row selection does not overwrite an existing clipboard. Open a new search or enter Ex commands after leaving Visual mode. Successful text effects or explicit command execution also leave Visual mode; rejected effects preserve the selection.
Search is case-sensitive and single-line, with no regular expressions or Unicode normalization. Matches start and end on whole grapheme boundaries, including combining marks and emoji. Next/previous navigation skips the current position and wraps through the buffer; a sole match wraps back to itself. The active match is highlighted yellow.
@@ -89,6 +93,7 @@ Vamp.configure do |config|
config.bind "ctrl+v", config.core.select
config.bind "ctrl+c", config.core.copy, mode: config.modes.visual
config.bind "ctrl+x", config.core.cut, mode: config.modes.visual
config.bind "ctrl+r", config.core.change, mode: config.modes.visual
end
```
@@ -113,7 +118,7 @@ Terminals share `ctrl+h` with `backspace`, `ctrl+i` with `tab`, and `ctrl+j`/`ct
| Normal, Insert, Visual | `left`, `down`, `up`, `right`, `line_start`, `line_end` |
| Normal, Insert, Visual | `word_next`, `word_previous`, `word_end`, `big_word_next`, `big_word_previous`, `big_word_end` |
| Normal, Insert | `delete` |
| Visual | `copy`, `cut` |
| Visual | `copy`, `cut`, `change` |
| Insert, Command, Search, Visual | `normal` |
| Insert, Command, Search | `backspace` |
| Insert | `newline` |