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
+21 -1
View File
@@ -564,7 +564,8 @@ pub(crate) fn active_binding_specs(
context: &str,
action: &str,
) -> Result<Vec<String>, String> {
if let Some(action_id) = keymap_action_id(context, action)
let action_id = keymap_action_id(context, action);
if let Some(action_id) = action_id
&& let Some(specs) = runtime_keymap.chords.configured_specs(action_id)
{
return Ok(specs.to_vec());
@@ -573,6 +574,16 @@ pub(crate) fn active_binding_specs(
let bindings = bindings_for_action(runtime_keymap, context, action).ok_or_else(|| {
format!("Unknown keymap action `{context}.{action}`. Reopen /keymap and choose an action.")
})?;
if let Some(action_id) = action_id
&& let Some(crate::key_hint::ShortcutHint::Chord { prefix, completion }) =
runtime_keymap.chords.primary_hint(action_id, bindings)
{
return Ok(vec![format!(
"{} {}",
binding_to_config_key_spec(prefix)?,
binding_to_config_key_spec(completion)?
)]);
}
bindings
.iter()
.map(|binding| binding_to_config_key_spec(*binding))
@@ -1037,6 +1048,15 @@ mod tests {
#[test]
fn picker_unbound_tab_lists_default_unbound_actions() {
let runtime = RuntimeKeymap::defaults();
for (context, action) in [
("vim_normal", "jump_top"),
("vim_operator", "motion_jump_top"),
] {
assert_eq!(
active_binding_specs(&runtime, context, action).expect("native Vim chord"),
["g g"]
);
}
let params = build_keymap_picker_params(&runtime, &TuiKeymap::default());
let unbound_tab = selection_tab(&params, KEYMAP_UNBOUND_TAB_ID);