diff options
author | Matouš Dzivjak | 2022-02-17 05:03:11 +0000 |
---|---|---|
committer | GitHub | 2022-02-17 05:03:11 +0000 |
commit | afec54485a3be29ff1172f70157a183853273420 (patch) | |
tree | 9612658764e105970cba22c2e4c26b0be7be942a /helix-term/src/keymap.rs | |
parent | 24f90ba8d8f4a10fb18f71b05c278fe89b71a261 (diff) |
feat(commands): command palette (#1400)
* feat(commands): command palette
Add new command to display command pallete that can be used
to discover and execute available commands.
Fixes: https://github.com/helix-editor/helix/issues/559
* Make picker take the whole context, not just editor
* Bind command pallete
* Typable commands also in the palette
* Show key bindings for commands
* Fix tests, small refactor
* Refactor keymap mapping, fix typo
* Ignore sequence key bindings for now
* Apply suggestions
* Fix lint issues in tests
* Fix after rebase
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Diffstat (limited to 'helix-term/src/keymap.rs')
-rw-r--r-- | helix-term/src/keymap.rs | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index f414f797..0147f58e 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -343,13 +343,46 @@ pub struct Keymap { impl Keymap { pub fn new(root: KeyTrie) -> Self { - Self { + Keymap { root, state: Vec::new(), sticky: None, } } + pub fn reverse_map(&self) -> HashMap<String, Vec<Vec<KeyEvent>>> { + // recursively visit all nodes in keymap + fn map_node( + cmd_map: &mut HashMap<String, Vec<Vec<KeyEvent>>>, + node: &KeyTrie, + keys: &mut Vec<KeyEvent>, + ) { + match node { + KeyTrie::Leaf(cmd) => match cmd { + MappableCommand::Typable { name, .. } => { + cmd_map.entry(name.into()).or_default().push(keys.clone()) + } + MappableCommand::Static { name, .. } => cmd_map + .entry(name.to_string()) + .or_default() + .push(keys.clone()), + }, + KeyTrie::Node(next) => { + for (key, trie) in &next.map { + keys.push(*key); + map_node(cmd_map, trie, keys); + keys.pop(); + } + } + KeyTrie::Sequence(_) => {} + }; + } + + let mut res = HashMap::new(); + map_node(&mut res, &self.root, &mut Vec::new()); + res + } + pub fn root(&self) -> &KeyTrie { &self.root } @@ -706,6 +739,7 @@ impl Default for Keymaps { "/" => global_search, "k" => hover, "r" => rename_symbol, + "?" => command_palette, }, "z" => { "View" "z" | "c" => align_view_center, @@ -958,4 +992,45 @@ mod tests { "Mismatch for view mode on `z` and `Z`" ); } + + #[test] + fn reverse_map() { + let normal_mode = keymap!({ "Normal mode" + "i" => insert_mode, + "g" => { "Goto" + "g" => goto_file_start, + "e" => goto_file_end, + }, + "j" | "k" => move_line_down, + }); + let keymap = Keymap::new(normal_mode); + let mut reverse_map = keymap.reverse_map(); + + // sort keybindings in order to have consistent tests + // HashMaps can be compared but we can still get different ordering of bindings + // for commands that have multiple bindings assigned + for v in reverse_map.values_mut() { + v.sort() + } + + assert_eq!( + reverse_map, + HashMap::from([ + ("insert_mode".to_string(), vec![vec![key!('i')]]), + ( + "goto_file_start".to_string(), + vec![vec![key!('g'), key!('g')]] + ), + ( + "goto_file_end".to_string(), + vec![vec![key!('g'), key!('e')]] + ), + ( + "move_line_down".to_string(), + vec![vec![key!('j')], vec![key!('k')]] + ), + ]), + "Mistmatch" + ) + } } |