From 9b1e09ee1e102aff5f285d2b1ff7099929acb18e Mon Sep 17 00:00:00 2001 From: Pranav Joglekar Date: Thu, 9 Oct 2025 14:34:23 +0530 Subject: [PATCH 1/2] improv keybindings: add gt and gT bindings for markdownviewer mode --- assets/keymaps/vim.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 4d296667ff572a..e2b065f333ff96 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -810,6 +810,13 @@ "escape": "buffer_search::Dismiss" } }, + { + "context": "MarkdownPreview", + "bindings": { + "g t": "vim::GoToTab", + "g shift-t": "vim::GoToPreviousTab" + } + }, { "context": "VimControl || !Editor && !Terminal", "bindings": { From 49aa0160aae81abaa0a61246d70cf6b157d1b902 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Thu, 9 Oct 2025 16:08:22 +0200 Subject: [PATCH 2/2] Fix --- assets/keymaps/vim.json | 13 +++------- crates/vim/src/normal.rs | 51 +--------------------------------------- crates/vim/src/vim.rs | 45 ++++++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 61 deletions(-) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index e2b065f333ff96..5a546356d9c5b7 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -95,8 +95,6 @@ "g g": "vim::StartOfDocument", "g h": "editor::Hover", "g B": "editor::BlameHover", - "g t": "vim::GoToTab", - "g shift-t": "vim::GoToPreviousTab", "g d": "editor::GoToDefinition", "g shift-d": "editor::GoToDeclaration", "g y": "editor::GoToTypeDefinition", @@ -810,13 +808,6 @@ "escape": "buffer_search::Dismiss" } }, - { - "context": "MarkdownPreview", - "bindings": { - "g t": "vim::GoToTab", - "g shift-t": "vim::GoToPreviousTab" - } - }, { "context": "VimControl || !Editor && !Terminal", "bindings": { @@ -872,7 +863,9 @@ "ctrl-w ctrl-o": "workspace::CloseInactiveTabsAndPanes", "ctrl-w o": "workspace::CloseInactiveTabsAndPanes", "ctrl-w ctrl-n": "workspace::NewFileSplitHorizontal", - "ctrl-w n": "workspace::NewFileSplitHorizontal" + "ctrl-w n": "workspace::NewFileSplitHorizontal", + "g t": "vim::GoToTab", + "g shift-t": "vim::GoToPreviousTab" } }, { diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index bf45129021de7d..cd9ff0d9205917 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -123,8 +123,6 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut Context) { Vim::action(editor, cx, Vim::toggle_comments); Vim::action(editor, cx, Vim::paste); Vim::action(editor, cx, Vim::show_location); - Vim::action(editor, cx, Vim::go_to_tab); - Vim::action(editor, cx, Vim::go_to_previous_tab); Vim::action(editor, cx, |vim, _: &DeleteLeft, window, cx| { vim.record_current_action(cx); @@ -1012,55 +1010,8 @@ impl Vim { self.switch_mode(Mode::Insert, true, window, cx); } } - - fn go_to_tab(&mut self, _: &GoToTab, window: &mut Window, cx: &mut Context) { - let count = Vim::take_count(cx); - Vim::take_forced_motion(cx); - - if let Some(tab_index) = count { - // gt goes to tab (1-based). - let zero_based_index = tab_index.saturating_sub(1); - window.dispatch_action( - workspace::pane::ActivateItem(zero_based_index).boxed_clone(), - cx, - ); - } else { - // If no count is provided, go to the next tab. - window.dispatch_action(workspace::pane::ActivateNextItem.boxed_clone(), cx); - } - } - - fn go_to_previous_tab( - &mut self, - _: &GoToPreviousTab, - window: &mut Window, - cx: &mut Context, - ) { - let count = Vim::take_count(cx); - Vim::take_forced_motion(cx); - - if let Some(count) = count { - // gT with count goes back that many tabs with wraparound (not the same as gt!). - if let Some(workspace) = self.workspace(window) { - let pane = workspace.read(cx).active_pane().read(cx); - let item_count = pane.items().count(); - if item_count > 0 { - let current_index = pane.active_item_index(); - let target_index = (current_index as isize - count as isize) - .rem_euclid(item_count as isize) - as usize; - window.dispatch_action( - workspace::pane::ActivateItem(target_index).boxed_clone(), - cx, - ); - } - } - } else { - // No count provided, go to the previous tab. - window.dispatch_action(workspace::pane::ActivatePreviousItem.boxed_clone(), cx); - } - } } + #[cfg(test)] mod test { use gpui::{KeyBinding, TestAppContext, UpdateGlobal}; diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index c9ca7cb325a99b..60ff63a5bedb69 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -51,7 +51,10 @@ use vim_mode_setting::HelixModeSetting; use vim_mode_setting::VimModeSetting; use workspace::{self, Pane, Workspace}; -use crate::state::ReplayableAction; +use crate::{ + normal::{GoToPreviousTab, GoToTab}, + state::ReplayableAction, +}; /// Number is used to manage vim's count. Pushing a digit /// multiplies the current value by 10 and adds the digit. @@ -409,6 +412,46 @@ pub fn init(cx: &mut App) { cx.defer_in(window, |vim, window, cx| vim.search_submit(window, cx)) }) }); + workspace.register_action(|workspace, _: &GoToTab, window, cx| { + let count = Vim::take_count(cx); + Vim::take_forced_motion(cx); + + if let Some(tab_index) = count { + // gt goes to tab (1-based). + let zero_based_index = tab_index.saturating_sub(1); + window.dispatch_action( + workspace::pane::ActivateItem(zero_based_index).boxed_clone(), + cx, + ); + } else { + // If no count is provided, go to the next tab. + window.dispatch_action(workspace::pane::ActivateNextItem.boxed_clone(), cx); + } + }); + + workspace.register_action(|workspace, _: &GoToPreviousTab, window, cx| { + let count = Vim::take_count(cx); + Vim::take_forced_motion(cx); + + if let Some(count) = count { + // gT with count goes back that many tabs with wraparound (not the same as gt!). + let pane = workspace.active_pane().read(cx); + let item_count = pane.items().count(); + if item_count > 0 { + let current_index = pane.active_item_index(); + let target_index = (current_index as isize - count as isize) + .rem_euclid(item_count as isize) + as usize; + window.dispatch_action( + workspace::pane::ActivateItem(target_index).boxed_clone(), + cx, + ); + } + } else { + // No count provided, go to the previous tab. + window.dispatch_action(workspace::pane::ActivatePreviousItem.boxed_clone(), cx); + } + }); }) .detach(); }