From 6ea9abdc1b36f6a5d9752393202f914c740958d3 Mon Sep 17 00:00:00 2001 From: Peter Tripp Date: Thu, 29 May 2025 15:20:58 -0400 Subject: [PATCH] Cursor keymap (#31702) To use this, spawn `weclome: toggle base keymap selector` from the command palette. Screenshot 2025-05-29 at 14 07 35 MacOS is well tested to match Cursor. The [curors keymap documentation](https://docs.cursor.com/kbd) is does not explicitly state windows/linux keymap entries only "All Cmd keys can be replaced with Ctrl on Windows." so that is what we've done. We welcome feedback / refinements. Note, because this provides a mapping for `cmd-k` (macos) and `ctrl-k` (linux/windows) using this keymap will disable all of the default chorded keymap entries which have `cmd-k` / `ctrl-k` as a prefix. For example `cmd-k cmd-s` for open keymap will no longer function. Release Notes: - Added Cursor compatibility keymap --------- Co-authored-by: Joseph Lyons --- assets/keymaps/default-linux.json | 6 +- assets/keymaps/default-macos.json | 8 +-- assets/keymaps/linux/cursor.json | 85 +++++++++++++++++++++++ assets/keymaps/macos/cursor.json | 85 +++++++++++++++++++++++ crates/welcome/src/base_keymap_setting.rs | 10 ++- 5 files changed, 185 insertions(+), 9 deletions(-) create mode 100644 assets/keymaps/linux/cursor.json create mode 100644 assets/keymaps/macos/cursor.json diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index b407733a94..c72975de42 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -127,9 +127,7 @@ "shift-f10": "editor::OpenContextMenu", "ctrl-shift-e": "editor::ToggleEditPrediction", "f9": "editor::ToggleBreakpoint", - "shift-f9": "editor::EditLogBreakpoint", - "ctrl-shift-backspace": "editor::GoToPreviousChange", - "ctrl-shift-alt-backspace": "editor::GoToNextChange" + "shift-f9": "editor::EditLogBreakpoint" } }, { @@ -148,6 +146,8 @@ "ctrl->": "assistant::QuoteSelection", "ctrl-<": "assistant::InsertIntoEditor", "ctrl-alt-e": "editor::SelectEnclosingSymbol", + "ctrl-shift-backspace": "editor::GoToPreviousChange", + "ctrl-shift-alt-backspace": "editor::GoToNextChange", "alt-enter": "editor::OpenSelectionsInMultibuffer" } }, diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index a7b4319b94..5ca3b1101c 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -546,9 +546,7 @@ "cmd-\\": "pane::SplitRight", "cmd-k v": "markdown::OpenPreviewToTheSide", "cmd-shift-v": "markdown::OpenPreview", - "ctrl-cmd-c": "editor::DisplayCursorNames", - "cmd-shift-backspace": "editor::GoToPreviousChange", - "cmd-shift-alt-backspace": "editor::GoToNextChange" + "ctrl-cmd-c": "editor::DisplayCursorNames" } }, { @@ -556,7 +554,9 @@ "use_key_equivalents": true, "bindings": { "cmd-shift-o": "outline::Toggle", - "ctrl-g": "go_to_line::Toggle" + "ctrl-g": "go_to_line::Toggle", + "cmd-shift-backspace": "editor::GoToPreviousChange", + "cmd-shift-alt-backspace": "editor::GoToNextChange" } }, { diff --git a/assets/keymaps/linux/cursor.json b/assets/keymaps/linux/cursor.json new file mode 100644 index 0000000000..14cfcc43ec --- /dev/null +++ b/assets/keymaps/linux/cursor.json @@ -0,0 +1,85 @@ +[ + // Cursor for MacOS. See: https://docs.cursor.com/kbd + { + "context": "Workspace", + "use_key_equivalents": true, + "bindings": { + "ctrl-i": "agent::ToggleFocus", + "ctrl-shift-i": "agent::ToggleFocus", + "ctrl-l": "agent::ToggleFocus", + "ctrl-shift-l": "agent::ToggleFocus", + "ctrl-alt-b": "agent::ToggleFocus", + "ctrl-shift-j": "agent::OpenConfiguration" + } + }, + { + "context": "Editor && mode == full", + "use_key_equivalents": true, + "bindings": { + "ctrl-i": "agent::ToggleFocus", + "ctrl-shift-i": "agent::ToggleFocus", + "ctrl-shift-l": "assistant::QuoteSelection", // In cursor uses "Ask" mode + "ctrl-l": "assistant::QuoteSelection", // In cursor uses "Agent" mode + "ctrl-k": "assistant::InlineAssist", + "ctrl-shift-k": "assistant::InsertIntoEditor" + } + }, + { + "context": "InlineAssistEditor", + "use_key_equivalents": true, + "bindings": { + "ctrl-shift-backspace": "editor::Cancel" + // "alt-enter": // Quick Question + // "ctrl-shift-enter": // Full File Context + // "ctrl-shift-k": // Toggle input focus (editor <> inline assist) + } + }, + { + "context": "AgentPanel || ContextEditor || (MessageEditor > Editor)", + "use_key_equivalents": true, + "bindings": { + "ctrl-i": "workspace::ToggleRightDock", + "ctrl-shift-i": "workspace::ToggleRightDock", + "ctrl-l": "workspace::ToggleRightDock", + "ctrl-shift-l": "workspace::ToggleRightDock", + "ctrl-alt-b": "workspace::ToggleRightDock", + "ctrl-w": "workspace::ToggleRightDock", // technically should close chat + "ctrl-.": "agent::ToggleProfileSelector", + "ctrl-/": "agent::ToggleModelSelector", + "ctrl-shift-backspace": "editor::Cancel", + "ctrl-r": "agent::NewThread", + "ctrl-shift-v": "editor::Paste", + "ctrl-shift-k": "assistant::InsertIntoEditor" + // "escape": "agent::ToggleFocus" + ///// Enable when Zed supports multiple thread tabs + // "ctrl-t": // new thread tab + // "ctrl-[": // next thread tab + // "ctrl-]": // next thread tab + ///// Enable if Zed adds support for keyboard navigation of thread elements + // "tab": // cycle to next message + // "shift-tab": // cycle to previous message + } + }, + { + "context": "Editor && editor_agent_diff", + "use_key_equivalents": true, + "bindings": { + "ctrl-enter": "agent::KeepAll", + "ctrl-backspace": "agent::RejectAll" + } + }, + { + "context": "Editor && mode == full && edit_prediction", + "use_key_equivalents": true, + "bindings": { + "ctrl-right": "editor::AcceptPartialEditPrediction" + } + }, + { + "context": "Terminal", + "use_key_equivalents": true, + "bindings": { + "ctrl-k": "assistant::InlineAssist" + } + } +] diff --git a/assets/keymaps/macos/cursor.json b/assets/keymaps/macos/cursor.json new file mode 100644 index 0000000000..62981a5f66 --- /dev/null +++ b/assets/keymaps/macos/cursor.json @@ -0,0 +1,85 @@ +[ + // Cursor for MacOS. See: https://docs.cursor.com/kbd + { + "context": "Workspace", + "use_key_equivalents": true, + "bindings": { + "cmd-i": "agent::ToggleFocus", + "cmd-shift-i": "agent::ToggleFocus", + "cmd-l": "agent::ToggleFocus", + "cmd-shift-l": "agent::ToggleFocus", + "cmd-alt-b": "agent::ToggleFocus", + "cmd-shift-j": "agent::OpenConfiguration" + } + }, + { + "context": "Editor && mode == full", + "use_key_equivalents": true, + "bindings": { + "cmd-i": "agent::ToggleFocus", + "cmd-shift-i": "agent::ToggleFocus", + "cmd-shift-l": "assistant::QuoteSelection", // In cursor uses "Ask" mode + "cmd-l": "assistant::QuoteSelection", // In cursor uses "Agent" mode + "cmd-k": "assistant::InlineAssist", + "cmd-shift-k": "assistant::InsertIntoEditor" + } + }, + { + "context": "InlineAssistEditor", + "use_key_equivalents": true, + "bindings": { + "cmd-shift-backspace": "editor::Cancel" + // "alt-enter": // Quick Question + // "cmd-shift-enter": // Full File Context + // "cmd-shift-k": // Toggle input focus (editor <> inline assist) + } + }, + { + "context": "AgentPanel || ContextEditor || (MessageEditor > Editor)", + "use_key_equivalents": true, + "bindings": { + "cmd-i": "workspace::ToggleRightDock", + "cmd-shift-i": "workspace::ToggleRightDock", + "cmd-l": "workspace::ToggleRightDock", + "cmd-shift-l": "workspace::ToggleRightDock", + "cmd-alt-b": "workspace::ToggleRightDock", + "cmd-w": "workspace::ToggleRightDock", // technically should close chat + "cmd-.": "agent::ToggleProfileSelector", + "cmd-/": "agent::ToggleModelSelector", + "cmd-shift-backspace": "editor::Cancel", + "cmd-r": "agent::NewThread", + "cmd-shift-v": "editor::Paste", + "cmd-shift-k": "assistant::InsertIntoEditor" + // "escape": "agent::ToggleFocus" + ///// Enable when Zed supports multiple thread tabs + // "cmd-t": // new thread tab + // "cmd-[": // next thread tab + // "cmd-]": // next thread tab + ///// Enable if Zed adds support for keyboard navigation of thread elements + // "tab": // cycle to next message + // "shift-tab": // cycle to previous message + } + }, + { + "context": "Editor && editor_agent_diff", + "use_key_equivalents": true, + "bindings": { + "cmd-enter": "agent::KeepAll", + "cmd-backspace": "agent::RejectAll" + } + }, + { + "context": "Editor && mode == full && edit_prediction", + "use_key_equivalents": true, + "bindings": { + "cmd-right": "editor::AcceptPartialEditPrediction" + } + }, + { + "context": "Terminal", + "use_key_equivalents": true, + "bindings": { + "cmd-k": "assistant::InlineAssist" + } + } +] diff --git a/crates/welcome/src/base_keymap_setting.rs b/crates/welcome/src/base_keymap_setting.rs index bce4d78617..b841b69f9d 100644 --- a/crates/welcome/src/base_keymap_setting.rs +++ b/crates/welcome/src/base_keymap_setting.rs @@ -16,6 +16,7 @@ pub enum BaseKeymap { Atom, TextMate, Emacs, + Cursor, None, } @@ -28,6 +29,7 @@ impl Display for BaseKeymap { BaseKeymap::Atom => write!(f, "Atom"), BaseKeymap::TextMate => write!(f, "TextMate"), BaseKeymap::Emacs => write!(f, "Emacs (beta)"), + BaseKeymap::Cursor => write!(f, "Cursor (beta)"), BaseKeymap::None => write!(f, "None"), } } @@ -35,22 +37,24 @@ impl Display for BaseKeymap { impl BaseKeymap { #[cfg(target_os = "macos")] - pub const OPTIONS: [(&'static str, Self); 6] = [ + pub const OPTIONS: [(&'static str, Self); 7] = [ ("VSCode (Default)", Self::VSCode), ("Atom", Self::Atom), ("JetBrains", Self::JetBrains), ("Sublime Text", Self::SublimeText), ("Emacs (beta)", Self::Emacs), ("TextMate", Self::TextMate), + ("Cursor (beta)", Self::Cursor), ]; #[cfg(not(target_os = "macos"))] - pub const OPTIONS: [(&'static str, Self); 5] = [ + pub const OPTIONS: [(&'static str, Self); 6] = [ ("VSCode (Default)", Self::VSCode), ("Atom", Self::Atom), ("JetBrains", Self::JetBrains), ("Sublime Text", Self::SublimeText), ("Emacs (beta)", Self::Emacs), + ("Cursor (beta)", Self::Cursor), ]; pub fn asset_path(&self) -> Option<&'static str> { @@ -61,6 +65,7 @@ impl BaseKeymap { BaseKeymap::Atom => Some("keymaps/macos/atom.json"), BaseKeymap::TextMate => Some("keymaps/macos/textmate.json"), BaseKeymap::Emacs => Some("keymaps/macos/emacs.json"), + BaseKeymap::Cursor => Some("keymaps/macos/cursor.json"), BaseKeymap::VSCode => None, BaseKeymap::None => None, } @@ -71,6 +76,7 @@ impl BaseKeymap { BaseKeymap::SublimeText => Some("keymaps/linux/sublime_text.json"), BaseKeymap::Atom => Some("keymaps/linux/atom.json"), BaseKeymap::Emacs => Some("keymaps/linux/emacs.json"), + BaseKeymap::Cursor => Some("keymaps/linux/cursor.json"), BaseKeymap::TextMate => None, BaseKeymap::VSCode => None, BaseKeymap::None => None,