diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index b0811f7d34..81aa1d1008 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -1,15 +1,4 @@ [ - // Moved before Standard macOS bindings so that `cmd-w` is not the last binding for - // `workspace::CloseWindow` and displayed/intercepted by macOS - { - "context": "PromptLibrary", - "use_key_equivalents": true, - "bindings": { - "cmd-n": "rules_library::NewRule", - "cmd-shift-s": "rules_library::ToggleDefaultRule", - "cmd-w": "workspace::CloseWindow" - } - }, // Standard macOS bindings { "use_key_equivalents": true, @@ -380,6 +369,15 @@ "shift-backspace": "agent::RemoveSelectedThread" } }, + { + "context": "PromptLibrary", + "use_key_equivalents": true, + "bindings": { + "cmd-n": "rules_library::NewRule", + "cmd-shift-s": "rules_library::ToggleDefaultRule", + "cmd-w": "workspace::CloseWindow" + } + }, { "context": "BufferSearchBar", "use_key_equivalents": true, diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index bba5d2d78e..4786a4db22 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -846,13 +846,5 @@ // and Windows. "alt-l": "editor::AcceptEditPrediction" } - }, - { - // Fixes https://github.com/zed-industries/zed/issues/29095 by ensuring that - // the last binding for editor::ToggleComments is not ctrl-c. - "context": "hack_to_fix_ctrl-c", - "bindings": { - "g c": "editor::ToggleComments" - } } ] diff --git a/crates/gpui/src/keymap.rs b/crates/gpui/src/keymap.rs index 4f2b57fc52..4dbad6dc45 100644 --- a/crates/gpui/src/keymap.rs +++ b/crates/gpui/src/keymap.rs @@ -206,12 +206,15 @@ impl Keymap { bindings.pop() } - /// Like `bindings_to_display_from_bindings` but takes a `DoubleEndedIterator` and returns a - /// reference. - pub fn binding_to_display_from_bindings_iterator<'a>( - mut bindings: impl DoubleEndedIterator, + /// Returns the first binding present in the iterator, which tends to be the + /// default binding without any key context. This is useful for cases where no + /// key context is available on binding display. Otherwise, bindings with a + /// more specific key context would take precedence and result in a + /// potentially invalid keybind being returned. + pub fn default_binding_from_bindings_iterator<'a>( + mut bindings: impl Iterator, ) -> Option<&'a KeyBinding> { - bindings.next_back() + bindings.next() } } diff --git a/crates/gpui/src/platform/mac/events.rs b/crates/gpui/src/platform/mac/events.rs index 34805c5bb2..58f5d9bc1c 100644 --- a/crates/gpui/src/platform/mac/events.rs +++ b/crates/gpui/src/platform/mac/events.rs @@ -30,6 +30,7 @@ pub fn key_to_native(key: &str) -> Cow { let code = match key { "space" => SPACE_KEY, "backspace" => BACKSPACE_KEY, + "escape" => ESCAPE_KEY, "up" => NSUpArrowFunctionKey, "down" => NSDownArrowFunctionKey, "left" => NSLeftArrowFunctionKey, diff --git a/crates/gpui/src/platform/mac/platform.rs b/crates/gpui/src/platform/mac/platform.rs index a59d9d3cdc..6cfd97ad33 100644 --- a/crates/gpui/src/platform/mac/platform.rs +++ b/crates/gpui/src/platform/mac/platform.rs @@ -6,8 +6,8 @@ use super::{ }; use crate::{ Action, AnyWindowHandle, BackgroundExecutor, ClipboardEntry, ClipboardItem, ClipboardString, - CursorStyle, ForegroundExecutor, Image, ImageFormat, Keymap, MacDispatcher, MacDisplay, - MacWindow, Menu, MenuItem, PathPromptOptions, Platform, PlatformDisplay, + CursorStyle, ForegroundExecutor, Image, ImageFormat, KeyContext, Keymap, MacDispatcher, + MacDisplay, MacWindow, Menu, MenuItem, PathPromptOptions, Platform, PlatformDisplay, PlatformKeyboardLayout, PlatformTextSystem, PlatformWindow, Result, ScreenCaptureSource, SemanticVersion, Task, WindowAppearance, WindowParams, hash, }; @@ -36,6 +36,7 @@ use core_foundation::{ }; use ctor::ctor; use futures::channel::oneshot; +use itertools::Itertools; use objc::{ class, declare::ClassDecl, @@ -46,7 +47,7 @@ use objc::{ use parking_lot::Mutex; use ptr::null_mut; use std::{ - cell::Cell, + cell::{Cell, LazyCell}, convert::TryInto, ffi::{CStr, OsStr, c_void}, os::{raw::c_char, unix::ffi::OsStrExt}, @@ -293,6 +294,19 @@ impl MacPlatform { actions: &mut Vec>, keymap: &Keymap, ) -> id { + const DEFAULT_CONTEXT: LazyCell> = LazyCell::new(|| { + let mut workspace_context = KeyContext::new_with_defaults(); + workspace_context.add("Workspace"); + let mut pane_context = KeyContext::new_with_defaults(); + pane_context.add("Pane"); + let mut editor_context = KeyContext::new_with_defaults(); + editor_context.add("Editor"); + + pane_context.extend(&editor_context); + workspace_context.extend(&pane_context); + vec![workspace_context] + }); + unsafe { match item { MenuItem::Separator => NSMenuItem::separatorItem(nil), @@ -301,10 +315,14 @@ impl MacPlatform { action, os_action, } => { - let keystrokes = crate::Keymap::binding_to_display_from_bindings_iterator( - keymap.bindings_for_action(action.as_ref()), - ) - .map(|binding| binding.keystrokes()); + let keystrokes = keymap + .bindings_for_action(action.as_ref()) + .find_or_first(|binding| { + binding + .predicate() + .is_none_or(|predicate| predicate.eval(&DEFAULT_CONTEXT)) + }) + .map(|binding| binding.keystrokes()); let selector = match os_action { Some(crate::OsAction::Cut) => selector("cut:"),