Merge pull request #93 from k0kubun/mode

Support modal remapping
This commit is contained in:
Takashi Kokubun 2022-06-21 21:32:40 -07:00 committed by GitHub
commit 18ee84e934
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 57 additions and 3 deletions

View File

@ -16,6 +16,8 @@ pub enum Action {
Remap(Remap), Remap(Remap),
#[serde(deserialize_with = "deserialize_launch")] #[serde(deserialize_with = "deserialize_launch")]
Launch(Vec<String>), Launch(Vec<String>),
#[serde(deserialize_with = "deserialize_set_mode")]
SetMode(String),
#[serde(deserialize_with = "deserialize_set_mark")] #[serde(deserialize_with = "deserialize_set_mark")]
SetMark(bool), SetMark(bool),
#[serde(deserialize_with = "deserialize_with_mark")] #[serde(deserialize_with = "deserialize_with_mark")]
@ -48,6 +50,19 @@ where
Err(de::Error::custom("not a map with a single \"launch\" key")) Err(de::Error::custom("not a map with a single \"launch\" key"))
} }
fn deserialize_set_mode<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
let mut action = HashMap::<String, String>::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<bool, D::Error> fn deserialize_set_mark<'de, D>(deserializer: D) -> Result<bool, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,

View File

@ -10,7 +10,7 @@ pub struct Application {
pub not: Option<Vec<String>>, pub not: Option<Vec<String>>,
} }
fn deserialize_string_or_vec<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error> pub fn deserialize_string_or_vec<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {

View File

@ -1,4 +1,5 @@
use crate::config::action::{Action, Actions}; use crate::config::action::{Action, Actions};
use crate::config::application::deserialize_string_or_vec;
use crate::config::application::Application; use crate::config::application::Application;
use crate::config::key_press::{KeyPress, Modifier, ModifierState}; use crate::config::key_press::{KeyPress, Modifier, ModifierState};
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
@ -12,6 +13,8 @@ pub struct Keymap {
#[serde(deserialize_with = "deserialize_remap")] #[serde(deserialize_with = "deserialize_remap")]
pub remap: HashMap<KeyPress, Vec<Action>>, pub remap: HashMap<KeyPress, Vec<Action>>,
pub application: Option<Application>, pub application: Option<Application>,
#[serde(default, deserialize_with = "deserialize_string_or_vec")]
pub mode: Option<Vec<String>>,
} }
fn deserialize_remap<'de, D>(deserializer: D) -> Result<HashMap<KeyPress, Vec<Action>>, D::Error> fn deserialize_remap<'de, D>(deserializer: D) -> Result<HashMap<KeyPress, Vec<Action>>, D::Error>

View File

@ -25,6 +25,8 @@ pub struct Config {
pub modmap: Vec<Modmap>, pub modmap: Vec<Modmap>,
#[serde(default = "Vec::new")] #[serde(default = "Vec::new")]
pub keymap: Vec<Keymap>, pub keymap: Vec<Keymap>,
#[serde(default = "default_mode")]
pub default_mode: String,
#[serde(skip)] #[serde(skip)]
pub modify_time: Option<SystemTime>, pub modify_time: Option<SystemTime>,
} }
@ -49,3 +51,7 @@ pub fn config_watcher(watch: bool, file: &Path) -> anyhow::Result<Option<Inotify
Ok(None) Ok(None)
} }
} }
fn default_mode() -> String {
"default".to_string()
}

View File

@ -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] #[test]
fn test_keymap_mark() { fn test_keymap_mark() {
assert_parse(indoc! {" assert_parse(indoc! {"

View File

@ -40,6 +40,8 @@ pub struct EventHandler {
override_timer: TimerFd, override_timer: TimerFd,
// Whether we've called a sigaction for spawing commands or not // Whether we've called a sigaction for spawing commands or not
sigaction_set: bool, sigaction_set: bool,
// { set_mode: String }
mode: String,
// { set_mark: true } // { set_mark: true }
mark_set: bool, mark_set: bool,
// { escape_next_key: true } // { escape_next_key: true }
@ -47,7 +49,7 @@ pub struct EventHandler {
} }
impl EventHandler { impl EventHandler {
pub fn new(device: VirtualDevice, timer: TimerFd) -> EventHandler { pub fn new(device: VirtualDevice, timer: TimerFd, mode: &str) -> EventHandler {
EventHandler { EventHandler {
device, device,
shift: PressState::new(), shift: PressState::new(),
@ -62,6 +64,7 @@ impl EventHandler {
override_timeout_key: None, override_timeout_key: None,
override_timer: timer, override_timer: timer,
sigaction_set: false, sigaction_set: false,
mode: mode.to_string(),
mark_set: false, mark_set: false,
escape_next_key: false, escape_next_key: false,
} }
@ -239,6 +242,11 @@ impl EventHandler {
continue; continue;
} }
} }
if let Some(modes) = &keymap.mode {
if !modes.contains(&self.mode) {
continue;
}
}
return Ok(Some(actions.to_vec())); return Ok(Some(actions.to_vec()));
} }
} }
@ -264,6 +272,10 @@ impl EventHandler {
} }
} }
Action::Launch(command) => self.run_command(command.clone()), 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::SetMark(set) => self.mark_set = *set,
Action::WithMark(key_press) => self.send_key_press(&self.with_mark(key_press))?, 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, Action::EscapeNextKey(escape_next_key) => self.escape_next_key = *escape_next_key,

View File

@ -100,7 +100,7 @@ fn main() -> anyhow::Result<()> {
}; };
let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty())?; let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty())?;
let timer_fd = timer.as_raw_fd(); 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) { let mut input_devices = match get_input_devices(&device_filter, &ignore_filter, watch_devices) {
Ok(input_devices) => input_devices, Ok(input_devices) => input_devices,
Err(e) => bail!("Failed to prepare input devices: {}", e), Err(e) => bail!("Failed to prepare input devices: {}", e),