Add Vim buffer jump motions (#40958)

## What changed

- Add `gg` and `G` motions to jump to the first and last buffer lines.
- Support the motions with delete, change, and yank operators, including dot-repeat for edits.
- Expose normal-mode and operator-motion bindings in the configurable keymap while preserving conflicting user bindings.

## Testing

- Cover buffer jumps, operator combinations, repeat behavior, chord routing, and custom remapping.

GitOrigin-RevId: 24a9178cf7964053aaf9a8cd268c5434dda0778e
This commit is contained in:
Benjamin Carlsson
2026-08-26 19:31:52 +00:00
committed by copyberry
parent 6ac012a0d4
commit d47e5cc0e2
17 changed files with 433 additions and 13 deletions
+32
View File
@@ -60,6 +60,38 @@ fn ctrl(ch: char) -> KeyEvent {
KeyEvent::new(KeyCode::Char(ch), KeyModifiers::CONTROL)
}
#[tokio::test]
async fn vim_buffer_jumps_route_default_chords_in_normal_and_operator_contexts() -> Result<()> {
for (input, command, expected) in [
("one\ntwo\nthree", "gg", "!one\ntwo\nthree"),
("one\ntwo\nthree", "dgg", "!"),
("ag bg", "0fg", "a!g bg"),
("ag bg", "0dfg", "! bg"),
] {
let (mut app, mut tui, mut app_server) = chord_app().await?;
app.chat_widget.toggle_vim_mode_and_notify();
app.chat_widget.insert_str(input);
for (index, key) in command.chars().enumerate() {
press(
&mut app,
&mut tui,
&mut app_server,
KeyCode::Char(key).into(),
)
.await?;
if key == 'g' && index + 1 < command.len() {
assert!(app.key_chord_matcher.is_pending());
}
}
assert!(!app.key_chord_matcher.is_pending());
app.chat_widget.insert_str("!");
assert_eq!(app.chat_widget.composer_text_with_pending(), expected);
}
Ok(())
}
#[tokio::test]
async fn completed_global_chord_reuses_the_existing_action_handler() -> Result<()> {
let (mut app, mut tui, mut app_server) = chord_app().await?;