feat: repeat last native edit with dot
This commit is contained in:
@@ -28,6 +28,7 @@ Without a file, vamp opens an unnamed buffer. A nonexistent file opens an empty
|
||||
| Normal, Visual | Decimal prefixes repeat cursor/word/search motions: `5j`, `3k`, `2w`, `4e`, `2n`; Esc cancels a pending count |
|
||||
| Normal | `J` (Shift+j) joins each targeted line with the next line |
|
||||
| Normal | `x`/Delete delete; `u` undo; `U` (Shift+u) redo; `:` enter command mode |
|
||||
| Normal, Visual | `.` repeats the last successful native edit against the current targets; one undo group |
|
||||
| Normal | `/` opens search; `n` finds the next match; `N` (Shift+n) finds the previous match |
|
||||
| Normal | `v` starts Visual selections; `p`/`P` paste internal clipboard after/before each caret; Esc keeps only the primary caret |
|
||||
| Normal, Visual | Ctrl+k clones above; Ctrl+e clones below |
|
||||
@@ -63,6 +64,20 @@ Bracketed paste broadcasts the same literal text to all Insert carets in a separ
|
||||
|
||||
The clipboard is internal to the editor session and independent of the system clipboard. Copy/cut store fragments in document order: one fragment broadcasts to every caret; matching fragment/caret counts pair in document order; any other count refuses paste without changing state. Empty clipboard paste does not edit text; copying/cutting only empty final-row selections does not overwrite the clipboard. Open a new search or enter Ex commands after leaving Visual mode. Plugin commands execute once, not once per target: successful text effects collapse to the primary and apply once; rejected or message-only effects preserve the selection set. There is no selection-aware plugin API yet.
|
||||
|
||||
### Repeat last edit
|
||||
|
||||
`.` repeats the session's last successful native edit in Normal/Visual. Insertion placements (`i`/`I`/`a`/`A`/`o`/`O`), Insert typing and edit-context motions/newline/backspace/delete, Visual change/cut, Normal deletion, clipboard/literal paste, and line joining are recorded as resolved edit operations—not keystrokes, command invocations, or old byte offsets. Remapping keys afterward does not change the recorded operation. Insert `.` and popup query `.` remain literal. A count before dot is consumed and repeats once, consistent with other non-motion commands.
|
||||
|
||||
In Normal, Visual change/cut targeting replays its resolved motions and counts at each current caret: `vecitem` followed later by `.` changes a fresh whole word, even if its length differs. If targeting was rebuilt by cloning, occurrence gathering, search, or overlap merging, repeat uses relative whole-grapheme spans instead. Equal spans broadcast; unequal spans require matching target counts. In Visual, the current explicit ranges replace the stored targeting. Target-building commands themselves do not recreate old cursors.
|
||||
|
||||
Clipboard paste captures the fragments actually pasted, so a later yank does not change repeat's payload. One fragment broadcasts; equal fragment/target counts pair; mismatches refuse atomically. Other per-target edit data, such as partially effective Insert deletion, obeys the same conservative distribution policy. A refusal or cardinality change during replay leaves text, caret/primary state, clipboard, and history unchanged.
|
||||
|
||||
Each repeat returns to Normal and creates one undo entry restoring the full caret set and primary. Original typing/paste/typing boundaries remain separate; dot replays the selected committed group as one transaction. Typed text retains scalar insertion boundaries, preserving combining/ZWJ interactions with surrounding graphemes; bracketed paste remains one bulk literal operation. Trailing Insert movement is not repeated.
|
||||
|
||||
The last recipe is session-wide across buffers, but pending Insert groups and undo/redo remain buffer-local. No-op/identical edits, rejected input, navigation, yank, explorer filtering, saving, undo/redo, and plugin effects do not replace it. Successful buffer parking and ordinary explicit Ex execution commit pending native typing at existing boundaries; failed buffer requests do not split that group. Plugins never execute through dot. Repeat does not consume or recursively replace its recipe. Rebind with `config.core.repeat_last_edit`, including Normal/Visual leader routes.
|
||||
|
||||
### Search
|
||||
|
||||
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.
|
||||
|
||||
Submitting an empty search repeats the last query. Esc cancels without moving the cursor or replacing the previous query/match. A missing match reports the query, clears the highlight, and leaves the cursor unchanged; searching without a previous query also leaves the cursor unchanged. Search never edits text or adds undo history. Buffer edits and undo/redo clear the highlight but retain the query, so subsequent navigation searches the current text again.
|
||||
@@ -242,6 +257,7 @@ Key notation follows [Herdr's readable style](https://herdr.dev/docs/configurati
|
||||
| Normal | `join_lines`, `undo`, `redo`, `command` |
|
||||
| Normal | `search`, `paste_before`, `paste_after` |
|
||||
| Normal, Visual | `select`, `search_next`, `search_previous` |
|
||||
| Normal, Visual | `repeat_last_edit` |
|
||||
| Normal, Visual | `file_picker`, `file_explorer` |
|
||||
| Normal, Insert, Visual | `line_start`, `line_end` |
|
||||
| Normal, Insert, Visual, Tree | `left`, `right` |
|
||||
|
||||
Reference in New Issue
Block a user