diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index 87a2c5132fb543..81c03128cf5c13 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -432,14 +432,14 @@ "ctrl-alt-s": "workspace::SaveAll", "ctrl-k m": "language_selector::Toggle", "escape": "workspace::Unfollow", - "ctrl-k ctrl-left": ["workspace::ActivatePaneInDirection", "Left"], - "ctrl-k ctrl-right": ["workspace::ActivatePaneInDirection", "Right"], - "ctrl-k ctrl-up": ["workspace::ActivatePaneInDirection", "Up"], - "ctrl-k ctrl-down": ["workspace::ActivatePaneInDirection", "Down"], - "ctrl-k shift-left": ["workspace::SwapPaneInDirection", "Left"], - "ctrl-k shift-right": ["workspace::SwapPaneInDirection", "Right"], - "ctrl-k shift-up": ["workspace::SwapPaneInDirection", "Up"], - "ctrl-k shift-down": ["workspace::SwapPaneInDirection", "Down"], + "ctrl-k ctrl-left": "workspace::ActivatePaneLeft", + "ctrl-k ctrl-right": "workspace::ActivatePaneRight", + "ctrl-k ctrl-up": "workspace::ActivatePaneUp", + "ctrl-k ctrl-down": "workspace::ActivatePaneDown", + "ctrl-k shift-left": "workspace::SwapPaneLeft", + "ctrl-k shift-right": "workspace::SwapPaneRight", + "ctrl-k shift-up": "workspace::SwapPaneUp", + "ctrl-k shift-down": "workspace::SwapPaneDown", "ctrl-shift-x": "zed::Extensions", "ctrl-shift-r": "task::Rerun", "ctrl-alt-r": "task::Rerun", @@ -453,8 +453,8 @@ { "context": "ApplicationMenu", "bindings": { - "left": ["app_menu::NavigateApplicationMenuInDirection", "Left"], - "right": ["app_menu::NavigateApplicationMenuInDirection", "Right"] + "left": "app_menu::ActivateMenuLeft", + "right": "app_menu::ActivateMenuRight" } }, // Bindings from Sublime Text diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index 86a761c0ec1876..1c4b7cff6e7ce8 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -509,14 +509,14 @@ "cmd-alt-s": "workspace::SaveAll", "cmd-k m": "language_selector::Toggle", "escape": "workspace::Unfollow", - "cmd-k cmd-left": ["workspace::ActivatePaneInDirection", "Left"], - "cmd-k cmd-right": ["workspace::ActivatePaneInDirection", "Right"], - "cmd-k cmd-up": ["workspace::ActivatePaneInDirection", "Up"], - "cmd-k cmd-down": ["workspace::ActivatePaneInDirection", "Down"], - "cmd-k shift-left": ["workspace::SwapPaneInDirection", "Left"], - "cmd-k shift-right": ["workspace::SwapPaneInDirection", "Right"], - "cmd-k shift-up": ["workspace::SwapPaneInDirection", "Up"], - "cmd-k shift-down": ["workspace::SwapPaneInDirection", "Down"], + "cmd-k cmd-left": "workspace::ActivatePaneLeft", + "cmd-k cmd-right": "workspace::ActivatePaneRight", + "cmd-k cmd-up": "workspace::ActivatePaneUp", + "cmd-k cmd-down": "workspace::ActivatePaneDown", + "cmd-k shift-left": "workspace::SwapPaneLeft", + "cmd-k shift-right": "workspace::SwapPaneRight", + "cmd-k shift-up": "workspace::SwapPaneUp", + "cmd-k shift-down": "workspace::SwapPaneDown", "cmd-shift-x": "zed::Extensions" } }, diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 7c3e8b66c08804..1703eb52889e42 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -2,8 +2,8 @@ { "context": "VimControl && !menu", "bindings": { - "i": ["vim::PushOperator", { "Object": { "around": false } }], - "a": ["vim::PushOperator", { "Object": { "around": true } }], + "i": ["vim::PushObject", { "around": false }], + "a": ["vim::PushObject", { "around": true }], "left": "vim::Left", "h": "vim::Left", "backspace": "vim::Backspace", @@ -54,10 +54,10 @@ // "b": "vim::PreviousSubwordStart", // "e": "vim::NextSubwordEnd", // "g e": "vim::PreviousSubwordEnd", - "shift-w": ["vim::NextWordStart", { "ignorePunctuation": true }], - "shift-e": ["vim::NextWordEnd", { "ignorePunctuation": true }], - "shift-b": ["vim::PreviousWordStart", { "ignorePunctuation": true }], - "g shift-e": ["vim::PreviousWordEnd", { "ignorePunctuation": true }], + "shift-w": ["vim::NextWordStart", { "ignore_punctuation": true }], + "shift-e": ["vim::NextWordEnd", { "ignore_punctuation": true }], + "shift-b": ["vim::PreviousWordStart", { "ignore_punctuation": true }], + "g shift-e": ["vim::PreviousWordEnd", { "ignore_punctuation": true }], "/": "vim::Search", "g /": "pane::DeploySearch", "?": ["vim::Search", { "backwards": true }], @@ -70,20 +70,20 @@ "[ {": ["vim::UnmatchedBackward", { "char": "{" }], "] )": ["vim::UnmatchedForward", { "char": ")" }], "[ (": ["vim::UnmatchedBackward", { "char": "(" }], - "f": ["vim::PushOperator", { "FindForward": { "before": false } }], - "t": ["vim::PushOperator", { "FindForward": { "before": true } }], - "shift-f": ["vim::PushOperator", { "FindBackward": { "after": false } }], - "shift-t": ["vim::PushOperator", { "FindBackward": { "after": true } }], - "m": ["vim::PushOperator", "Mark"], - "'": ["vim::PushOperator", { "Jump": { "line": true } }], - "`": ["vim::PushOperator", { "Jump": { "line": false } }], + "f": ["vim::PushFindForward", { "before": false }], + "t": ["vim::PushFindForward", { "before": true }], + "shift-f": ["vim::PushFindBackward", { "after": false }], + "shift-t": ["vim::PushFindBackward", { "after": true }], + "m": "vim::PushMark", + "'": ["vim::PushJump", { "line": true }], + "`": ["vim::PushJump", { "line": false }], ";": "vim::RepeatFind", ",": "vim::RepeatFindReversed", "ctrl-o": "pane::GoBack", "ctrl-i": "pane::GoForward", "ctrl-]": "editor::GoToDefinition", - "escape": ["vim::SwitchMode", "Normal"], - "ctrl-[": ["vim::SwitchMode", "Normal"], + "escape": "vim::SwitchToNormalMode", + "ctrl-[": "vim::SwitchToNormalMode", "v": "vim::ToggleVisual", "shift-v": "vim::ToggleVisualLine", "ctrl-g": "vim::ShowLocation", @@ -124,17 +124,17 @@ "g .": "editor::ToggleCodeActions", // zed specific "g shift-a": "editor::FindAllReferences", // zed specific "g space": "editor::OpenExcerpts", // zed specific - "g *": ["vim::MoveToNext", { "partialWord": true }], - "g #": ["vim::MoveToPrev", { "partialWord": true }], - "g j": ["vim::Down", { "displayLines": true }], - "g down": ["vim::Down", { "displayLines": true }], - "g k": ["vim::Up", { "displayLines": true }], - "g up": ["vim::Up", { "displayLines": true }], - "g $": ["vim::EndOfLine", { "displayLines": true }], - "g end": ["vim::EndOfLine", { "displayLines": true }], - "g 0": ["vim::StartOfLine", { "displayLines": true }], - "g home": ["vim::StartOfLine", { "displayLines": true }], - "g ^": ["vim::FirstNonWhitespace", { "displayLines": true }], + "g *": ["vim::MoveToNext", { "partial_word": true }], + "g #": ["vim::MoveToPrev", { "partial_word": true }], + "g j": ["vim::Down", { "display_lines": true }], + "g down": ["vim::Down", { "display_lines": true }], + "g k": ["vim::Up", { "display_lines": true }], + "g up": ["vim::Up", { "display_lines": true }], + "g $": ["vim::EndOfLine", { "display_lines": true }], + "g end": ["vim::EndOfLine", { "display_lines": true }], + "g 0": ["vim::StartOfLine", { "display_lines": true }], + "g home": ["vim::StartOfLine", { "display_lines": true }], + "g ^": ["vim::FirstNonWhitespace", { "display_lines": true }], "g v": "vim::RestoreVisualSelection", "g ]": "editor::GoToDiagnostic", "g [": "editor::GoToPrevDiagnostic", @@ -146,7 +146,7 @@ "shift-l": "vim::WindowBottom", "q": "vim::ToggleRecord", "shift-q": "vim::ReplayLastRecording", - "@": ["vim::PushOperator", "ReplayRegister"], + "@": "vim::PushReplayRegister", // z commands "z enter": ["workspace::SendKeystrokes", "z t ^"], "z -": ["workspace::SendKeystrokes", "z b ^"], @@ -165,8 +165,8 @@ "z f": "editor::FoldSelectedRanges", "z shift-m": "editor::FoldAll", "z shift-r": "editor::UnfoldAll", - "shift-z shift-q": ["pane::CloseActiveItem", { "saveIntent": "skip" }], - "shift-z shift-z": ["pane::CloseActiveItem", { "saveIntent": "saveAll" }], + "shift-z shift-q": ["pane::CloseActiveItem", { "save_intent": "skip" }], + "shift-z shift-z": ["pane::CloseActiveItem", { "save_intent": "save_all" }], // Count support "1": ["vim::Number", 1], "2": ["vim::Number", 2], @@ -193,13 +193,13 @@ "escape": "editor::Cancel", ":": "command_palette::Toggle", ".": "vim::Repeat", - "c": ["vim::PushOperator", "Change"], + "c": "vim::PushChange", "shift-c": "vim::ChangeToEndOfLine", - "d": ["vim::PushOperator", "Delete"], + "d": "vim::PushDelete", "shift-d": "vim::DeleteToEndOfLine", "shift-j": "vim::JoinLines", "g shift-j": "vim::JoinLinesNoWhitespace", - "y": ["vim::PushOperator", "Yank"], + "y": "vim::PushYank", "shift-y": "vim::YankLine", "i": "vim::InsertBefore", "shift-i": "vim::InsertFirstNonWhitespace", @@ -216,19 +216,19 @@ "shift-p": ["vim::Paste", { "before": true }], "u": "vim::Undo", "ctrl-r": "vim::Redo", - "r": ["vim::PushOperator", "Replace"], + "r": "vim::PushReplace", "s": "vim::Substitute", "shift-s": "vim::SubstituteLine", - ">": ["vim::PushOperator", "Indent"], - "<": ["vim::PushOperator", "Outdent"], - "=": ["vim::PushOperator", "AutoIndent"], - "!": ["vim::PushOperator", "ShellCommand"], - "g u": ["vim::PushOperator", "Lowercase"], - "g shift-u": ["vim::PushOperator", "Uppercase"], - "g ~": ["vim::PushOperator", "OppositeCase"], - "\"": ["vim::PushOperator", "Register"], - "g w": ["vim::PushOperator", "Rewrap"], - "g q": ["vim::PushOperator", "Rewrap"], + ">": "vim::PushIndent", + "<": "vim::PushOutdent", + "=": "vim::PushAutoIndent", + "!": "vim::PushShellCommand", + "g u": "vim::PushLowercase", + "g shift-u": "vim::PushUppercase", + "g ~": "vim::PushOppositeCase", + "\"": "vim::PushRegister", + "g w": "vim::PushRewrap", + "g q": "vim::PushRewrap", "ctrl-pagedown": "pane::ActivateNextItem", "ctrl-pageup": "pane::ActivatePrevItem", "insert": "vim::InsertBefore", @@ -239,7 +239,7 @@ "[ d": "editor::GoToPrevDiagnostic", "] c": "editor::GoToHunk", "[ c": "editor::GoToPrevHunk", - "g c": ["vim::PushOperator", "ToggleComments"] + "g c": "vim::PushToggleComments" } }, { @@ -264,14 +264,14 @@ "y": "vim::VisualYank", "shift-y": "vim::VisualYankLine", "p": "vim::Paste", - "shift-p": ["vim::Paste", { "preserveClipboard": true }], + "shift-p": ["vim::Paste", { "preserve_clipboard": true }], "c": "vim::Substitute", "s": "vim::Substitute", "shift-r": "vim::SubstituteLine", "shift-s": "vim::SubstituteLine", "~": "vim::ChangeCase", - "*": ["vim::MoveToNext", { "partialWord": true }], - "#": ["vim::MoveToPrev", { "partialWord": true }], + "*": ["vim::MoveToNext", { "partial_word": true }], + "#": ["vim::MoveToPrev", { "partial_word": true }], "ctrl-a": "vim::Increment", "ctrl-x": "vim::Decrement", "g ctrl-a": ["vim::Increment", { "step": true }], @@ -282,19 +282,19 @@ "g shift-a": "vim::VisualInsertEndOfLine", "shift-j": "vim::JoinLines", "g shift-j": "vim::JoinLinesNoWhitespace", - "r": ["vim::PushOperator", "Replace"], - "ctrl-c": ["vim::SwitchMode", "Normal"], - "ctrl-[": ["vim::SwitchMode", "Normal"], - "escape": ["vim::SwitchMode", "Normal"], + "r": "vim::PushReplace", + "ctrl-c": "vim::SwitchToNormalMode", + "ctrl-[": "vim::SwitchToNormalMode", + "escape": "vim::SwitchToNormalMode", ">": "vim::Indent", "<": "vim::Outdent", "=": "vim::AutoIndent", "!": "vim::ShellCommand", - "i": ["vim::PushOperator", { "Object": { "around": false } }], - "a": ["vim::PushOperator", { "Object": { "around": true } }], + "i": ["vim::PushObject", { "around": false }], + "a": ["vim::PushObject", { "around": true }], "g c": "vim::ToggleComments", "g q": "vim::Rewrap", - "\"": ["vim::PushOperator", "Register"], + "\"": "vim::PushRegister", // tree-sitter related commands "[ x": "editor::SelectLargerSyntaxNode", "] x": "editor::SelectSmallerSyntaxNode" @@ -316,12 +316,12 @@ "ctrl-u": "editor::DeleteToBeginningOfLine", "ctrl-t": "vim::Indent", "ctrl-d": "vim::Outdent", - "ctrl-k": ["vim::PushOperator", { "Digraph": {} }], - "ctrl-v": ["vim::PushOperator", { "Literal": {} }], + "ctrl-k": ["vim::PushDigraph", {}], + "ctrl-v": ["vim::PushLiteral", {}], "ctrl-shift-v": "editor::Paste", // note: this is *very* similar to ctrl-v in vim, but ctrl-shift-v on linux is the typical shortcut for paste when ctrl-v is already in use. - "ctrl-q": ["vim::PushOperator", { "Literal": {} }], - "ctrl-shift-q": ["vim::PushOperator", { "Literal": {} }], - "ctrl-r": ["vim::PushOperator", "Register"], + "ctrl-q": ["vim::PushLiteral", {}], + "ctrl-shift-q": ["vim::PushLiteral", {}], + "ctrl-r": "vim::PushRegister", "insert": "vim::ToggleReplace", "ctrl-o": "vim::TemporaryNormal" } @@ -356,11 +356,11 @@ "ctrl-c": "vim::NormalBefore", "ctrl-[": "vim::NormalBefore", "escape": "vim::NormalBefore", - "ctrl-k": ["vim::PushOperator", { "Digraph": {} }], - "ctrl-v": ["vim::PushOperator", { "Literal": {} }], + "ctrl-k": ["vim::PushDigraph", {}], + "ctrl-v": ["vim::PushLiteral", {}], "ctrl-shift-v": "editor::Paste", // note: this is *very* similar to ctrl-v in vim, but ctrl-shift-v on linux is the typical shortcut for paste when ctrl-v is already in use. - "ctrl-q": ["vim::PushOperator", { "Literal": {} }], - "ctrl-shift-q": ["vim::PushOperator", { "Literal": {} }], + "ctrl-q": ["vim::PushLiteral", {}], + "ctrl-shift-q": ["vim::PushLiteral", {}], "backspace": "vim::UndoReplace", "tab": "vim::Tab", "enter": "vim::Enter", @@ -375,9 +375,9 @@ "ctrl-c": "vim::ClearOperators", "ctrl-[": "vim::ClearOperators", "escape": "vim::ClearOperators", - "ctrl-k": ["vim::PushOperator", { "Digraph": {} }], - "ctrl-v": ["vim::PushOperator", { "Literal": {} }], - "ctrl-q": ["vim::PushOperator", { "Literal": {} }] + "ctrl-k": ["vim::PushDigraph", {}], + "ctrl-v": ["vim::PushLiteral", {}], + "ctrl-q": ["vim::PushLiteral", {}] } }, { @@ -393,10 +393,10 @@ "context": "vim_operator == a || vim_operator == i || vim_operator == cs", "bindings": { "w": "vim::Word", - "shift-w": ["vim::Word", { "ignorePunctuation": true }], + "shift-w": ["vim::Word", { "ignore_punctuation": true }], // Subword TextObject // "w": "vim::Subword", - // "shift-w": ["vim::Subword", { "ignorePunctuation": true }], + // "shift-w": ["vim::Subword", { "ignore_punctuation": true }], "t": "vim::Tag", "s": "vim::Sentence", "p": "vim::Paragraph", @@ -419,7 +419,7 @@ ">": "vim::AngleBrackets", "a": "vim::Argument", "i": "vim::IndentObj", - "shift-i": ["vim::IndentObj", { "includeBelow": true }], + "shift-i": ["vim::IndentObj", { "include_below": true }], "f": "vim::Method", "c": "vim::Class" } @@ -429,14 +429,14 @@ "bindings": { "c": "vim::CurrentLine", "d": "editor::Rename", // zed specific - "s": ["vim::PushOperator", { "ChangeSurrounds": {} }] + "s": ["vim::PushChangeSurrounds", {}] } }, { "context": "vim_operator == d", "bindings": { "d": "vim::CurrentLine", - "s": ["vim::PushOperator", "DeleteSurrounds"], + "s": "vim::PushDeleteSurrounds", "o": "editor::ToggleSelectedDiffHunks", // "d o" "p": "editor::RevertSelectedHunks" // "d p" } @@ -475,7 +475,7 @@ "context": "vim_operator == y", "bindings": { "y": "vim::CurrentLine", - "s": ["vim::PushOperator", { "AddSurrounds": {} }] + "s": ["vim::PushAddSurrounds", {}] } }, { @@ -569,30 +569,30 @@ "bindings": { // window related commands (ctrl-w X) "ctrl-w": null, - "ctrl-w left": ["workspace::ActivatePaneInDirection", "Left"], - "ctrl-w right": ["workspace::ActivatePaneInDirection", "Right"], - "ctrl-w up": ["workspace::ActivatePaneInDirection", "Up"], - "ctrl-w down": ["workspace::ActivatePaneInDirection", "Down"], - "ctrl-w ctrl-h": ["workspace::ActivatePaneInDirection", "Left"], - "ctrl-w ctrl-l": ["workspace::ActivatePaneInDirection", "Right"], - "ctrl-w ctrl-k": ["workspace::ActivatePaneInDirection", "Up"], - "ctrl-w ctrl-j": ["workspace::ActivatePaneInDirection", "Down"], - "ctrl-w h": ["workspace::ActivatePaneInDirection", "Left"], - "ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"], - "ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"], - "ctrl-w j": ["workspace::ActivatePaneInDirection", "Down"], - "ctrl-w shift-left": ["workspace::SwapPaneInDirection", "Left"], - "ctrl-w shift-right": ["workspace::SwapPaneInDirection", "Right"], - "ctrl-w shift-up": ["workspace::SwapPaneInDirection", "Up"], - "ctrl-w shift-down": ["workspace::SwapPaneInDirection", "Down"], - "ctrl-w shift-h": ["workspace::SwapPaneInDirection", "Left"], - "ctrl-w shift-l": ["workspace::SwapPaneInDirection", "Right"], - "ctrl-w shift-k": ["workspace::SwapPaneInDirection", "Up"], - "ctrl-w shift-j": ["workspace::SwapPaneInDirection", "Down"], - "ctrl-w >": ["vim::ResizePane", "Widen"], - "ctrl-w <": ["vim::ResizePane", "Narrow"], - "ctrl-w -": ["vim::ResizePane", "Shorten"], - "ctrl-w +": ["vim::ResizePane", "Lengthen"], + "ctrl-w left": "workspace::ActivatePaneLeft", + "ctrl-w right": "workspace::ActivatePaneRight", + "ctrl-w up": "workspace::ActivatePaneUp", + "ctrl-w down": "workspace::ActivatePaneDown", + "ctrl-w ctrl-h": "workspace::ActivatePaneLeft", + "ctrl-w ctrl-l": "workspace::ActivatePaneRight", + "ctrl-w ctrl-k": "workspace::ActivatePaneUp", + "ctrl-w ctrl-j": "workspace::ActivatePaneDown", + "ctrl-w h": "workspace::ActivatePaneLeft", + "ctrl-w l": "workspace::ActivatePaneRight", + "ctrl-w k": "workspace::ActivatePaneUp", + "ctrl-w j": "workspace::ActivatePaneDown", + "ctrl-w shift-left": "workspace::SwapPaneLeft", + "ctrl-w shift-right": "workspace::SwapPaneRight", + "ctrl-w shift-up": "workspace::SwapPaneUp", + "ctrl-w shift-down": "workspace::SwapPaneDown", + "ctrl-w shift-h": "workspace::SwapPaneLeft", + "ctrl-w shift-l": "workspace::SwapPaneRight", + "ctrl-w shift-k": "workspace::SwapPaneUp", + "ctrl-w shift-j": "workspace::SwapPaneDown", + "ctrl-w >": "vim::ResizePaneRight", + "ctrl-w <": "vim::ResizePaneLeft", + "ctrl-w -": "vim::ResizePaneDown", + "ctrl-w +": "vim::ResizePaneUp", "ctrl-w _": "vim::MaximizePane", "ctrl-w =": "vim::ResetPaneSizes", "ctrl-w g t": "pane::ActivateNextItem", diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index f2e74b71f4e732..14a3e111b304a8 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -35,10 +35,11 @@ use workspace::{ item::SerializableItem, move_active_item, move_item, pane, ui::IconName, - ActivateNextPane, ActivatePane, ActivatePaneInDirection, ActivatePreviousPane, - DraggedSelection, DraggedTab, ItemId, MoveItemToPane, MoveItemToPaneInDirection, NewTerminal, - Pane, PaneGroup, SplitDirection, SplitDown, SplitLeft, SplitRight, SplitUp, - SwapPaneInDirection, ToggleZoom, Workspace, + ActivateNextPane, ActivatePane, ActivatePaneDown, ActivatePaneLeft, ActivatePaneRight, + ActivatePaneUp, ActivatePreviousPane, DraggedSelection, DraggedTab, ItemId, MoveItemToPane, + MoveItemToPaneInDirection, NewTerminal, Pane, PaneGroup, SplitDirection, SplitDown, SplitLeft, + SplitRight, SplitUp, SwapPaneDown, SwapPaneLeft, SwapPaneRight, SwapPaneUp, ToggleZoom, + Workspace, }; use anyhow::{anyhow, Context as _, Result}; @@ -889,6 +890,37 @@ impl TerminalPanel { is_enabled_in_workspace(workspace.read(cx), cx) }) } + + fn activate_pane_in_direction( + &mut self, + direction: SplitDirection, + window: &mut Window, + cx: &mut Context, + ) { + if let Some(pane) = self + .center + .find_pane_in_direction(&self.active_pane, direction, cx) + { + window.focus(&pane.focus_handle(cx)); + } else { + self.workspace + .update(cx, |workspace, cx| { + workspace.activate_pane_in_direction(direction, window, cx) + }) + .ok(); + } + } + + fn swap_pane_in_direction(&mut self, direction: SplitDirection, cx: &mut Context) { + if let Some(to) = self + .center + .find_pane_in_direction(&self.active_pane, direction, cx) + .cloned() + { + self.center.swap(&self.active_pane, &to); + cx.notify(); + } + } } fn is_enabled_in_workspace(workspace: &Workspace, cx: &App) -> bool { @@ -1145,24 +1177,28 @@ impl Render for TerminalPanel { .ok() .map(|div| { div.on_action({ - cx.listener( - |terminal_panel, action: &ActivatePaneInDirection, window, cx| { - if let Some(pane) = terminal_panel.center.find_pane_in_direction( - &terminal_panel.active_pane, - action.0, - cx, - ) { - window.focus(&pane.focus_handle(cx)); - } else { - terminal_panel - .workspace - .update(cx, |workspace, cx| { - workspace.activate_pane_in_direction(action.0, window, cx) - }) - .ok(); - } - }, - ) + cx.listener(|terminal_panel, _: &ActivatePaneLeft, window, cx| { + terminal_panel.activate_pane_in_direction(SplitDirection::Left, window, cx); + }) + }) + .on_action({ + cx.listener(|terminal_panel, _: &ActivatePaneRight, window, cx| { + terminal_panel.activate_pane_in_direction( + SplitDirection::Right, + window, + cx, + ); + }) + }) + .on_action({ + cx.listener(|terminal_panel, _: &ActivatePaneUp, window, cx| { + terminal_panel.activate_pane_in_direction(SplitDirection::Up, window, cx); + }) + }) + .on_action({ + cx.listener(|terminal_panel, _: &ActivatePaneDown, window, cx| { + terminal_panel.activate_pane_in_direction(SplitDirection::Down, window, cx); + }) }) .on_action( cx.listener(|terminal_panel, _action: &ActivateNextPane, window, cx| { @@ -1210,18 +1246,18 @@ impl Render for TerminalPanel { } }), ) - .on_action( - cx.listener(|terminal_panel, action: &SwapPaneInDirection, _, cx| { - if let Some(to) = terminal_panel - .center - .find_pane_in_direction(&terminal_panel.active_pane, action.0, cx) - .cloned() - { - terminal_panel.center.swap(&terminal_panel.active_pane, &to); - cx.notify(); - } - }), - ) + .on_action(cx.listener(|terminal_panel, _: &SwapPaneLeft, _, cx| { + terminal_panel.swap_pane_in_direction(SplitDirection::Left, cx); + })) + .on_action(cx.listener(|terminal_panel, _: &SwapPaneRight, _, cx| { + terminal_panel.swap_pane_in_direction(SplitDirection::Right, cx); + })) + .on_action(cx.listener(|terminal_panel, _: &SwapPaneUp, _, cx| { + terminal_panel.swap_pane_in_direction(SplitDirection::Up, cx); + })) + .on_action(cx.listener(|terminal_panel, _: &SwapPaneDown, _, cx| { + terminal_panel.swap_pane_in_direction(SplitDirection::Down, cx); + })) .on_action( cx.listener(|terminal_panel, action: &MoveItemToPane, window, cx| { let Some(&target_pane) = diff --git a/crates/title_bar/src/application_menu.rs b/crates/title_bar/src/application_menu.rs index eb4acfaf6732a3..955550596d69d3 100644 --- a/crates/title_bar/src/application_menu.rs +++ b/crates/title_bar/src/application_menu.rs @@ -1,19 +1,31 @@ -use gpui::{impl_actions, Entity, OwnedMenu, OwnedMenuItem}; +use gpui::{Entity, OwnedMenu, OwnedMenuItem}; + +#[cfg(not(target_os = "macos"))] +use gpui::{actions, impl_actions}; + +#[cfg(not(target_os = "macos"))] use schemars::JsonSchema; +#[cfg(not(target_os = "macos"))] use serde::Deserialize; + use smallvec::SmallVec; use ui::{prelude::*, ContextMenu, PopoverMenu, PopoverMenuHandle, Tooltip}; -impl_actions!( - app_menu, - [OpenApplicationMenu, NavigateApplicationMenuInDirection] -); +#[cfg(not(target_os = "macos"))] +impl_actions!(app_menu, [OpenApplicationMenu]); +#[cfg(not(target_os = "macos"))] +actions!(app_menu, [ActivateMenuRight, ActivateMenuLeft]); + +#[cfg(not(target_os = "macos"))] #[derive(Clone, Deserialize, JsonSchema, PartialEq, Default)] pub struct OpenApplicationMenu(String); -#[derive(Clone, Deserialize, JsonSchema, PartialEq, Default)] -pub struct NavigateApplicationMenuInDirection(String); +#[cfg(not(target_os = "macos"))] +pub enum ActivateDirection { + Left, + Right, +} #[derive(Clone)] struct MenuEntry { @@ -190,7 +202,7 @@ impl ApplicationMenu { #[cfg(not(target_os = "macos"))] pub fn navigate_menus_in_direction( &mut self, - action: &NavigateApplicationMenuInDirection, + direction: ActivateDirection, window: &mut Window, cx: &mut Context, ) { @@ -202,22 +214,21 @@ impl ApplicationMenu { return; }; - let next_index = match action.0.as_str() { - "Left" => { + let next_index = match direction { + ActivateDirection::Left => { if current_index == 0 { self.entries.len() - 1 } else { current_index - 1 } } - "Right" => { + ActivateDirection::Right => { if current_index == self.entries.len() - 1 { 0 } else { current_index + 1 } } - _ => return, }; self.entries[current_index].handle.hide(cx); diff --git a/crates/title_bar/src/title_bar.rs b/crates/title_bar/src/title_bar.rs index 7ed4d4609a048d..e9d9debb414f7a 100644 --- a/crates/title_bar/src/title_bar.rs +++ b/crates/title_bar/src/title_bar.rs @@ -9,7 +9,9 @@ mod stories; use crate::application_menu::ApplicationMenu; #[cfg(not(target_os = "macos"))] -use crate::application_menu::{NavigateApplicationMenuInDirection, OpenApplicationMenu}; +use crate::application_menu::{ + ActivateDirection, ActivateMenuLeft, ActivateMenuRight, OpenApplicationMenu, +}; use crate::platforms::{platform_linux, platform_mac, platform_windows}; use auto_update::AutoUpdateStatus; @@ -81,22 +83,36 @@ pub fn init(cx: &mut App) { }); #[cfg(not(target_os = "macos"))] - workspace.register_action( - |workspace, action: &NavigateApplicationMenuInDirection, window, cx| { - if let Some(titlebar) = workspace - .titlebar_item() - .and_then(|item| item.downcast::().ok()) - { - titlebar.update(cx, |titlebar, cx| { - if let Some(ref menu) = titlebar.application_menu { - menu.update(cx, |menu, cx| { - menu.navigate_menus_in_direction(action, window, cx) - }); - } - }); - } - }, - ); + workspace.register_action(|workspace, _: &ActivateMenuRight, window, cx| { + if let Some(titlebar) = workspace + .titlebar_item() + .and_then(|item| item.downcast::().ok()) + { + titlebar.update(cx, |titlebar, cx| { + if let Some(ref menu) = titlebar.application_menu { + menu.update(cx, |menu, cx| { + menu.navigate_menus_in_direction(ActivateDirection::Right, window, cx) + }); + } + }); + } + }); + + #[cfg(not(target_os = "macos"))] + workspace.register_action(|workspace, _: &ActivateMenuLeft, window, cx| { + if let Some(titlebar) = workspace + .titlebar_item() + .and_then(|item| item.downcast::().ok()) + { + titlebar.update(cx, |titlebar, cx| { + if let Some(ref menu) = titlebar.application_menu { + menu.update(cx, |menu, cx| { + menu.navigate_menus_in_direction(ActivateDirection::Left, window, cx) + }); + } + }); + } + }); }) .detach(); } diff --git a/crates/vim/src/motion.rs b/crates/vim/src/motion.rs index 96a5ef7454b72a..26cacde0d2bec4 100644 --- a/crates/vim/src/motion.rs +++ b/crates/vim/src/motion.rs @@ -141,105 +141,90 @@ pub enum Motion { } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct NextWordStart { #[serde(default)] ignore_punctuation: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct NextWordEnd { #[serde(default)] ignore_punctuation: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct PreviousWordStart { #[serde(default)] ignore_punctuation: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct PreviousWordEnd { #[serde(default)] ignore_punctuation: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] pub(crate) struct NextSubwordStart { #[serde(default)] pub(crate) ignore_punctuation: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] pub(crate) struct NextSubwordEnd { #[serde(default)] pub(crate) ignore_punctuation: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] pub(crate) struct PreviousSubwordStart { #[serde(default)] pub(crate) ignore_punctuation: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] pub(crate) struct PreviousSubwordEnd { #[serde(default)] pub(crate) ignore_punctuation: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] pub(crate) struct Up { #[serde(default)] pub(crate) display_lines: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] pub(crate) struct Down { #[serde(default)] pub(crate) display_lines: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct FirstNonWhitespace { #[serde(default)] display_lines: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct EndOfLine { #[serde(default)] display_lines: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] pub struct StartOfLine { #[serde(default)] pub(crate) display_lines: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct UnmatchedForward { #[serde(default)] char: char, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct UnmatchedBackward { #[serde(default)] char: char, diff --git a/crates/vim/src/normal/increment.rs b/crates/vim/src/normal/increment.rs index 36bcce1b8e2dab..ff1a4a6be8bbe2 100644 --- a/crates/vim/src/normal/increment.rs +++ b/crates/vim/src/normal/increment.rs @@ -8,14 +8,12 @@ use std::ops::Range; use crate::{state::Mode, Vim}; #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct Increment { #[serde(default)] step: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct Decrement { #[serde(default)] step: bool, diff --git a/crates/vim/src/normal/paste.rs b/crates/vim/src/normal/paste.rs index eb3acde6dc3982..84f7f175154b6a 100644 --- a/crates/vim/src/normal/paste.rs +++ b/crates/vim/src/normal/paste.rs @@ -11,7 +11,6 @@ use crate::{ }; #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] pub struct Paste { #[serde(default)] before: bool, diff --git a/crates/vim/src/normal/search.rs b/crates/vim/src/normal/search.rs index 948141c4e7577b..fe0ecebf5cf8b7 100644 --- a/crates/vim/src/normal/search.rs +++ b/crates/vim/src/normal/search.rs @@ -16,7 +16,6 @@ use crate::{ }; #[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] pub(crate) struct MoveToNext { #[serde(default = "default_true")] case_sensitive: bool, @@ -27,7 +26,6 @@ pub(crate) struct MoveToNext { } #[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] pub(crate) struct MoveToPrev { #[serde(default = "default_true")] case_sensitive: bool, diff --git a/crates/vim/src/object.rs b/crates/vim/src/object.rs index d59d59a26ea5c0..caac6b0ee59e2d 100644 --- a/crates/vim/src/object.rs +++ b/crates/vim/src/object.rs @@ -19,6 +19,7 @@ use serde::Deserialize; use ui::Context; #[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] pub enum Object { Word { ignore_punctuation: bool }, Subword { ignore_punctuation: bool }, @@ -43,20 +44,17 @@ pub enum Object { } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct Word { #[serde(default)] ignore_punctuation: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct Subword { #[serde(default)] ignore_punctuation: bool, } #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -#[serde(rename_all = "camelCase")] struct IndentObj { #[serde(default)] include_below: bool, diff --git a/crates/vim/src/state.rs b/crates/vim/src/state.rs index ddd83f4666b759..4b941a4789e5e7 100644 --- a/crates/vim/src/state.rs +++ b/crates/vim/src/state.rs @@ -10,7 +10,6 @@ use gpui::{ Action, App, BorrowAppContext, ClipboardEntry, ClipboardItem, Entity, Global, WeakEntity, }; use language::Point; -use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings::{Settings, SettingsStore}; use std::borrow::BorrowMut; @@ -18,7 +17,7 @@ use std::{fmt::Display, ops::Range, sync::Arc}; use ui::{Context, SharedString}; use workspace::searchable::Direction; -#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, JsonSchema, Serialize)] +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] pub enum Mode { Normal, Insert, @@ -59,7 +58,7 @@ impl Default for Mode { } } -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, JsonSchema)] +#[derive(Clone, Debug, PartialEq)] pub enum Operator { Change, Delete, @@ -82,7 +81,6 @@ pub enum Operator { }, AddSurrounds { // Typically no need to configure this as `SendKeystrokes` can be used - see #23088. - #[serde(skip)] target: Option, }, ChangeSurrounds { diff --git a/crates/vim/src/surrounds.rs b/crates/vim/src/surrounds.rs index fd774d6159a087..099c92e9b196c8 100644 --- a/crates/vim/src/surrounds.rs +++ b/crates/vim/src/surrounds.rs @@ -554,11 +554,7 @@ mod test { use gpui::KeyBinding; use indoc::indoc; - use crate::{ - state::{Mode, Operator}, - test::VimTestContext, - PushOperator, - }; + use crate::{state::Mode, test::VimTestContext, PushAddSurrounds}; #[gpui::test] async fn test_add_surrounds(cx: &mut gpui::TestAppContext) { @@ -749,7 +745,7 @@ mod test { cx.update(|_, cx| { cx.bind_keys([KeyBinding::new( "shift-s", - PushOperator(Operator::AddSurrounds { target: None }), + PushAddSurrounds, Some("vim_mode == visual"), )]) }); diff --git a/crates/vim/src/test.rs b/crates/vim/src/test.rs index 34ae719fbf22df..6c336375ae65cb 100644 --- a/crates/vim/src/test.rs +++ b/crates/vim/src/test.rs @@ -17,12 +17,7 @@ use indoc::indoc; use search::BufferSearchBar; use workspace::WorkspaceSettings; -use crate::{ - insert::NormalBefore, - motion, - state::{Mode, Operator}, - PushOperator, -}; +use crate::{insert::NormalBefore, motion, state::Mode, PushSneak, PushSneakBackward}; #[gpui::test] async fn test_initially_disabled(cx: &mut gpui::TestAppContext) { @@ -1347,17 +1342,17 @@ async fn test_sneak(cx: &mut gpui::TestAppContext) { cx.bind_keys([ KeyBinding::new( "s", - PushOperator(Operator::Sneak { first_char: None }), + PushSneak { first_char: None }, Some("vim_mode == normal"), ), KeyBinding::new( "S", - PushOperator(Operator::SneakBackward { first_char: None }), + PushSneakBackward { first_char: None }, Some("vim_mode == normal"), ), KeyBinding::new( "S", - PushOperator(Operator::SneakBackward { first_char: None }), + PushSneakBackward { first_char: None }, Some("vim_mode == visual"), ), ]) diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index be54fed0842768..bd6eff599669e7 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -34,6 +34,7 @@ use language::{CursorShape, Point, Selection, SelectionGoal, TransactionId}; pub use mode_indicator::ModeIndicator; use motion::Motion; use normal::search::SearchSubmit; +use object::Object; use schemars::JsonSchema; use serde::Deserialize; use serde_derive::Serialize; @@ -44,55 +45,124 @@ use surrounds::SurroundsType; use theme::ThemeSettings; use ui::{px, IntoElement, SharedString}; use vim_mode_setting::VimModeSetting; -use workspace::{self, Pane, ResizeIntent, Workspace}; +use workspace::{self, Pane, Workspace}; use crate::state::ReplayableAction; -/// Used to resize the current pane +/// Number is used to manage vim's count. Pushing a digit +/// multiplies the current value by 10 and adds the digit. #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -pub struct ResizePane(pub ResizeIntent); +struct Number(usize); -/// An Action to Switch between modes #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -pub struct SwitchMode(pub Mode); +struct SelectRegister(String); -/// PushOperator is used to put vim into a "minor" mode, -/// where it's waiting for a specific next set of keystrokes. -/// For example 'd' needs a motion to complete. #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -pub struct PushOperator(pub Operator); +struct PushObject { + around: bool, +} -/// Number is used to manage vim's count. Pushing a digit -/// multiplies the current value by 10 and adds the digit. #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -struct Number(usize); +struct PushFindForward { + before: bool, +} #[derive(Clone, Deserialize, JsonSchema, PartialEq)] -struct SelectRegister(String); +struct PushFindBackward { + after: bool, +} + +#[derive(Clone, Deserialize, JsonSchema, PartialEq)] +struct PushSneak { + first_char: Option, +} + +#[derive(Clone, Deserialize, JsonSchema, PartialEq)] +struct PushSneakBackward { + first_char: Option, +} + +#[derive(Clone, Deserialize, JsonSchema, PartialEq)] +struct PushChangeSurrounds { + target: Option, +} + +#[derive(Clone, Deserialize, JsonSchema, PartialEq)] +struct PushJump { + line: bool, +} + +#[derive(Clone, Deserialize, JsonSchema, PartialEq)] +struct PushDigraph { + first_char: Option, +} + +#[derive(Clone, Deserialize, JsonSchema, PartialEq)] +struct PushLiteral { + prefix: Option, +} actions!( vim, [ + SwitchToNormalMode, + SwitchToInsertMode, + SwitchToReplaceMode, + SwitchToVisualMode, + SwitchToVisualLineMode, + SwitchToVisualBlockMode, + SwitchToHelixNormalMode, ClearOperators, Tab, Enter, InnerObject, - FindForward, - FindBackward, MaximizePane, OpenDefaultKeymap, ResetPaneSizes, - Sneak, - SneakBackward, + ResizePaneRight, + ResizePaneLeft, + ResizePaneUp, + ResizePaneDown, + PushChange, + PushDelete, + PushYank, + PushReplace, + PushAddSurrounds, + PushDeleteSurrounds, + PushMark, + PushIndent, + PushOutdent, + PushAutoIndent, + PushRewrap, + PushShellCommand, + PushLowercase, + PushUppercase, + PushOppositeCase, + PushRegister, + PushRecordRegister, + PushReplayRegister, + PushToggleComments, ] ); // in the workspace namespace so it's not filtered out when vim is disabled. -actions!(workspace, [ToggleVimMode]); +actions!(workspace, [ToggleVimMode,]); impl_actions!( vim, - [ResizePane, SwitchMode, PushOperator, Number, SelectRegister] + [ + Number, + SelectRegister, + PushObject, + PushFindForward, + PushFindBackward, + PushSneak, + PushSneakBackward, + PushChangeSurrounds, + PushJump, + PushDigraph, + PushLiteral + ] ); /// Initializes the `vim` crate. @@ -141,7 +211,7 @@ pub fn init(cx: &mut App) { workspace.resize_pane(Axis::Vertical, desired_size - size.size.height, cx) }); - workspace.register_action(|workspace, action: &ResizePane, window, cx| { + workspace.register_action(|workspace, _: &ResizePaneRight, window, cx| { let count = Vim::take_count(cx).unwrap_or(1) as f32; let theme = ThemeSettings::get_global(cx); let Ok(font_id) = window.text_system().font_id(&theme.buffer_font) else { @@ -153,16 +223,36 @@ pub fn init(cx: &mut App) { else { return; }; - let height = theme.buffer_font_size() * theme.buffer_line_height.value(); + workspace.resize_pane(Axis::Horizontal, width.width * count, cx); + }); - let (axis, amount) = match action.0 { - ResizeIntent::Lengthen => (Axis::Vertical, height), - ResizeIntent::Shorten => (Axis::Vertical, height * -1.), - ResizeIntent::Widen => (Axis::Horizontal, width.width), - ResizeIntent::Narrow => (Axis::Horizontal, width.width * -1.), + workspace.register_action(|workspace, _: &ResizePaneLeft, window, cx| { + let count = Vim::take_count(cx).unwrap_or(1) as f32; + let theme = ThemeSettings::get_global(cx); + let Ok(font_id) = window.text_system().font_id(&theme.buffer_font) else { + return; + }; + let Ok(width) = window + .text_system() + .advance(font_id, theme.buffer_font_size(), 'm') + else { + return; }; + workspace.resize_pane(Axis::Horizontal, -width.width * count, cx); + }); - workspace.resize_pane(axis, amount * count, cx); + workspace.register_action(|workspace, _: &ResizePaneUp, _, cx| { + let count = Vim::take_count(cx).unwrap_or(1) as f32; + let theme = ThemeSettings::get_global(cx); + let height = theme.buffer_font_size() * theme.buffer_line_height.value(); + workspace.resize_pane(Axis::Vertical, height * count, cx); + }); + + workspace.register_action(|workspace, _: &ResizePaneDown, _, cx| { + let count = Vim::take_count(cx).unwrap_or(1) as f32; + let theme = ThemeSettings::get_global(cx); + let height = theme.buffer_font_size() * theme.buffer_line_height.value(); + workspace.resize_pane(Axis::Vertical, -height * count, cx); }); workspace.register_action(|workspace, _: &SearchSubmit, window, cx| { @@ -327,12 +417,204 @@ impl Vim { editor.register_addon(VimAddon { model: vim.clone() }); vim.update(cx, |_, cx| { - Vim::action(editor, cx, |vim, action: &SwitchMode, window, cx| { - vim.switch_mode(action.0, false, window, cx) + Vim::action(editor, cx, |vim, _: &SwitchToNormalMode, window, cx| { + vim.switch_mode(Mode::Normal, false, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &SwitchToInsertMode, window, cx| { + vim.switch_mode(Mode::Insert, false, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &SwitchToReplaceMode, window, cx| { + vim.switch_mode(Mode::Replace, false, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &SwitchToVisualMode, window, cx| { + vim.switch_mode(Mode::Visual, false, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &SwitchToVisualLineMode, window, cx| { + vim.switch_mode(Mode::VisualLine, false, window, cx) + }); + + Vim::action( + editor, + cx, + |vim, _: &SwitchToVisualBlockMode, window, cx| { + vim.switch_mode(Mode::VisualBlock, false, window, cx) + }, + ); + + Vim::action( + editor, + cx, + |vim, _: &SwitchToHelixNormalMode, window, cx| { + vim.switch_mode(Mode::HelixNormal, false, window, cx) + }, + ); + + Vim::action(editor, cx, |vim, action: &PushObject, window, cx| { + vim.push_operator( + Operator::Object { + around: action.around, + }, + window, + cx, + ) + }); + + Vim::action(editor, cx, |vim, action: &PushFindForward, window, cx| { + vim.push_operator( + Operator::FindForward { + before: action.before, + }, + window, + cx, + ) + }); + + Vim::action(editor, cx, |vim, action: &PushFindBackward, window, cx| { + vim.push_operator( + Operator::FindBackward { + after: action.after, + }, + window, + cx, + ) + }); + + Vim::action(editor, cx, |vim, action: &PushSneak, window, cx| { + vim.push_operator( + Operator::Sneak { + first_char: action.first_char, + }, + window, + cx, + ) + }); + + Vim::action(editor, cx, |vim, action: &PushSneakBackward, window, cx| { + vim.push_operator( + Operator::SneakBackward { + first_char: action.first_char, + }, + window, + cx, + ) + }); + + Vim::action( + editor, + cx, + |vim, action: &PushChangeSurrounds, window, cx| { + vim.push_operator( + Operator::ChangeSurrounds { + target: action.target, + }, + window, + cx, + ) + }, + ); + + Vim::action(editor, cx, |vim, action: &PushJump, window, cx| { + vim.push_operator(Operator::Jump { line: action.line }, window, cx) + }); + + Vim::action(editor, cx, |vim, action: &PushDigraph, window, cx| { + vim.push_operator( + Operator::Digraph { + first_char: action.first_char, + }, + window, + cx, + ) + }); + + Vim::action(editor, cx, |vim, action: &PushLiteral, window, cx| { + vim.push_operator( + Operator::Literal { + prefix: action.prefix.clone(), + }, + window, + cx, + ) + }); + + Vim::action(editor, cx, |vim, _: &PushChange, window, cx| { + vim.push_operator(Operator::Change, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushDelete, window, cx| { + vim.push_operator(Operator::Delete, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushYank, window, cx| { + vim.push_operator(Operator::Yank, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushReplace, window, cx| { + vim.push_operator(Operator::Replace, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushAddSurrounds, window, cx| { + vim.push_operator(Operator::AddSurrounds { target: None }, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushDeleteSurrounds, window, cx| { + vim.push_operator(Operator::DeleteSurrounds, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushMark, window, cx| { + vim.push_operator(Operator::Mark, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushIndent, window, cx| { + vim.push_operator(Operator::Indent, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushOutdent, window, cx| { + vim.push_operator(Operator::Outdent, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushAutoIndent, window, cx| { + vim.push_operator(Operator::AutoIndent, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushRewrap, window, cx| { + vim.push_operator(Operator::Rewrap, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushShellCommand, window, cx| { + vim.push_operator(Operator::ShellCommand, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushLowercase, window, cx| { + vim.push_operator(Operator::Lowercase, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushUppercase, window, cx| { + vim.push_operator(Operator::Uppercase, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushOppositeCase, window, cx| { + vim.push_operator(Operator::OppositeCase, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushRegister, window, cx| { + vim.push_operator(Operator::Register, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushRecordRegister, window, cx| { + vim.push_operator(Operator::RecordRegister, window, cx) + }); + + Vim::action(editor, cx, |vim, _: &PushReplayRegister, window, cx| { + vim.push_operator(Operator::ReplayRegister, window, cx) }); - Vim::action(editor, cx, |vim, action: &PushOperator, window, cx| { - vim.push_operator(action.0.clone(), window, cx) + Vim::action(editor, cx, |vim, _: &PushToggleComments, window, cx| { + vim.push_operator(Operator::ToggleComments, window, cx) }); Vim::action(editor, cx, |vim, _: &ClearOperators, window, cx| { diff --git a/crates/vim/test_data/test_command_replace.json b/crates/vim/test_data/test_command_replace.json index 698ef2a3bff162..df920aa4428de1 100644 --- a/crates/vim/test_data/test_command_replace.json +++ b/crates/vim/test_data/test_command_replace.json @@ -28,4 +28,4 @@ {"Key":"/"} {"Key":"ee"} {"Key":"enter"} -{"Get":{"state":"aa\ndd\nˇee\ncc", "mode":"Normal"}} \ No newline at end of file +{"Get":{"state":"aa\ndd\nˇee\ncc","mode":"Normal"}} diff --git a/crates/vim/test_data/test_increment_bin_wrapping_and_padding.json b/crates/vim/test_data/test_increment_bin_wrapping_and_padding.json index 4f1a6aa1d364b7..69c118c0adc0dc 100644 --- a/crates/vim/test_data/test_increment_bin_wrapping_and_padding.json +++ b/crates/vim/test_data/test_increment_bin_wrapping_and_padding.json @@ -1,10 +1,10 @@ {"Put":{"state":"0b111111111111111111111111111111111111111111111111111111111111111111111ˇ1\n"}} {"Key":"ctrl-a"} -{"Get":{"state":"0b000000111111111111111111111111111111111111111111111111111111111111111ˇ1\n", "mode":"Normal"}} +{"Get":{"state":"0b000000111111111111111111111111111111111111111111111111111111111111111ˇ1\n","mode":"Normal"}} {"Key":"ctrl-a"} {"Get":{"state":"0b000000000000000000000000000000000000000000000000000000000000000000000ˇ0\n","mode":"Normal"}} {"Key":"ctrl-a"} {"Get":{"state":"0b000000000000000000000000000000000000000000000000000000000000000000000ˇ1\n","mode":"Normal"}} {"Key":"2"} {"Key":"ctrl-x"} -{"Get":{"state":"0b000000111111111111111111111111111111111111111111111111111111111111111ˇ1\n", "mode":"Normal"}} +{"Get":{"state":"0b000000111111111111111111111111111111111111111111111111111111111111111ˇ1\n","mode":"Normal"}} diff --git a/crates/vim/test_data/test_increment_hex_wrapping_and_padding.json b/crates/vim/test_data/test_increment_hex_wrapping_and_padding.json index 23a561126487c6..562b368812c033 100644 --- a/crates/vim/test_data/test_increment_hex_wrapping_and_padding.json +++ b/crates/vim/test_data/test_increment_hex_wrapping_and_padding.json @@ -1,10 +1,10 @@ {"Put":{"state":"0xfffffffffffffffffffˇf\n"}} {"Key":"ctrl-a"} -{"Get":{"state":"0x0000fffffffffffffffˇf\n", "mode":"Normal"}} +{"Get":{"state":"0x0000fffffffffffffffˇf\n","mode":"Normal"}} {"Key":"ctrl-a"} {"Get":{"state":"0x0000000000000000000ˇ0\n","mode":"Normal"}} {"Key":"ctrl-a"} {"Get":{"state":"0x0000000000000000000ˇ1\n","mode":"Normal"}} {"Key":"2"} {"Key":"ctrl-x"} -{"Get":{"state":"0x0000fffffffffffffffˇf\n", "mode":"Normal"}} +{"Get":{"state":"0x0000fffffffffffffffˇf\n","mode":"Normal"}} diff --git a/crates/vim/test_data/test_increment_inline.json b/crates/vim/test_data/test_increment_inline.json index 98c4fc28052724..1e3d8fbd90efd5 100644 --- a/crates/vim/test_data/test_increment_inline.json +++ b/crates/vim/test_data/test_increment_inline.json @@ -2,9 +2,9 @@ {"Key":"ctrl-a"} {"Get":{"state":"inline0x3ˇau32\n","mode":"Normal"}} {"Key":"ctrl-a"} -{"Get":{"state":"inline0x3ˇbu32\n", "mode":"Normal"}} +{"Get":{"state":"inline0x3ˇbu32\n","mode":"Normal"}} {"Key":"l"} {"Key":"l"} {"Key":"l"} {"Key":"ctrl-a"} -{"Get":{"state":"inline0x3bu3ˇ3\n", "mode":"Normal"}} +{"Get":{"state":"inline0x3bu3ˇ3\n","mode":"Normal"}} diff --git a/crates/vim/test_data/test_increment_sign_change.json b/crates/vim/test_data/test_increment_sign_change.json index 1f4edd57b456af..8f2ee7f2f3d513 100644 --- a/crates/vim/test_data/test_increment_sign_change.json +++ b/crates/vim/test_data/test_increment_sign_change.json @@ -3,4 +3,4 @@ {"Get":{"state":"-ˇ1\n","mode":"Normal"}} {"Key":"2"} {"Key":"ctrl-a"} -{"Get":{"state":"ˇ1\n", "mode":"Normal"}} +{"Get":{"state":"ˇ1\n","mode":"Normal"}} diff --git a/crates/vim/test_data/test_increment_wrapping.json b/crates/vim/test_data/test_increment_wrapping.json index 9f84c8cb1145d4..9f189991a6ee67 100644 --- a/crates/vim/test_data/test_increment_wrapping.json +++ b/crates/vim/test_data/test_increment_wrapping.json @@ -2,12 +2,12 @@ {"Key":"ctrl-a"} {"Get":{"state":"1844674407370955161ˇ5\n","mode":"Normal"}} {"Key":"ctrl-a"} -{"Get":{"state":"-1844674407370955161ˇ5\n", "mode":"Normal"}} +{"Get":{"state":"-1844674407370955161ˇ5\n","mode":"Normal"}} {"Key":"ctrl-a"} -{"Get":{"state":"-1844674407370955161ˇ4\n", "mode":"Normal"}} +{"Get":{"state":"-1844674407370955161ˇ4\n","mode":"Normal"}} {"Key":"3"} {"Key":"ctrl-x"} -{"Get":{"state":"1844674407370955161ˇ4\n", "mode":"Normal"}} +{"Get":{"state":"1844674407370955161ˇ4\n","mode":"Normal"}} {"Key":"2"} {"Key":"ctrl-a"} -{"Get":{"state":"-1844674407370955161ˇ5\n", "mode":"Normal"}} +{"Get":{"state":"-1844674407370955161ˇ5\n","mode":"Normal"}} diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 098faf8897e808..5ccd7808c9a6a5 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -72,7 +72,7 @@ impl DraggedSelection { } #[derive(Clone, Copy, PartialEq, Debug, Deserialize, JsonSchema)] -#[serde(rename_all = "camelCase")] +#[serde(rename_all = "snake_case")] pub enum SaveIntent { /// write all files (even if unchanged) /// prompt before overwriting on-disk changes @@ -96,13 +96,11 @@ pub enum SaveIntent { pub struct ActivateItem(pub usize); #[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)] -#[serde(rename_all = "camelCase")] pub struct CloseActiveItem { pub save_intent: Option, } #[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)] -#[serde(rename_all = "camelCase")] pub struct CloseInactiveItems { pub save_intent: Option, #[serde(default)] @@ -110,7 +108,6 @@ pub struct CloseInactiveItems { } #[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)] -#[serde(rename_all = "camelCase")] pub struct CloseAllItems { pub save_intent: Option, #[serde(default)] @@ -118,28 +115,24 @@ pub struct CloseAllItems { } #[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)] -#[serde(rename_all = "camelCase")] pub struct CloseCleanItems { #[serde(default)] pub close_pinned: bool, } #[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)] -#[serde(rename_all = "camelCase")] pub struct CloseItemsToTheRight { #[serde(default)] pub close_pinned: bool, } #[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)] -#[serde(rename_all = "camelCase")] pub struct CloseItemsToTheLeft { #[serde(default)] pub close_pinned: bool, } #[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)] -#[serde(rename_all = "camelCase")] pub struct RevealInProjectPanel { #[serde(skip)] pub entry_id: Option, diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index 7409dead145123..0b2cc55e3bc337 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -725,6 +725,7 @@ impl PaneAxis { } #[derive(Clone, Copy, Debug, Deserialize, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] pub enum SplitDirection { Up, Down, @@ -807,14 +808,6 @@ impl SplitDirection { } } -#[derive(Clone, Copy, Debug, Deserialize, JsonSchema, PartialEq)] -pub enum ResizeIntent { - Lengthen, - Shorten, - Widen, - Narrow, -} - mod element { use std::mem; use std::{cell::RefCell, iter, rc::Rc, sync::Arc}; diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 89bcd53d6d9f67..b13455c5edf3b0 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -168,12 +168,6 @@ pub struct OpenPaths { #[derive(Clone, Deserialize, PartialEq, JsonSchema)] pub struct ActivatePane(pub usize); -#[derive(Clone, Deserialize, PartialEq, JsonSchema)] -pub struct ActivatePaneInDirection(pub SplitDirection); - -#[derive(Clone, Deserialize, PartialEq, JsonSchema)] -pub struct SwapPaneInDirection(pub SplitDirection); - #[derive(Clone, Deserialize, PartialEq, JsonSchema)] pub struct MoveItemToPane { pub destination: usize, @@ -189,25 +183,21 @@ pub struct MoveItemToPaneInDirection { } #[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema)] -#[serde(rename_all = "camelCase")] pub struct SaveAll { pub save_intent: Option, } #[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema)] -#[serde(rename_all = "camelCase")] pub struct Save { pub save_intent: Option, } #[derive(Clone, PartialEq, Debug, Deserialize, Default, JsonSchema)] -#[serde(rename_all = "camelCase")] pub struct CloseAllItemsAndPanes { pub save_intent: Option, } #[derive(Clone, PartialEq, Debug, Deserialize, Default, JsonSchema)] -#[serde(rename_all = "camelCase")] pub struct CloseInactiveTabsAndPanes { pub save_intent: Option, } @@ -234,7 +224,6 @@ impl_actions!( workspace, [ ActivatePane, - ActivatePaneInDirection, CloseAllItemsAndPanes, CloseInactiveTabsAndPanes, MoveItemToPane, @@ -243,11 +232,24 @@ impl_actions!( Reload, Save, SaveAll, - SwapPaneInDirection, SendKeystrokes, ] ); +actions!( + workspace, + [ + ActivatePaneLeft, + ActivatePaneRight, + ActivatePaneUp, + ActivatePaneDown, + SwapPaneLeft, + SwapPaneRight, + SwapPaneUp, + SwapPaneDown, + ] +); + #[derive(PartialEq, Eq, Debug)] pub enum CloseIntent { /// Quit the program entirely. @@ -4800,29 +4802,38 @@ impl Workspace { workspace.activate_previous_window(cx) }), ) - .on_action( - cx.listener(|workspace, action: &ActivatePaneInDirection, window, cx| { - workspace.activate_pane_in_direction(action.0, window, cx) - }), - ) + .on_action(cx.listener(|workspace, _: &ActivatePaneLeft, window, cx| { + workspace.activate_pane_in_direction(SplitDirection::Left, window, cx) + })) + .on_action(cx.listener(|workspace, _: &ActivatePaneRight, window, cx| { + workspace.activate_pane_in_direction(SplitDirection::Right, window, cx) + })) + .on_action(cx.listener(|workspace, _: &ActivatePaneUp, window, cx| { + workspace.activate_pane_in_direction(SplitDirection::Up, window, cx) + })) + .on_action(cx.listener(|workspace, _: &ActivatePaneDown, window, cx| { + workspace.activate_pane_in_direction(SplitDirection::Down, window, cx) + })) .on_action(cx.listener(|workspace, _: &ActivateNextPane, window, cx| { workspace.activate_next_pane(window, cx) })) - .on_action( - cx.listener(|workspace, action: &ActivatePaneInDirection, window, cx| { - workspace.activate_pane_in_direction(action.0, window, cx) - }), - ) .on_action(cx.listener( |workspace, action: &MoveItemToPaneInDirection, window, cx| { workspace.move_item_to_pane_in_direction(action, window, cx) }, )) - .on_action( - cx.listener(|workspace, action: &SwapPaneInDirection, _, cx| { - workspace.swap_pane_in_direction(action.0, cx) - }), - ) + .on_action(cx.listener(|workspace, _: &SwapPaneLeft, _, cx| { + workspace.swap_pane_in_direction(SplitDirection::Left, cx) + })) + .on_action(cx.listener(|workspace, _: &SwapPaneRight, _, cx| { + workspace.swap_pane_in_direction(SplitDirection::Right, cx) + })) + .on_action(cx.listener(|workspace, _: &SwapPaneUp, _, cx| { + workspace.swap_pane_in_direction(SplitDirection::Up, cx) + })) + .on_action(cx.listener(|workspace, _: &SwapPaneDown, _, cx| { + workspace.swap_pane_in_direction(SplitDirection::Down, cx) + })) .on_action(cx.listener(|this, _: &ToggleLeftDock, window, cx| { this.toggle_dock(DockPosition::Left, window, cx); })) diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 1cfc9460d4f802..6c891880340af7 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -3898,24 +3898,28 @@ mod tests { "vim::FindCommand" | "vim::Literal" | "vim::ResizePane" - | "vim::SwitchMode" - | "vim::PushOperator" + | "vim::PushObject" + | "vim::PushFindForward" + | "vim::PushFindBackward" + | "vim::PushSneak" + | "vim::PushSneakBackward" + | "vim::PushChangeSurrounds" + | "vim::PushJump" + | "vim::PushDigraph" + | "vim::PushLiteral" | "vim::Number" | "vim::SelectRegister" | "terminal::SendText" | "terminal::SendKeystroke" | "app_menu::OpenApplicationMenu" - | "app_menu::NavigateApplicationMenuInDirection" | "picker::ConfirmInput" | "editor::HandleInput" | "editor::FoldAtLevel" | "pane::ActivateItem" | "workspace::ActivatePane" - | "workspace::ActivatePaneInDirection" | "workspace::MoveItemToPane" | "workspace::MoveItemToPaneInDirection" | "workspace::OpenTerminal" - | "workspace::SwapPaneInDirection" | "workspace::SendKeystrokes" | "zed::OpenBrowser" | "zed::OpenZedUrl" => {} diff --git a/docs/src/key-bindings.md b/docs/src/key-bindings.md index 4d0a33ce5507f8..7482c8563cc411 100644 --- a/docs/src/key-bindings.md +++ b/docs/src/key-bindings.md @@ -119,7 +119,7 @@ command palette, by looking in the default keymaps for or [Linux](https://github.com/zed-industries/zed/blob/main/assets/keymaps/default-linux.json), or by using Zed's autocomplete in your keymap file. -Most actions do not require any arguments, and so you can bind them as strings: `"ctrl-a": "language_selector::Toggle"`. Some require a single argument, and must be bound as an array: `"ctrl-a": ["workspace::ActivatePaneInDirection", "down"]`. Some actions require multiple arguments, and are bound as an array of a string and an object: `"ctrl-a": ["pane::DeploySearch", { "replace_enabled": true }]`. +Most actions do not require any arguments, and so you can bind them as strings: `"ctrl-a": "language_selector::Toggle"`. Some require a single argument, and must be bound as an array: `"cmd-1": ["workspace::ActivatePane", 0]`. Some actions require multiple arguments, and are bound as an array of a string and an object: `"ctrl-a": ["pane::DeploySearch", { "replace_enabled": true }]`. ### Precedence diff --git a/docs/src/vim.md b/docs/src/vim.md index 96f124897f25ec..0646aa029a5326 100644 --- a/docs/src/vim.md +++ b/docs/src/vim.md @@ -367,10 +367,10 @@ But you cannot use the same shortcuts to move between all the editor docks (the { "context": "Dock", "bindings": { - "ctrl-w h": ["workspace::ActivatePaneInDirection", "Left"], - "ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"], - "ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"], - "ctrl-w j": ["workspace::ActivatePaneInDirection", "Down"] + "ctrl-w h": "workspace::ActivatePaneLeft", + "ctrl-w l": "workspace::ActivatePaneRight", + "ctrl-w k": "workspace::ActivatePaneUp", + "ctrl-w j": "workspace::ActivatePaneDown" // ... or other keybindings } } @@ -398,12 +398,7 @@ Vim mode comes with shortcuts to surround the selection in normal mode (`ys`), b { "context": "vim_mode == visual", "bindings": { - "shift-s": [ - "vim::PushOperator", - { - "AddSurrounds": {} - } - ] + "shift-s": ["vim::PushAddSurrounds", {}] } } ``` @@ -415,8 +410,8 @@ The [Sneak motion](https://github.com/justinmk/vim-sneak) feature allows for qui { "context": "vim_mode == normal || vim_mode == visual", "bindings": { - "s": ["vim::PushOperator", { "Sneak": {} }], - "S": ["vim::PushOperator", { "SneakBackward": {} }] + "s": ["vim::PushSneak", {}], + "S": ["vim::PushSneakBackward", {}] } } ]