mirror of
https://github.com/wez/wezterm.git
synced 2024-11-23 15:04:36 +03:00
keys: default assignments can now be set to mapped or physical
A bit of a PITA, this commit: * Introduces a DeferredKeyCode type that defers resolving a concrete keycode * Adds key_map_preference config which can be Mapped or Physical * Key map building resolves the keycode using key_map_preference * Default key assignments have been re-phrased in order to produce DeferredKeyCodes * User-specified keys without `mapped:` or `phys:` prefixes will resolve according to key_map_preference refs: https://github.com/wez/wezterm/issues/1788 refs: https://github.com/wez/wezterm/issues/1784
This commit is contained in:
parent
76cbcb1341
commit
508baabc79
@ -16,8 +16,8 @@ use crate::unix::UnixDomain;
|
||||
use crate::wsl::WslDomain;
|
||||
use crate::{
|
||||
de_number, de_vec_table, default_config_with_overrides_applied, default_one_point_oh,
|
||||
default_one_point_oh_f64, default_true, make_lua_context, LoadedConfig, CONFIG_DIR,
|
||||
CONFIG_FILE_OVERRIDE, CONFIG_OVERRIDES, CONFIG_SKIP, HOME_DIR,
|
||||
default_one_point_oh_f64, default_true, make_lua_context, KeyMapPreference, LoadedConfig,
|
||||
CONFIG_DIR, CONFIG_FILE_OVERRIDE, CONFIG_OVERRIDES, CONFIG_SKIP, HOME_DIR,
|
||||
};
|
||||
use anyhow::Context;
|
||||
use luahelper::impl_lua_conversion;
|
||||
@ -249,7 +249,7 @@ pub struct Config {
|
||||
#[serde(default = "default_mux_env_remove", deserialize_with = "de_vec_table")]
|
||||
pub mux_env_remove: Vec<String>,
|
||||
|
||||
#[serde(default)]
|
||||
#[serde(default, deserialize_with = "de_vec_table")]
|
||||
pub keys: Vec<Key>,
|
||||
#[serde(
|
||||
default = "default_bypass_mouse_reporting_modifiers",
|
||||
@ -612,6 +612,9 @@ pub struct Config {
|
||||
|
||||
#[serde(default)]
|
||||
pub xcursor_size: Option<u32>,
|
||||
|
||||
#[serde(default)]
|
||||
pub key_map_preference: KeyMapPreference,
|
||||
}
|
||||
impl_lua_conversion!(Config);
|
||||
|
||||
@ -781,7 +784,11 @@ impl Config {
|
||||
let mut map = HashMap::new();
|
||||
|
||||
for k in &self.keys {
|
||||
let (key, mods) = k.key.key.normalize_shift(k.key.mods);
|
||||
let (key, mods) = k
|
||||
.key
|
||||
.key
|
||||
.resolve(self.key_map_preference)
|
||||
.normalize_shift(k.key.mods);
|
||||
map.insert((key, mods), k.action.clone());
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
use crate::keys::KeyNoAction;
|
||||
use crate::{de_notnan, ConfigHandle, LeaderKey};
|
||||
use crate::{de_notnan, ConfigHandle};
|
||||
use luahelper::impl_lua_conversion;
|
||||
use ordered_float::NotNan;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::path::PathBuf;
|
||||
use wezterm_input_types::{KeyCode, Modifiers, PhysKeyCode};
|
||||
use std::time::Duration;
|
||||
use wezterm_input_types::{KeyCode, Modifiers};
|
||||
use wezterm_term::input::MouseButton;
|
||||
|
||||
#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||
@ -351,7 +352,7 @@ impl_lua_conversion!(KeyAssignment);
|
||||
pub struct InputMap {
|
||||
pub keys: HashMap<(KeyCode, Modifiers), KeyAssignment>,
|
||||
pub mouse: HashMap<(MouseEventTrigger, Modifiers), KeyAssignment>,
|
||||
leader: Option<LeaderKey>,
|
||||
leader: Option<(KeyCode, Modifiers, Duration)>,
|
||||
}
|
||||
|
||||
impl InputMap {
|
||||
@ -360,12 +361,21 @@ impl InputMap {
|
||||
|
||||
let mut keys = config.key_bindings();
|
||||
|
||||
let leader = config.leader.clone();
|
||||
let leader = config.leader.as_ref().map(|leader| {
|
||||
(
|
||||
leader.key.key.resolve(config.key_map_preference).clone(),
|
||||
leader.key.mods,
|
||||
Duration::from_millis(leader.timeout_milliseconds),
|
||||
)
|
||||
});
|
||||
|
||||
macro_rules! k {
|
||||
($([$mod:expr, $code:expr, $action:expr]),* $(,)?) => {
|
||||
($([$mod:expr, $code:literal, $action:expr]),* $(,)?) => {
|
||||
$(
|
||||
keys.entry(($code, $mod)).or_insert($action);
|
||||
let key = crate::DeferredKeyCode::try_from($code)
|
||||
.unwrap()
|
||||
.resolve(config.key_map_preference).clone();
|
||||
keys.entry((key, $mod)).or_insert($action);
|
||||
)*
|
||||
};
|
||||
}
|
||||
@ -388,290 +398,177 @@ impl InputMap {
|
||||
// Clipboard
|
||||
[
|
||||
Modifiers::SHIFT,
|
||||
KeyCode::Physical(PhysKeyCode::Insert),
|
||||
"Insert",
|
||||
PasteFrom(ClipboardPasteSource::PrimarySelection)
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL,
|
||||
KeyCode::Physical(PhysKeyCode::Insert),
|
||||
"Insert",
|
||||
CopyTo(ClipboardCopyDestination::PrimarySelection)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::C),
|
||||
"c",
|
||||
CopyTo(ClipboardCopyDestination::Clipboard)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::V),
|
||||
PasteFrom(ClipboardPasteSource::Clipboard)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::C),
|
||||
CopyTo(ClipboardCopyDestination::Clipboard)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::V),
|
||||
"v",
|
||||
PasteFrom(ClipboardPasteSource::Clipboard)
|
||||
],
|
||||
[ctrl_shift, "C", CopyTo(ClipboardCopyDestination::Clipboard)],
|
||||
[ctrl_shift, "c", CopyTo(ClipboardCopyDestination::Clipboard)],
|
||||
[ctrl_shift, "V", PasteFrom(ClipboardPasteSource::Clipboard)],
|
||||
[ctrl_shift, "v", PasteFrom(ClipboardPasteSource::Clipboard)],
|
||||
[
|
||||
Modifiers::NONE,
|
||||
KeyCode::Copy,
|
||||
"Copy",
|
||||
CopyTo(ClipboardCopyDestination::Clipboard)
|
||||
],
|
||||
[
|
||||
Modifiers::NONE,
|
||||
KeyCode::Paste,
|
||||
"Paste",
|
||||
PasteFrom(ClipboardPasteSource::Clipboard)
|
||||
],
|
||||
// Window management
|
||||
[
|
||||
Modifiers::ALT,
|
||||
KeyCode::Physical(PhysKeyCode::Return),
|
||||
ToggleFullScreen
|
||||
],
|
||||
[Modifiers::SUPER, KeyCode::Physical(PhysKeyCode::M), Hide],
|
||||
[Modifiers::ALT, "Return", ToggleFullScreen],
|
||||
[Modifiers::SUPER, "m", Hide],
|
||||
[Modifiers::SUPER, "n", SpawnWindow],
|
||||
[ctrl_shift, "M", Hide],
|
||||
[ctrl_shift, "m", Hide],
|
||||
[ctrl_shift, "N", SpawnWindow],
|
||||
[ctrl_shift, "n", SpawnWindow],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::N),
|
||||
SpawnWindow
|
||||
],
|
||||
[ctrl_shift, KeyCode::Physical(PhysKeyCode::M), Hide],
|
||||
[ctrl_shift, KeyCode::Physical(PhysKeyCode::N), SpawnWindow],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::K),
|
||||
"k",
|
||||
ClearScrollback(ScrollbackEraseMode::ScrollbackOnly)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::K),
|
||||
"K",
|
||||
ClearScrollback(ScrollbackEraseMode::ScrollbackOnly)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
"k",
|
||||
ClearScrollback(ScrollbackEraseMode::ScrollbackOnly)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::F),
|
||||
"f",
|
||||
Search(Pattern::CaseSensitiveString("".into()))
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::F),
|
||||
"F",
|
||||
Search(Pattern::CaseSensitiveString("".into()))
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::L),
|
||||
ShowDebugOverlay
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::Space),
|
||||
QuickSelect
|
||||
"f",
|
||||
Search(Pattern::CaseSensitiveString("".into()))
|
||||
],
|
||||
[ctrl_shift, "L", ShowDebugOverlay],
|
||||
[ctrl_shift, "l", ShowDebugOverlay],
|
||||
[ctrl_shift, "Space", QuickSelect],
|
||||
// Font size manipulation
|
||||
[
|
||||
Modifiers::CTRL,
|
||||
KeyCode::Physical(PhysKeyCode::Minus),
|
||||
DecreaseFontSize
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL,
|
||||
KeyCode::Physical(PhysKeyCode::K0),
|
||||
ResetFontSize
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL,
|
||||
KeyCode::Physical(PhysKeyCode::Equal),
|
||||
IncreaseFontSize
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::Minus),
|
||||
DecreaseFontSize
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::K0),
|
||||
ResetFontSize
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::Equal),
|
||||
IncreaseFontSize
|
||||
],
|
||||
[Modifiers::SUPER, "-", DecreaseFontSize],
|
||||
[Modifiers::SUPER, "0", ResetFontSize],
|
||||
[Modifiers::SUPER, "=", IncreaseFontSize],
|
||||
// Font size, CTRL variant.
|
||||
[Modifiers::CTRL, "-", DecreaseFontSize],
|
||||
[Modifiers::CTRL, "0", ResetFontSize],
|
||||
[Modifiers::CTRL, "=", IncreaseFontSize],
|
||||
// Font size, CTRL+SHIFT variant.
|
||||
// Ugh. Combinations of these to account for varying degrees
|
||||
// of shift/mapping normalizing on different systems.
|
||||
[Modifiers::CTRL | Modifiers::SHIFT, "-", DecreaseFontSize],
|
||||
[Modifiers::CTRL | Modifiers::SHIFT, "_", DecreaseFontSize],
|
||||
[Modifiers::CTRL, "_", DecreaseFontSize],
|
||||
[Modifiers::CTRL | Modifiers::SHIFT, "0", ResetFontSize],
|
||||
[Modifiers::CTRL | Modifiers::SHIFT, ")", ResetFontSize],
|
||||
[Modifiers::CTRL, ")", ResetFontSize],
|
||||
[Modifiers::CTRL | Modifiers::SHIFT, "=", IncreaseFontSize],
|
||||
[Modifiers::CTRL | Modifiers::SHIFT, "+", IncreaseFontSize],
|
||||
[Modifiers::CTRL, "+", IncreaseFontSize],
|
||||
// Tab navigation and management
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::T),
|
||||
"t",
|
||||
SpawnTab(SpawnTabDomain::CurrentPaneDomain)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::T),
|
||||
SpawnTab(SpawnTabDomain::CurrentPaneDomain)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::K1),
|
||||
ActivateTab(0)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::K2),
|
||||
ActivateTab(1)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::K3),
|
||||
ActivateTab(2)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::K4),
|
||||
ActivateTab(3)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::K5),
|
||||
ActivateTab(4)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::K6),
|
||||
ActivateTab(5)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::K7),
|
||||
ActivateTab(6)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::K8),
|
||||
ActivateTab(7)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::K9),
|
||||
ActivateTab(-1)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::W),
|
||||
CloseCurrentTab { confirm: true }
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::K1),
|
||||
ActivateTab(0)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::K2),
|
||||
ActivateTab(1)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::K3),
|
||||
ActivateTab(2)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::K4),
|
||||
ActivateTab(3)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::K5),
|
||||
ActivateTab(4)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::K6),
|
||||
ActivateTab(5)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::K7),
|
||||
ActivateTab(6)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::K8),
|
||||
ActivateTab(7)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::K9),
|
||||
ActivateTab(-1)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::W),
|
||||
CloseCurrentTab { confirm: true }
|
||||
],
|
||||
[ctrl_shift, "t", SpawnTab(SpawnTabDomain::CurrentPaneDomain)],
|
||||
[ctrl_shift, "T", SpawnTab(SpawnTabDomain::CurrentPaneDomain)],
|
||||
[Modifiers::SUPER, "1", ActivateTab(0)],
|
||||
[Modifiers::SUPER, "2", ActivateTab(1)],
|
||||
[Modifiers::SUPER, "3", ActivateTab(2)],
|
||||
[Modifiers::SUPER, "4", ActivateTab(3)],
|
||||
[Modifiers::SUPER, "5", ActivateTab(4)],
|
||||
[Modifiers::SUPER, "6", ActivateTab(5)],
|
||||
[Modifiers::SUPER, "7", ActivateTab(6)],
|
||||
[Modifiers::SUPER, "8", ActivateTab(7)],
|
||||
[Modifiers::SUPER, "9", ActivateTab(-1)],
|
||||
[Modifiers::SUPER, "w", CloseCurrentTab { confirm: true }],
|
||||
[ctrl_shift, "1", ActivateTab(0)],
|
||||
[ctrl_shift, "2", ActivateTab(1)],
|
||||
[ctrl_shift, "3", ActivateTab(2)],
|
||||
[ctrl_shift, "4", ActivateTab(3)],
|
||||
[ctrl_shift, "5", ActivateTab(4)],
|
||||
[ctrl_shift, "6", ActivateTab(5)],
|
||||
[ctrl_shift, "7", ActivateTab(6)],
|
||||
[ctrl_shift, "8", ActivateTab(7)],
|
||||
[ctrl_shift, "9", ActivateTab(-1)],
|
||||
[ctrl_shift, "W", CloseCurrentTab { confirm: true }],
|
||||
[
|
||||
Modifiers::SUPER | Modifiers::SHIFT,
|
||||
KeyCode::Physical(PhysKeyCode::LeftBracket),
|
||||
"[",
|
||||
ActivateTabRelative(-1)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::Tab),
|
||||
Modifiers::SUPER | Modifiers::SHIFT,
|
||||
"{",
|
||||
ActivateTabRelative(-1)
|
||||
],
|
||||
[Modifiers::CTRL, KeyCode::PageUp, ActivateTabRelative(-1)],
|
||||
[ctrl_shift, "Tab", ActivateTabRelative(-1)],
|
||||
[Modifiers::CTRL, "PageUp", ActivateTabRelative(-1)],
|
||||
[
|
||||
Modifiers::SUPER | Modifiers::SHIFT,
|
||||
KeyCode::Physical(PhysKeyCode::RightBracket),
|
||||
"]",
|
||||
ActivateTabRelative(1)
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL,
|
||||
KeyCode::Physical(PhysKeyCode::Tab),
|
||||
Modifiers::SUPER | Modifiers::SHIFT,
|
||||
"}",
|
||||
ActivateTabRelative(1)
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL,
|
||||
KeyCode::Physical(PhysKeyCode::PageDown),
|
||||
ActivateTabRelative(1)
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::R),
|
||||
ReloadConfiguration
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::R),
|
||||
ReloadConfiguration
|
||||
],
|
||||
[ctrl_shift, KeyCode::PageUp, MoveTabRelative(-1)],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::PageDown),
|
||||
MoveTabRelative(1)
|
||||
],
|
||||
[Modifiers::CTRL, "Tab", ActivateTabRelative(1)],
|
||||
[Modifiers::CTRL, "PageDown", ActivateTabRelative(1)],
|
||||
[Modifiers::SUPER, "r", ReloadConfiguration],
|
||||
[ctrl_shift, "R", ReloadConfiguration],
|
||||
[ctrl_shift, "PageUp", MoveTabRelative(-1)],
|
||||
[ctrl_shift, "PageDown", MoveTabRelative(1)],
|
||||
[
|
||||
Modifiers::SHIFT,
|
||||
KeyCode::PageUp,
|
||||
"PageUp",
|
||||
ScrollByPage(NotNan::new(-1.0).unwrap())
|
||||
],
|
||||
[
|
||||
Modifiers::SHIFT,
|
||||
KeyCode::Physical(PhysKeyCode::PageDown),
|
||||
"PageDown",
|
||||
ScrollByPage(NotNan::new(1.0).unwrap())
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::X),
|
||||
ActivateCopyMode
|
||||
],
|
||||
[ctrl_shift, "X", ActivateCopyMode],
|
||||
[
|
||||
Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
|
||||
KeyCode::Physical(PhysKeyCode::Quote),
|
||||
"'",
|
||||
SplitVertical(SpawnCommand {
|
||||
domain: SpawnTabDomain::CurrentPaneDomain,
|
||||
..Default::default()
|
||||
})
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL | Modifiers::ALT,
|
||||
"\"",
|
||||
SplitVertical(SpawnCommand {
|
||||
domain: SpawnTabDomain::CurrentPaneDomain,
|
||||
..Default::default()
|
||||
@ -679,7 +576,15 @@ impl InputMap {
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
|
||||
KeyCode::Physical(PhysKeyCode::K5),
|
||||
"5",
|
||||
SplitHorizontal(SpawnCommand {
|
||||
domain: SpawnTabDomain::CurrentPaneDomain,
|
||||
..Default::default()
|
||||
})
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL | Modifiers::ALT,
|
||||
"%",
|
||||
SplitHorizontal(SpawnCommand {
|
||||
domain: SpawnTabDomain::CurrentPaneDomain,
|
||||
..Default::default()
|
||||
@ -687,63 +592,51 @@ impl InputMap {
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
|
||||
KeyCode::Physical(PhysKeyCode::LeftArrow),
|
||||
"LeftArrow",
|
||||
AdjustPaneSize(PaneDirection::Left, 1)
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
|
||||
KeyCode::Physical(PhysKeyCode::RightArrow),
|
||||
"RightArrow",
|
||||
AdjustPaneSize(PaneDirection::Right, 1)
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
|
||||
KeyCode::Physical(PhysKeyCode::UpArrow),
|
||||
"UpArrow",
|
||||
AdjustPaneSize(PaneDirection::Up, 1)
|
||||
],
|
||||
[
|
||||
Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
|
||||
KeyCode::Physical(PhysKeyCode::DownArrow),
|
||||
"DownArrow",
|
||||
AdjustPaneSize(PaneDirection::Down, 1)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::LeftArrow),
|
||||
"LeftArrow",
|
||||
ActivatePaneDirection(PaneDirection::Left)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::RightArrow),
|
||||
"RightArrow",
|
||||
ActivatePaneDirection(PaneDirection::Right)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::UpArrow),
|
||||
"UpArrow",
|
||||
ActivatePaneDirection(PaneDirection::Up)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::DownArrow),
|
||||
"DownArrow",
|
||||
ActivatePaneDirection(PaneDirection::Down)
|
||||
],
|
||||
[
|
||||
ctrl_shift,
|
||||
KeyCode::Physical(PhysKeyCode::Z),
|
||||
TogglePaneZoomState
|
||||
],
|
||||
[ctrl_shift, "Z", TogglePaneZoomState],
|
||||
);
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
k!(
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::H),
|
||||
HideApplication
|
||||
],
|
||||
[
|
||||
Modifiers::SUPER,
|
||||
KeyCode::Physical(PhysKeyCode::Q),
|
||||
QuitApplication
|
||||
],
|
||||
[Modifiers::SUPER, "h", HideApplication],
|
||||
[Modifiers::SUPER, "q", QuitApplication],
|
||||
);
|
||||
}
|
||||
|
||||
@ -879,11 +772,9 @@ impl InputMap {
|
||||
}
|
||||
|
||||
pub fn is_leader(&self, key: &KeyCode, mods: Modifiers) -> Option<std::time::Duration> {
|
||||
if let Some(leader) = self.leader.as_ref() {
|
||||
if leader.key.key == *key && leader.key.mods == mods {
|
||||
return Some(std::time::Duration::from_millis(
|
||||
leader.timeout_milliseconds,
|
||||
));
|
||||
if let Some((leader_key, leader_mods, timeout)) = self.leader.as_ref() {
|
||||
if *leader_key == *key && *leader_mods == mods {
|
||||
return Some(timeout.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -5,10 +5,130 @@ use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use wezterm_input_types::{KeyCode, Modifiers, PhysKeyCode};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub enum KeyMapPreference {
|
||||
Physical,
|
||||
Mapped,
|
||||
}
|
||||
impl_lua_conversion!(KeyMapPreference);
|
||||
|
||||
impl Default for KeyMapPreference {
|
||||
fn default() -> Self {
|
||||
Self::Mapped
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(into = "String", try_from = "String")]
|
||||
pub enum DeferredKeyCode {
|
||||
KeyCode(KeyCode),
|
||||
Either { physical: KeyCode, mapped: KeyCode },
|
||||
}
|
||||
|
||||
impl DeferredKeyCode {
|
||||
pub fn resolve(&self, position: KeyMapPreference) -> &KeyCode {
|
||||
match (self, position) {
|
||||
(Self::KeyCode(key), _) => key,
|
||||
(Self::Either { mapped, .. }, KeyMapPreference::Mapped) => mapped,
|
||||
(Self::Either { physical, .. }, KeyMapPreference::Physical) => physical,
|
||||
}
|
||||
}
|
||||
|
||||
fn as_string(key: &KeyCode) -> String {
|
||||
if let Some(s) = INV_KEYCODE_MAP.get(key) {
|
||||
s.to_string()
|
||||
} else {
|
||||
key.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_str(s: &str) -> anyhow::Result<KeyCode> {
|
||||
if let Some(c) = KEYCODE_MAP.get(s) {
|
||||
return Ok(c.clone());
|
||||
}
|
||||
|
||||
if let Some(phys) = s.strip_prefix("phys:") {
|
||||
let phys = PhysKeyCode::try_from(phys).map_err(|_| {
|
||||
anyhow::anyhow!("expected phys:CODE physical keycode string, got: {}", s)
|
||||
})?;
|
||||
return Ok(KeyCode::Physical(phys));
|
||||
}
|
||||
|
||||
if let Some(raw) = s.strip_prefix("raw:") {
|
||||
let num: u32 = raw.parse().map_err(|_| {
|
||||
anyhow::anyhow!("expected raw:<NUMBER> raw keycode string, got: {}", s)
|
||||
})?;
|
||||
return Ok(KeyCode::RawCode(num));
|
||||
}
|
||||
|
||||
if let Some(mapped) = s.strip_prefix("mapped:") {
|
||||
let chars: Vec<char> = mapped.chars().collect();
|
||||
return if chars.len() == 1 {
|
||||
Ok(KeyCode::Char(chars[0]))
|
||||
} else {
|
||||
anyhow::bail!("invalid KeyCode string {}", s);
|
||||
};
|
||||
}
|
||||
|
||||
let chars: Vec<char> = s.chars().collect();
|
||||
if chars.len() == 1 {
|
||||
let k = KeyCode::Char(chars[0]);
|
||||
if let Some(phys) = k.to_phys() {
|
||||
Ok(KeyCode::Physical(phys))
|
||||
} else {
|
||||
Ok(k)
|
||||
}
|
||||
} else {
|
||||
anyhow::bail!("invalid KeyCode string {}", s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for DeferredKeyCode {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
DeferredKeyCode::KeyCode(key) => Self::as_string(&key),
|
||||
DeferredKeyCode::Either { mapped, .. } => {
|
||||
let mapped = Self::as_string(&mapped);
|
||||
mapped
|
||||
.strip_prefix("mapped:")
|
||||
.expect("to have mapped: prefix")
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for DeferredKeyCode {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(s: String) -> anyhow::Result<DeferredKeyCode> {
|
||||
DeferredKeyCode::try_from(s.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for DeferredKeyCode {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(s: &str) -> anyhow::Result<DeferredKeyCode> {
|
||||
if s.starts_with("mapped:") || s.starts_with("phys:") {
|
||||
let key = Self::parse_str(&s)?;
|
||||
return Ok(DeferredKeyCode::KeyCode(key));
|
||||
}
|
||||
|
||||
let mapped = Self::parse_str(&format!("mapped:{}", s));
|
||||
let phys = Self::parse_str(&format!("phys:{}", s));
|
||||
|
||||
match (mapped, phys) {
|
||||
(Ok(mapped), Ok(physical)) => Ok(DeferredKeyCode::Either { mapped, physical }),
|
||||
(Ok(mapped), Err(_)) => Ok(DeferredKeyCode::KeyCode(mapped)),
|
||||
(Err(_), Ok(phys)) => Ok(DeferredKeyCode::KeyCode(phys)),
|
||||
(Err(a), Err(b)) => anyhow::bail!("invalid keycode {}: {:#}, {:#}", s, a, b),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||
pub struct KeyNoAction {
|
||||
#[serde(deserialize_with = "de_keycode", serialize_with = "ser_keycode")]
|
||||
pub key: KeyCode,
|
||||
pub key: DeferredKeyCode,
|
||||
#[serde(
|
||||
deserialize_with = "de_modifiers",
|
||||
serialize_with = "ser_modifiers",
|
||||
@ -60,10 +180,10 @@ fn make_map() -> HashMap<String, KeyCode> {
|
||||
$(
|
||||
let v = KeyCode::$val;
|
||||
if let Some(phys) = v.to_phys() {
|
||||
map.insert(stringify!($val).to_string(), KeyCode::Physical(phys));
|
||||
map.insert(format!("phys:{}", stringify!($val)), KeyCode::Physical(phys));
|
||||
map.insert(format!("mapped:{}", stringify!($val)), v);
|
||||
} else {
|
||||
map.insert(stringify!($val).to_string(), v);
|
||||
map.insert(format!("mapped:{}", stringify!($val)), v);
|
||||
}
|
||||
)*
|
||||
}
|
||||
@ -143,14 +263,14 @@ fn make_map() -> HashMap<String, KeyCode> {
|
||||
("Escape", PhysKeyCode::Escape),
|
||||
("Tab", PhysKeyCode::Tab),
|
||||
] {
|
||||
map.insert(label.to_string(), KeyCode::Physical(*phys));
|
||||
map.insert(format!("phys:{}", label), KeyCode::Physical(*phys));
|
||||
map.insert(format!("mapped:{}", label), phys.to_key_code());
|
||||
}
|
||||
|
||||
for i in 0..=9 {
|
||||
let k = KeyCode::Numpad(i);
|
||||
map.insert(
|
||||
format!("Numpad{}", i),
|
||||
format!("phys:Numpad{}", i),
|
||||
KeyCode::Physical(k.to_phys().unwrap()),
|
||||
);
|
||||
// Not sure how likely someone is to remap the numpad, but...
|
||||
@ -160,11 +280,11 @@ fn make_map() -> HashMap<String, KeyCode> {
|
||||
for i in 1..=24 {
|
||||
let k = KeyCode::Function(i);
|
||||
if let Some(phys) = k.to_phys() {
|
||||
map.insert(format!("F{}", i), KeyCode::Physical(phys));
|
||||
map.insert(format!("phys:F{}", i), KeyCode::Physical(phys));
|
||||
map.insert(format!("mapped:F{}", i), k);
|
||||
} else {
|
||||
// 21 and up don't have phys equivalents
|
||||
map.insert(format!("F{}", i), k);
|
||||
map.insert(format!("mapped:F{}", i), k);
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,76 +304,6 @@ lazy_static::lazy_static! {
|
||||
static ref INV_KEYCODE_MAP: HashMap<KeyCode, String> = make_inv_map();
|
||||
}
|
||||
|
||||
pub(crate) fn ser_keycode<S>(key: &KeyCode, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
if let Some(s) = INV_KEYCODE_MAP.get(key) {
|
||||
serializer.serialize_str(s)
|
||||
} else {
|
||||
let s = key.to_string();
|
||||
serializer.serialize_str(&s)
|
||||
}
|
||||
}
|
||||
|
||||
fn de_keycode<'de, D>(deserializer: D) -> Result<KeyCode, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
|
||||
if let Some(c) = KEYCODE_MAP.get(&s) {
|
||||
return Ok(c.clone());
|
||||
}
|
||||
|
||||
if s.len() > 5 && s.starts_with("phys:") {
|
||||
let phys = PhysKeyCode::try_from(&s[5..]).map_err(|_| {
|
||||
serde::de::Error::custom(format!(
|
||||
"expected phys:CODE physical keycode string, got: {}",
|
||||
s
|
||||
))
|
||||
})?;
|
||||
return Ok(KeyCode::Physical(phys));
|
||||
}
|
||||
|
||||
if s.len() > 4 && s.starts_with("raw:") {
|
||||
let num: u32 = s[4..].parse().map_err(|_| {
|
||||
serde::de::Error::custom(format!(
|
||||
"expected raw:<NUMBER> raw keycode string, got: {}",
|
||||
s
|
||||
))
|
||||
})?;
|
||||
return Ok(KeyCode::RawCode(num));
|
||||
}
|
||||
|
||||
if let Some(mapped) = s.strip_prefix("mapped:") {
|
||||
let chars: Vec<char> = mapped.chars().collect();
|
||||
return if chars.len() == 1 {
|
||||
Ok(KeyCode::Char(chars[0]))
|
||||
} else {
|
||||
Err(serde::de::Error::custom(format!(
|
||||
"invalid KeyCode string {}",
|
||||
s
|
||||
)))
|
||||
};
|
||||
}
|
||||
|
||||
let chars: Vec<char> = s.chars().collect();
|
||||
if chars.len() == 1 {
|
||||
let k = KeyCode::Char(chars[0]);
|
||||
if let Some(phys) = k.to_phys() {
|
||||
Ok(KeyCode::Physical(phys))
|
||||
} else {
|
||||
Ok(k)
|
||||
}
|
||||
} else {
|
||||
Err(serde::de::Error::custom(format!(
|
||||
"invalid KeyCode string {}",
|
||||
s
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ser_modifiers<S>(mods: &Modifiers, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
|
@ -13,6 +13,7 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
|
||||
#### New
|
||||
#### Changed
|
||||
* Default key assignments are `mapped:` again. A new [key_map_preference](config/lua/config/key_map_preference.md) option allows the defaults to use `"Mapped"` or `"Physical"`.
|
||||
* Disabled ligatures for `"Monaco"` and `"Menlo"` fonts, as those ligatures match even for words such as `find`. [#1786](https://github.com/wez/wezterm/issues/1786) [#1736](https://github.com/wez/wezterm/issues/1736)
|
||||
#### Updated and Improved
|
||||
* Bundled harfbuzz to 4.1.0
|
||||
|
@ -275,6 +275,15 @@ your config, you will need to change it to either
|
||||
`{key="N", mods="CMD|SHIFT", ..}` or `{key="mapped:N", mods="CMD", ..}`
|
||||
in order to continue to respect the `SHIFT` modifier.
|
||||
|
||||
*Since: nightly builds only*
|
||||
|
||||
A new `key_map_preference` option controls how keys without an explicit `phys:`
|
||||
or `mapped:` prefix are treated. If `key_map_preference = "Mapped"` (the
|
||||
default), then `mapped:` is assumed. If `key_map_preference = "Physical"` then
|
||||
`phys:` is assumed.
|
||||
|
||||
The default key assignments will respect `key_map_preference`.
|
||||
|
||||
### Leader Key
|
||||
|
||||
*Since: 20201031-154415-9614e117*
|
||||
|
11
docs/config/lua/config/key_map_preference.md
Normal file
11
docs/config/lua/config/key_map_preference.md
Normal file
@ -0,0 +1,11 @@
|
||||
# `key_map_preference = "Mapped"`
|
||||
|
||||
*Since: nightly builds only*
|
||||
|
||||
Controls how keys without an explicit `phys:` or `mapped:` prefix are treated.
|
||||
|
||||
If `key_map_preference = "Mapped"` (the default), then `mapped:` is assumed. If
|
||||
`key_map_preference = "Physical"` then `phys:` is assumed.
|
||||
|
||||
Default key assignments also respect `key_map_preference`.
|
||||
|
@ -2032,7 +2032,9 @@ impl TermWindow {
|
||||
SendKey(key) => {
|
||||
use keyevent::{window_mods_to_termwiz_mods, Key};
|
||||
let mods = window_mods_to_termwiz_mods(key.mods);
|
||||
if let Key::Code(key) = self.win_key_code_to_termwiz_key_code(&key.key) {
|
||||
if let Key::Code(key) = self.win_key_code_to_termwiz_key_code(
|
||||
&key.key.resolve(self.config.key_map_preference),
|
||||
) {
|
||||
pane.key_down(key, mods)?;
|
||||
}
|
||||
}
|
||||
|
@ -618,7 +618,11 @@ impl PhysKeyCode {
|
||||
macro_rules! m {
|
||||
($($val:ident),* $(,)?) => {
|
||||
$(
|
||||
map.insert(stringify!($val).to_string(), PhysKeyCode::$val);
|
||||
let key = stringify!($val).to_string();
|
||||
if key.len() == 1 {
|
||||
map.insert(key.to_ascii_lowercase(), PhysKeyCode::$val);
|
||||
}
|
||||
map.insert(key, PhysKeyCode::$val);
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user