From 27382516570e385eefe4edca088511ab96f87728 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Fri, 6 May 2022 21:54:48 -0700 Subject: [PATCH] Support modal remapping --- src/config/action.rs | 15 +++++++++++++++ src/config/application.rs | 2 +- src/config/keymap.rs | 3 +++ src/config/mod.rs | 6 ++++++ src/config/tests.rs | 18 ++++++++++++++++++ src/event_handler.rs | 14 +++++++++++++- src/main.rs | 2 +- 7 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/config/action.rs b/src/config/action.rs index e6834e1..9096be9 100644 --- a/src/config/action.rs +++ b/src/config/action.rs @@ -16,6 +16,8 @@ pub enum Action { Remap(Remap), #[serde(deserialize_with = "deserialize_launch")] Launch(Vec), + #[serde(deserialize_with = "deserialize_set_mode")] + SetMode(String), #[serde(deserialize_with = "deserialize_set_mark")] SetMark(bool), #[serde(deserialize_with = "deserialize_with_mark")] @@ -48,6 +50,19 @@ where Err(de::Error::custom("not a map with a single \"launch\" key")) } +fn deserialize_set_mode<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let mut action = HashMap::::deserialize(deserializer)?; + if let Some(set) = action.remove("set_mode") { + if action.is_empty() { + return Ok(set); + } + } + Err(de::Error::custom("not a map with a single \"set_mode\" key")) +} + fn deserialize_set_mark<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, diff --git a/src/config/application.rs b/src/config/application.rs index aae16d9..e8b8262 100644 --- a/src/config/application.rs +++ b/src/config/application.rs @@ -10,7 +10,7 @@ pub struct Application { pub not: Option>, } -fn deserialize_string_or_vec<'de, D>(deserializer: D) -> Result>, D::Error> +pub fn deserialize_string_or_vec<'de, D>(deserializer: D) -> Result>, D::Error> where D: Deserializer<'de>, { diff --git a/src/config/keymap.rs b/src/config/keymap.rs index 69209e4..0c3cc74 100644 --- a/src/config/keymap.rs +++ b/src/config/keymap.rs @@ -1,4 +1,5 @@ use crate::config::action::{Action, Actions}; +use crate::config::application::deserialize_string_or_vec; use crate::config::application::Application; use crate::config::key_press::{KeyPress, Modifier, ModifierState}; use serde::{Deserialize, Deserializer}; @@ -12,6 +13,8 @@ pub struct Keymap { #[serde(deserialize_with = "deserialize_remap")] pub remap: HashMap>, pub application: Option, + #[serde(default, deserialize_with = "deserialize_string_or_vec")] + pub mode: Option>, } fn deserialize_remap<'de, D>(deserializer: D) -> Result>, D::Error> diff --git a/src/config/mod.rs b/src/config/mod.rs index 31b840f..9c18530 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -25,6 +25,8 @@ pub struct Config { pub modmap: Vec, #[serde(default = "Vec::new")] pub keymap: Vec, + #[serde(default = "default_mode")] + pub default_mode: String, #[serde(skip)] pub modify_time: Option, } @@ -49,3 +51,7 @@ pub fn config_watcher(watch: bool, file: &Path) -> anyhow::Result String { + "default".to_string() +} diff --git a/src/config/tests.rs b/src/config/tests.rs index 56f4ff0..8c0dcb9 100644 --- a/src/config/tests.rs +++ b/src/config/tests.rs @@ -127,6 +127,24 @@ fn test_keymap_launch() { "#}) } +#[test] +fn test_keymap_mode() { + assert_parse(indoc! {" + default_mode: insert + keymap: + - mode: insert + remap: + Esc: { set_mode: normal } + - mode: normal + remap: + i: { set_mode: insert } + h: Left + j: Down + k: Up + l: Right + "}) +} + #[test] fn test_keymap_mark() { assert_parse(indoc! {" diff --git a/src/event_handler.rs b/src/event_handler.rs index 2935a59..569612b 100644 --- a/src/event_handler.rs +++ b/src/event_handler.rs @@ -40,6 +40,8 @@ pub struct EventHandler { override_timer: TimerFd, // Whether we've called a sigaction for spawing commands or not sigaction_set: bool, + // { set_mode: String } + mode: String, // { set_mark: true } mark_set: bool, // { escape_next_key: true } @@ -47,7 +49,7 @@ pub struct EventHandler { } impl EventHandler { - pub fn new(device: VirtualDevice, timer: TimerFd) -> EventHandler { + pub fn new(device: VirtualDevice, timer: TimerFd, mode: &str) -> EventHandler { EventHandler { device, shift: PressState::new(), @@ -62,6 +64,7 @@ impl EventHandler { override_timeout_key: None, override_timer: timer, sigaction_set: false, + mode: mode.to_string(), mark_set: false, escape_next_key: false, } @@ -239,6 +242,11 @@ impl EventHandler { continue; } } + if let Some(modes) = &keymap.mode { + if !modes.contains(&self.mode) { + continue; + } + } return Ok(Some(actions.to_vec())); } } @@ -264,6 +272,10 @@ impl EventHandler { } } Action::Launch(command) => self.run_command(command.clone()), + Action::SetMode(mode) => { + self.mode = mode.clone(); + println!("mode: {}", mode); + } Action::SetMark(set) => self.mark_set = *set, Action::WithMark(key_press) => self.send_key_press(&self.with_mark(key_press))?, Action::EscapeNextKey(escape_next_key) => self.escape_next_key = *escape_next_key, diff --git a/src/main.rs b/src/main.rs index 8b65b77..659ab35 100644 --- a/src/main.rs +++ b/src/main.rs @@ -100,7 +100,7 @@ fn main() -> anyhow::Result<()> { }; let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty())?; let timer_fd = timer.as_raw_fd(); - let mut handler = EventHandler::new(output_device, timer); + let mut handler = EventHandler::new(output_device, timer, &config.default_mode); let mut input_devices = match get_input_devices(&device_filter, &ignore_filter, watch_devices) { Ok(input_devices) => input_devices, Err(e) => bail!("Failed to prepare input devices: {}", e),