From 31beaabe6b2cf4119aacae6c1722cdc1e5ba2f5b Mon Sep 17 00:00:00 2001 From: Jeff Zhao Date: Tue, 29 Aug 2023 10:16:53 -0400 Subject: command chaining support - breaks existing keymap configs -`command` field is renamed to `commands` - now an array instead of a single string --- src/config/keymap/keymapping.rs | 87 ++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 36 deletions(-) (limited to 'src/config/keymap/keymapping.rs') diff --git a/src/config/keymap/keymapping.rs b/src/config/keymap/keymapping.rs index 0b3e122..33c7407 100644 --- a/src/config/keymap/keymapping.rs +++ b/src/config/keymap/keymapping.rs @@ -8,7 +8,7 @@ use termion::event::Event; use crate::config::{parse_config_or_default, TomlConfigFile}; use crate::error::JoshutoResult; -use crate::key_command::{AppCommand, Command, CommandKeybind}; +use crate::key_command::{Command, CommandKeybind}; use crate::traits::ToString; use crate::util::keyparse::str_to_event; @@ -20,9 +20,9 @@ enum KeymapError { #[derive(Clone, Debug, Deserialize)] struct CommandKeymap { - pub command: String, - pub description: Option, pub keys: Vec, + pub commands: Vec, + pub description: Option, } #[derive(Clone, Debug, Deserialize)] @@ -63,38 +63,53 @@ impl AppKeyMapping { } } -fn vec_to_map(vec: &[CommandKeymap]) -> HashMap { +fn command_keymaps_vec_to_map(keymaps: &[CommandKeymap]) -> HashMap { let mut hashmap = HashMap::new(); - for m in vec { - match Command::from_str(m.command.as_str()) { - Ok(command) => { - let events: Vec = m - .keys - .iter() - .filter_map(|s| str_to_event(s.as_str())) - .collect(); - - if events.len() != m.keys.len() { - eprintln!("Failed to parse events: {:?}", m.keys); - continue; + for keymap in keymaps { + if keymap.commands.is_empty() { + eprintln!("Keymap `commands` cannot be empty"); + continue; + } + let commands: Vec = keymap + .commands + .iter() + .filter_map(|cmd_str| match Command::from_str(cmd_str) { + Ok(s) => Some(s), + Err(err) => { + eprintln!("Keymap error: {}", err); + None } + }) + .collect(); + + if commands.len() != keymap.commands.len() { + eprintln!("Failed to parse commands: {:?}", keymap.commands); + continue; + } + + let key_events: Vec = keymap + .keys + .iter() + .filter_map(|s| str_to_event(s.as_str())) + .collect(); + + if key_events.len() != keymap.keys.len() { + eprintln!("Failed to parse keys: {:?}", keymap.keys); + continue; + } - let command_str = command.command(); - let command_description = m.description.to_owned(); - let result = insert_keycommand(&mut hashmap, command, command_description, &events); - match result { - Ok(_) => {} - Err(e) => match e { - KeymapError::Conflict => { - let events_str: Vec = - events.iter().map(|e| e.to_string()).collect(); - eprintln!("Error: Ambiguous Keymapping: Multiple commands mapped to key sequence {:?} {}", events_str, command_str); - } - }, + let command_description = keymap.description.to_owned(); + if let Err(err) = + insert_keycommand(&mut hashmap, commands, command_description, &key_events) + { + match err { + KeymapError::Conflict => { + let events_str: Vec = + key_events.iter().map(|e| e.to_string()).collect(); + eprintln!("Error: Ambiguous Keymapping: Multiple commands mapped to key sequence {:?} {:?}", events_str, keymap.commands); } } - Err(e) => eprintln!("Keymap error: {}", e), } } hashmap @@ -103,9 +118,9 @@ fn vec_to_map(vec: &[CommandKeymap]) -> HashMap { impl From for AppKeyMapping { fn from(raw: AppKeyMappingRaw) -> Self { let mut keymaps = Self::new(); - keymaps.default_view = vec_to_map(&raw.default_view.keymap); - keymaps.task_view = vec_to_map(&raw.task_view.keymap); - keymaps.help_view = vec_to_map(&raw.help_view.keymap); + keymaps.default_view = command_keymaps_vec_to_map(&raw.default_view.keymap); + keymaps.task_view = command_keymaps_vec_to_map(&raw.task_view.keymap); + keymaps.help_view = command_keymaps_vec_to_map(&raw.help_view.keymap); keymaps } } @@ -126,7 +141,7 @@ impl std::default::Default for AppKeyMapping { fn insert_keycommand( keymap: &mut KeyMapping, - keycommand: Command, + commands: Vec, description: Option, events: &[Event], ) -> Result<(), KeymapError> { @@ -140,7 +155,7 @@ fn insert_keycommand( match keymap.entry(event) { Entry::Occupied(_) => return Err(KeymapError::Conflict), Entry::Vacant(entry) => entry.insert(CommandKeybind::SimpleKeybind { - command: keycommand, + commands, description, }), }; @@ -150,13 +165,13 @@ fn insert_keycommand( match keymap.entry(event) { Entry::Occupied(mut entry) => match entry.get_mut() { CommandKeybind::CompositeKeybind(ref mut m) => { - insert_keycommand(m, keycommand, description, &events[1..]) + insert_keycommand(m, commands, description, &events[1..]) } _ => Err(KeymapError::Conflict), }, Entry::Vacant(entry) => { let mut new_map = KeyMapping::new(); - let result = insert_keycommand(&mut new_map, keycommand, description, &events[1..]); + let result = insert_keycommand(&mut new_map, commands, description, &events[1..]); if result.is_ok() { let composite_command = CommandKeybind::CompositeKeybind(new_map); entry.insert(composite_command); -- cgit v1.2.3