Add Vim character find and till motions (#40785)

## What changed

- Add line-local `f`, `F`, `t`, and `T` motions to Vim normal mode.
- Support the motions with `c`, `d`, and `y`, including dot-repeat for changes.
- Expose separate configurable normal-mode and operator-motion bindings, while preserving existing custom keymaps that use the new defaults.
- Keep character targeting aligned to extended grapheme boundaries and skip embedded composer elements.

## Testing

- Cover forward and backward motion and operator ranges, missing and adjacent targets, cancellation, dot-repeat, custom bindings, shifted terminal key events, grapheme clusters, and embedded elements.

GitOrigin-RevId: 2610cf9a13538d9ae9b890c01417ca25316c1d60
This commit is contained in:
Benjamin Carlsson authored and copyberry committed 2026-08-26 04:18:49 +00:00
1 parent 25a6e316c8
commit 98ee29c7cd
16 files changed
+703 -13

No files matched your search

+80
View File
@@ -3807,6 +3807,8 @@
"delete_char": null,
"delete_to_line_end": null,
"enter_insert": null,
"find_backward": null,
"find_forward": null,
"insert_line_start": null,
"move_down": null,
"move_left": null,
@@ -3826,16 +3828,22 @@
"start_delete_operator": null,
"start_yank_operator": null,
"substitute_char": null,
"till_backward": null,
"till_forward": null,
"yank_line": null
},
"vim_operator": {
"cancel": null,
"delete_line": null,
"motion_down": null,
"motion_find_backward": null,
"motion_find_forward": null,
"motion_left": null,
"motion_line_end": null,
"motion_line_start": null,
"motion_right": null,
"motion_till_backward": null,
"motion_till_forward": null,
"motion_up": null,
"motion_word_backward": null,
"motion_word_end": null,
@@ -4615,6 +4623,8 @@
"delete_char": null,
"delete_to_line_end": null,
"enter_insert": null,
"find_backward": null,
"find_forward": null,
"insert_line_start": null,
"move_down": null,
"move_left": null,
@@ -4634,6 +4644,8 @@
"start_delete_operator": null,
"start_yank_operator": null,
"substitute_char": null,
"till_backward": null,
"till_forward": null,
"yank_line": null
}
},
@@ -4647,10 +4659,14 @@
"cancel": null,
"delete_line": null,
"motion_down": null,
"motion_find_backward": null,
"motion_find_forward": null,
"motion_left": null,
"motion_line_end": null,
"motion_line_start": null,
"motion_right": null,
"motion_till_backward": null,
"motion_till_forward": null,
"motion_up": null,
"motion_word_backward": null,
"motion_word_end": null,
@@ -4933,6 +4949,22 @@
],
"description": "Enter insert mode at cursor (`i`)."
},
"find_backward": {
"allOf": [
{
"$ref": "#/definitions/KeybindingsSpec"
}
],
"description": "Find the previous character on the current line (`F`)."
},
"find_forward": {
"allOf": [
{
"$ref": "#/definitions/KeybindingsSpec"
}
],
"description": "Find the next character on the current line (`f`)."
},
"insert_line_start": {
"allOf": [
{
@@ -5085,6 +5117,22 @@
],
"description": "Delete character under cursor and enter insert mode (`s`)."
},
"till_backward": {
"allOf": [
{
"$ref": "#/definitions/KeybindingsSpec"
}
],
"description": "Stop after the previous character on the current line (`T`)."
},
"till_forward": {
"allOf": [
{
"$ref": "#/definitions/KeybindingsSpec"
}
],
"description": "Stop before the next character on the current line (`t`)."
},
"yank_line": {
"allOf": [
{
@@ -5124,6 +5172,22 @@
],
"description": "Motion: down one line (`j`)."
},
"motion_find_backward": {
"allOf": [
{
"$ref": "#/definitions/KeybindingsSpec"
}
],
"description": "Motion: find the previous character on the current line (`F`)."
},
"motion_find_forward": {
"allOf": [
{
"$ref": "#/definitions/KeybindingsSpec"
}
],
"description": "Motion: find the next character on the current line (`f`)."
},
"motion_left": {
"allOf": [
{
@@ -5156,6 +5220,22 @@
],
"description": "Motion: right (`l`)."
},
"motion_till_backward": {
"allOf": [
{
"$ref": "#/definitions/KeybindingsSpec"
}
],
"description": "Motion: stop after the previous character on the current line (`T`)."
},
"motion_till_forward": {
"allOf": [
{
"$ref": "#/definitions/KeybindingsSpec"
}
],
"description": "Motion: stop before the next character on the current line (`t`)."
},
"motion_up": {
"allOf": [
{