macOS: Add key equivalents for non-Latin layouts (#20401)
Closes #16343 Closes #10972 Release Notes: - (breaking change) On macOS when using a keyboard that supports an extended Latin character set (e.g. French, German, ...) keyboard shortcuts are automatically updated so that they can be typed without `option`. This fixes several long-standing problems where some keyboards could not type some shortcuts. - This mapping works the same way as [macOS](https://developer.apple.com/documentation/swiftui/view/keyboardshortcut(_:modifiers:localization:)). For example on a German keyboard shortcuts like `cmd->` become `cmd-:`, `cmd-[` and `cmd-]` become `cmd-ö` and `cmd-ä`. This mapping happens at the time keyboard layout files are read so the keybindings are visible in the command palette. To opt out of this behavior for your custom keyboard shortcuts, set `"use_layout_keys": true` in your binding section. For the mappings used for each layout [see here](https://github.com/zed-industries/zed/blob/a890df1863ca939ee7f0ada6e629b6f83eb18bc5/crates/settings/src/key_equivalents.rs#L7). --------- Co-authored-by: Will <will@zed.dev>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use collections::HashMap;
|
||||
|
||||
use crate::{Action, KeyBindingContextPredicate, Keystroke};
|
||||
use anyhow::Result;
|
||||
use smallvec::SmallVec;
|
||||
@@ -22,22 +24,37 @@ impl Clone for KeyBinding {
|
||||
impl KeyBinding {
|
||||
/// Construct a new keybinding from the given data.
|
||||
pub fn new<A: Action>(keystrokes: &str, action: A, context_predicate: Option<&str>) -> Self {
|
||||
Self::load(keystrokes, Box::new(action), context_predicate).unwrap()
|
||||
Self::load(keystrokes, Box::new(action), context_predicate, None).unwrap()
|
||||
}
|
||||
|
||||
/// Load a keybinding from the given raw data.
|
||||
pub fn load(keystrokes: &str, action: Box<dyn Action>, context: Option<&str>) -> Result<Self> {
|
||||
pub fn load(
|
||||
keystrokes: &str,
|
||||
action: Box<dyn Action>,
|
||||
context: Option<&str>,
|
||||
key_equivalents: Option<&HashMap<char, char>>,
|
||||
) -> Result<Self> {
|
||||
let context = if let Some(context) = context {
|
||||
Some(KeyBindingContextPredicate::parse(context)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let keystrokes = keystrokes
|
||||
let mut keystrokes: SmallVec<[Keystroke; 2]> = keystrokes
|
||||
.split_whitespace()
|
||||
.map(Keystroke::parse)
|
||||
.collect::<Result<_>>()?;
|
||||
|
||||
if let Some(equivalents) = key_equivalents {
|
||||
for keystroke in keystrokes.iter_mut() {
|
||||
if keystroke.key.chars().count() == 1 {
|
||||
if let Some(key) = equivalents.get(&keystroke.key.chars().next().unwrap()) {
|
||||
keystroke.key = key.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
keystrokes,
|
||||
action,
|
||||
|
||||
Reference in New Issue
Block a user