feat: add counted word change actions
Add cw/cb and configurable core actions using the same line-local spans as dw/db. Enter Insert with grouped replacement undo and native dot repeat.
This commit is contained in:
@@ -156,7 +156,7 @@ The built-in `gt`/`gb` sequences move to the first/last line in Normal and Visua
|
||||
|
||||
With a decimal prefix, `g` instead jumps immediately to that one-based source line: `42g` goes to line 42, clamped at EOF, at first nonblank. Normal moves all carets; Visual extends selections. In diff text panes, explicit line jumps reveal folded source lines rather than counting only displayed excerpts. `g` without a count still begins `gt`, `gb`, or `gf`; a count followed by `g` is complete and does not await a suffix. Rebind the Normal/Visual native action `config.core.go_to_line` to use the numeric prefix with another key. Existing `g` bindings and prefixes override this default route.
|
||||
|
||||
Normal `yy` copies complete rows without moving the carets; `dd` / `cc` delete/change complete rows; `dw` / `db` delete forward/backward word spans within each caret's current logical line, preserving newlines. Leading and post-operator counts multiply and word deletions stop at the line end/start. Bind `config.core.copy_line`, `config.core.delete_line`, `config.core.change_line`, `config.core.delete_word_forward`, or `config.core.delete_word_backward` to another key or sequence for another route. A configured/disabled operator key, a configured sequence starting with that key, or choosing it as the leader overrides its built-in operator prefix. These are dedicated actions, not general operator–motion grammar.
|
||||
Normal `yy` copies complete rows without moving the carets; `dd` / `cc` delete/change complete rows; `dw` / `db` delete forward/backward word spans within each caret's current logical line, preserving newlines. `cw` / `cb` cut the same spans and enter Insert. Leading and post-operator counts multiply and word edits stop at the line end/start. Bind `config.core.copy_line`, `config.core.delete_line`, `config.core.change_line`, `config.core.delete_word_forward`, `config.core.delete_word_backward`, `config.core.change_word_forward`, or `config.core.change_word_backward` to another key or sequence for another route. A configured/disabled operator key, a configured sequence starting with that key, or choosing it as the leader overrides its built-in operator prefix. These are dedicated actions, not general operator–motion grammar.
|
||||
|
||||
Normal `C` / `D` / `Y` change/delete/copy the cursor-to-line-end suffix through `config.core.change_to_line_end`, `config.core.delete_to_line_end`, and `config.core.copy_to_line_end`. Normal `r` waits for a literal replacement character through `config.core.replace_character`; `s` deletes the current grapheme and enters Insert through `config.core.substitute_character`. Rebinding these actions preserves their native counts, Unicode boundaries, undo, and read-only guards.
|
||||
|
||||
@@ -170,7 +170,7 @@ Normal `C` / `D` / `Y` change/delete/copy the cursor-to-line-end suffix through
|
||||
| Normal, Visual | `insert_first_nonblank`, `append_line_end`, `clone_above`, `clone_below` |
|
||||
| Normal | `join_lines`, `undo`, `redo`, `command` |
|
||||
| Normal | `copy_line`, `delete_line`, `change_line` |
|
||||
| Normal | `change_to_line_end`, `delete_to_line_end`, `copy_to_line_end`, `replace_character`, `substitute_character`, `delete_word_forward`, `delete_word_backward` |
|
||||
| Normal | `change_to_line_end`, `delete_to_line_end`, `copy_to_line_end`, `replace_character`, `substitute_character`, `delete_word_forward`, `delete_word_backward`, `change_word_forward`, `change_word_backward` |
|
||||
| Normal | `save`, `force_save`, `quit`, `force_quit`, `restart`, `force_restart`, `save_and_quit`, `force_save_and_quit`, `plugins` |
|
||||
| Normal | `edit`, `buffers`, `buffer`, `buffer_next`, `buffer_previous`, `buffer_delete`, `buffer_force_delete` |
|
||||
| Normal | `follow_link` |
|
||||
|
||||
+5
-2
@@ -31,6 +31,7 @@ Default controls and editing behavior. For custom bindings, see [configuration](
|
||||
| Normal | `D` deletes through line end; `C` changes that suffix and enters Insert; `Y` copies that suffix characterwise |
|
||||
| Normal | `r<char>` replaces the current grapheme; `s` deletes it and enters Insert |
|
||||
| Normal | `d<count>w` / `d<count>b` delete forward/backward word spans, e.g. `d2w` / `d2b` |
|
||||
| Normal | `c<count>w` / `c<count>b` cut the same line-local spans as `d` and enter Insert, e.g. `c2w` / `c2b` |
|
||||
| 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 characterwise Visual; `V` starts linewise Visual; `p`/`P` paste the configured clipboard after/before each caret or row for linewise fragments (system by default); Esc keeps only the primary caret |
|
||||
@@ -97,7 +98,7 @@ The status bar displays a pending count. Esc cancels it without moving, collapsi
|
||||
|
||||
`yy` copies the entire current line into the configured linewise clipboard without moving any caret, changing text, or replacing undo/redo and dot-repeat history. Counts before and after `y` multiply (`2yy`, `y2y`, `2y3y`), selecting rows downward and clamping at EOF. Empty and unterminated final rows retain linewise shape. `p` pastes these complete rows below the current line; `P` pastes above it. The caret lands on the first nonblank of the first inserted row. Characterwise yanks still paste after/before the current grapheme. Bind `config.core.copy_line` for another Normal-mode route; historical read-only buffers permit yanking but reject paste.
|
||||
|
||||
The first `d`, `c`, or `y` waits for its second key and appears in the status bar. `d` accepts `d`, `w`, or `b`; `c` accepts `c`; `y` accepts `y`. Counts before and after the operator multiply: `2d3w` deletes six forward word spans, and `d2d` deletes two rows. Escape cancels only the pending prefix/count, preserving carets; an unmatched key cancels the prefix and then performs its ordinary action. Explicit bindings, disabled first keys, and a leader using that first key take precedence.
|
||||
The first `d`, `c`, or `y` waits for its second key and appears in the status bar. `d` accepts `d`, `w`, or `b`; `c` accepts `c`, `w`, or `b`; `y` accepts `y`. Counts before and after the operator multiply: `2d3w` deletes six forward word spans, `2c3b` cuts six backward spans and enters Insert, and `d2d` deletes two rows. Escape cancels only the pending prefix/count, preserving carets; an unmatched key cancels the prefix and then performs its ordinary action. Explicit bindings, disabled first keys, and a leader using that first key take precedence.
|
||||
|
||||
System clipboard publication must succeed before any deletion. Failure preserves text, carets, mode, undo/redo, and repeat intent. `dd` is one undo action; `cc` and subsequent replacement typing form one Insert undo group. Dot repeats the original requested row count at the current carets—even if the original action was clamped at EOF—and replays `cc` replacement text. Rebind the Normal-only `config.core.delete_line` / `config.core.change_line` actions to a single key or leader sequence without relying on the built-in doubled keys.
|
||||
|
||||
@@ -107,6 +108,8 @@ System clipboard publication must succeed before any deletion. Failure preserves
|
||||
|
||||
`dw` / `db` cut characterwise spans from each caret to the forward/backward word-start boundary, using the same Unicode word boundaries as `w` / `b`, but confined to that caret's current logical line. Counts repeat the boundary motion, stopping at the line end/start without deleting its newline or touching neighboring lines; ordinary `w` / `b` navigation still crosses lines. Backward spans exclude the original caret character. Empty spans do not edit text. These are dedicated actions, not arbitrary operator–motion grammar. Suffix, substitution, and word cuts share the configured clipboard's failure-before-edit protection; all native edits support undo and dot repeat.
|
||||
|
||||
`cw` / `cb` cut exactly the same line-local spans as `dw` / `db`, including intervening whitespace, then enter Insert at each cut's start. Counts before and after `c` multiply (`2cw`, `c2w`, `2c3b`); excess counts stop at the current line's boundary. Empty spans still enter Insert, including on empty lines and for `cb` at column zero. The cut and subsequent replacement typing form one undo group; dot repeat recomputes the requested spans at the current carets and replays the replacement text. Rebind the Normal-only `config.core.change_word_forward` / `config.core.change_word_backward` actions for another route.
|
||||
|
||||
## Selections and multi-caret editing
|
||||
|
||||
Editing uses an ordered selection set with one primary target. Cursor and word motions apply to every target; Visual motions keep each target's anchor and move its active endpoint. Whole combining sequences and ZWJ emoji remain intact. `v` selects characterwise, inclusive of endpoints; `V` selects every complete row touched by the endpoints, including blank and empty final rows. Switching between `v` and `V` retains endpoints; pressing the current shape's selector again cancels. Read-only ranges are end-exclusive. Characterwise `$`/End can select the newline after a non-final row; selected newlines appear as a blue blank cell after the line. Linewise highlighting covers the copied text, including trailing whitespace, plus one blank cell for each copied newline; unused viewport space and the gutter remain unhighlighted. The status reads VISUAL LINE. Blue highlighting overrides yellow search highlighting; secondary carets are magenta, including on empty lines and at line ends. Only the primary owns the hardware cursor and viewport. The status line counts all targets, including offscreen targets.
|
||||
@@ -117,7 +120,7 @@ Copy and cut return to Normal at each selection start; Visual cancellation keeps
|
||||
|
||||
Visual `c` removes all selected text into the configured clipboard and enters Insert at each selection start. In the default System policy, clipboard publication must succeed before any deletion; failures leave text and selections intact. Deletion and 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 only characterwise empty final-row selections enters Insert without overwriting either clipboard; linewise empty final rows are genuine rows and publish a newline.
|
||||
|
||||
Bracketed paste broadcasts the same literal text to all Insert carets in a separate undo group, distinct from typing before/after it. A rejected paste leaves the pending change intact. Normal supports counted `yy`, `dd`, `cc`, `dw`, and `db`, but not general operator grammar such as `cw`; blockwise Visual is also unsupported. `c`, `d`, and `y` type literal text in Insert mode.
|
||||
Bracketed paste broadcasts the same literal text to all Insert carets in a separate undo group, distinct from typing before/after it. A rejected paste leaves the pending change intact. Normal supports counted `yy`, `dd`, `cc`, `dw`, `db`, `cw`, and `cb`, but not arbitrary operator–motion grammar; blockwise Visual is also unsupported. `c`, `d`, and `y` type literal text in Insert mode.
|
||||
|
||||
Clipboard policy is session-wide and defaults to 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 editing state. Empty clipboard paste does not edit text; copying/cutting only characterwise empty final-row selections does not overwrite either register. Linewise copy/cut retain whole-row shape, including a newline fragment for an empty final row. 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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user