From a7f603361a82d6c374247c24297cda87650ef9cf Mon Sep 17 00:00:00 2001 From: Matthew Cheely Date: Fri, 23 Sep 2022 23:03:56 -0400 Subject: [PATCH] Add support for labels on typable commands --- helix-term/src/config.rs | 38 ++++++++++++++++++++++++++++++++++++++ helix-term/src/keymap.rs | 28 +++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/helix-term/src/config.rs b/helix-term/src/config.rs index 91738f3ef..92b4fb856 100644 --- a/helix-term/src/config.rs +++ b/helix-term/src/config.rs @@ -207,6 +207,44 @@ mod tests { ); } + #[test] + fn parsing_typable_commands() { + use crate::keymap; + use crate::keymap::MappableCommand; + use helix_view::document::Mode; + use helix_view::input::KeyEvent; + use std::str::FromStr; + + let sample_keymaps = r#" + [keys.normal] + o = { label = "Edit Config", command = ":open ~/.config" } + c = ":buffer-close" + "#; + + let config = toml::from_str::(sample_keymaps).unwrap(); + + let tree = config.keys.get(&Mode::Normal).unwrap().root(); + + if let keymap::KeyTrie::Node(node) = tree { + let open_node = node.get(&KeyEvent::from_str("o").unwrap()).unwrap(); + + if let keymap::KeyTrie::Leaf(MappableCommand::Typable { doc, .. }) = open_node { + assert_eq!(doc, "Edit Config"); + } else { + panic!("Edit Config did not parse to typable command"); + } + + let close_node = node.get(&KeyEvent::from_str("c").unwrap()).unwrap(); + if let keymap::KeyTrie::Leaf(MappableCommand::Typable { doc, .. }) = close_node { + assert_eq!(doc, ":buffer-close []"); + } else { + panic!(":buffer-close command did not parse to typable command"); + } + } else { + panic!("Config did not parse to trie"); + } + } + #[test] fn keys_resolve_to_correct_defaults() { // From serde default diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index ccb293a35..3dbb635d0 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -197,13 +197,15 @@ impl<'de> serde::de::Visitor<'de> for KeyTrieVisitor { where M: serde::de::MapAccess<'de>, { - let mut name = ""; + let mut label = ""; + let mut command = None; let mut mapping = HashMap::new(); let mut order = Vec::new(); while let Some(key) = map.next_key::<&str>()? { match key { - "label" => name = map.next_value::<&str>()?, + "label" => label = map.next_value::<&str>()?, + "command" => command = Some(map.next_value::()?), _ => { let key_event = key.parse::().map_err(serde::de::Error::custom)?; let key_trie = map.next_value::()?; @@ -212,7 +214,27 @@ impl<'de> serde::de::Visitor<'de> for KeyTrieVisitor { } } } - Ok(KeyTrie::Node(KeyTrieNode::new(name, mapping, order))) + + match command { + None => Ok(KeyTrie::Node(KeyTrieNode::new(label, mapping, order))), + Some(cmd) => { + if label.is_empty() { + Ok(KeyTrie::Leaf(cmd)) + } else { + match cmd { + MappableCommand::Typable { name, args, .. } => { + Ok(MappableCommand::Typable { + name, + args, + doc: label.to_string(), + }) + .map(KeyTrie::Leaf) + } + MappableCommand::Static { .. } => Ok(KeyTrie::Leaf(cmd)), + } + } + } + } } }