@@ -1,7 +1,7 @@
1pub use crate::commands::Command;
1pub use crate::commands::Command;
2use crate::config::Config;
2use crate::config::Config;
3use helix_core::hashmap;
3use helix_core::hashmap;
4−use helix_view::{document::Mode, input::KeyEvent};
4+use helix_view::{document::Mode, info::Info, input::KeyEvent};
5use serde::Deserialize;
5use serde::Deserialize;
7 collections::HashMap,
7 collections::HashMap,
@@ -24,30 +24,276 @@ macro_rules! key {
27+/// Macro for defining the root of a `Keymap` object. Example:
30+/// # use helix_core::hashmap;
31+/// # use helix_term::keymap;
32+/// # use helix_term::keymap::Keymap;
33+/// let normal_mode = keymap!({ "Normal mode"
34+/// "i" => insert_mode,
36+/// "g" => goto_file_start,
37+/// "e" => goto_file_end,
39+/// "j" | "down" => move_line_down,
41+/// let keymap = Keymap::new(normal_mode);
27−macro_rules! ctrl {
44+macro_rules! keymap {
45+ (@trie $cmd:ident) => {
46+ $crate::keymap::KeyTrie::Leaf($crate::commands::Command::$cmd)
50+ { $label:literal $($($key:literal)|+ => $value:tt,)+ }
28− ($($ch:tt)*) => {
51+ ) => {
29− KeyEvent {
52+ keymap!({ $label $($($key)|+ => $value,)+ })
30− code: ::helix_view::keyboard::KeyCode::Char($($ch)*),
53+ };
31− modifiers: ::helix_view::keyboard::KeyModifiers::CONTROL,
54+
56+ { $label:literal $($($key:literal)|+ => $value:tt,)+ }
58+ // modified from the hashmap! macro
60+ let _cap = hashmap!(@count $($($key),+),*);
61+ let mut _map = ::std::collections::HashMap::with_capacity(_cap);
62+ let mut _order = ::std::vec::Vec::with_capacity(_cap);
65+ let _key = $key.parse::<::helix_view::input::KeyEvent>().unwrap();
68+ keymap!(@trie $value)
73+ $crate::keymap::KeyTrie::Node($crate::keymap::KeyTrieNode::new($label, _map, _order))
36−macro_rules! alt {
78+#[derive(Debug, Clone, Deserialize)]
37− ($($ch:tt)*) => {
79+pub struct KeyTrieNode {
38− KeyEvent {
80+ /// A label for keys coming under this node, like "Goto mode"
39− code: ::helix_view::keyboard::KeyCode::Char($($ch)*),
81+ #[serde(skip)]
40− modifiers: ::helix_view::keyboard::KeyModifiers::ALT,
82+ name: String,
84+ map: HashMap<KeyEvent, KeyTrie>,
86+ order: Vec<KeyEvent>,
90+ pub fn new(name: &str, map: HashMap<KeyEvent, KeyTrie>, order: Vec<KeyEvent>) -> Self {
92+ name: name.to_string(),
98+ pub fn name(&self) -> &str {
102+ /// Merge another Node in. Leaves and subnodes from the other node replace
103+ /// corresponding keyevent in self, except when both other and self have
104+ /// subnodes for same key. In that case the merge is recursive.
105+ pub fn merge(&mut self, mut other: Self) {
106+ for (key, trie) in std::mem::take(&mut other.map) {
107+ if let Some(KeyTrie::Node(node)) = self.map.get_mut(&key) {
108+ if let KeyTrie::Node(other_node) = trie {
109+ node.merge(other_node);
113+ self.map.insert(key, trie);
116+ for &key in self.map.keys() {
117+ if !self.order.contains(&key) {
118+ self.order.push(key);
124+impl From<KeyTrieNode> for Info {
125+ fn from(node: KeyTrieNode) -> Self {
126+ let mut body: Vec<(&str, Vec<KeyEvent>)> = Vec::with_capacity(node.len());
127+ for (&key, trie) in node.iter() {
128+ let desc = match trie {
129+ KeyTrie::Leaf(cmd) => cmd.doc(),
130+ KeyTrie::Node(n) => n.name(),
132+ match body.iter().position(|(d, _)| d == &desc) {
133+ // FIXME: multiple keys are ordered randomly (use BTreeSet)
134+ Some(pos) => body[pos].1.push(key),
135+ None => body.push((desc, vec![key])),
138+ body.sort_unstable_by_key(|(_, keys)| {
139+ node.order.iter().position(|&k| k == keys[0]).unwrap()
141+ let prefix = format!("{} ", node.name());
142+ if body.iter().all(|(desc, _)| desc.starts_with(&prefix)) {
145+ .map(|(desc, keys)| (desc.strip_prefix(&prefix).unwrap(), keys))
148+ Info::key(node.name(), body)
152+impl Default for KeyTrieNode {
153+ fn default() -> Self {
154+ Self::new("", HashMap::new(), Vec::new())
158+impl PartialEq for KeyTrieNode {
159+ fn eq(&self, other: &Self) -> bool {
160+ self.map == other.map
164+impl Deref for KeyTrieNode {
165+ type Target = HashMap<KeyEvent, KeyTrie>;
167+ fn deref(&self) -> &Self::Target {
172+impl DerefMut for KeyTrieNode {
173+ fn deref_mut(&mut self) -> &mut Self::Target {
178+#[derive(Debug, Clone, PartialEq, Deserialize)]
186+ pub fn node(&self) -> Option<&KeyTrieNode> {
188+ KeyTrie::Node(ref node) => Some(node),
189+ KeyTrie::Leaf(_) => None,
193+ pub fn node_mut(&mut self) -> Option<&mut KeyTrieNode> {
195+ KeyTrie::Node(ref mut node) => Some(node),
196+ KeyTrie::Leaf(_) => None,
200+ /// Merge another KeyTrie in, assuming that this KeyTrie and the other
201+ /// are both Nodes. Panics otherwise.
202+ pub fn merge_nodes(&mut self, mut other: Self) {
203+ let node = std::mem::take(other.node_mut().unwrap());
204+ self.node_mut().unwrap().merge(node);
207+ pub fn search(&self, keys: &[KeyEvent]) -> Option<&KeyTrie> {
208+ let mut trie = self;
211+ KeyTrie::Node(map) => map.get(key),
212+ // leaf encountered while keys left to process
213+ KeyTrie::Leaf(_) => None,
220+#[derive(Debug, Clone, PartialEq)]
221+pub enum KeymapResult {
222+ /// Needs more keys to execute a command. Contains valid keys for next keystroke.
223+ Pending(KeyTrieNode),
225+ /// Key was not found in the root keymap
227+ /// Key is invalid in combination with previous keys. Contains keys leading upto
228+ /// and including current (invalid) key.
229+ Cancelled(Vec<KeyEvent>),
232+#[derive(Debug, Clone, PartialEq, Deserialize)]
238+ state: Vec<KeyEvent>,
242+ pub fn new(root: KeyTrie) -> Self {
249+ pub fn root(&self) -> &KeyTrie {
253+ /// Lookup `key` in the keymap to try and find a command to execute
254+ pub fn get(&mut self, key: KeyEvent) -> KeymapResult {
255+ let &first = self.state.get(0).unwrap_or(&key);
256+ let trie = match self.root.search(&[first]) {
257+ Some(&KeyTrie::Leaf(cmd)) => return KeymapResult::Matched(cmd),
258+ None => return KeymapResult::NotFound,
261+ self.state.push(key);
262+ match trie.search(&self.state[1..]) {
263+ Some(&KeyTrie::Node(ref map)) => KeymapResult::Pending(map.clone()),
264+ Some(&KeyTrie::Leaf(command)) => {
266+ KeymapResult::Matched(command)
268+ None => KeymapResult::Cancelled(self.state.drain(..).collect()),
272+ pub fn merge(&mut self, other: Self) {
273+ self.root.merge_nodes(other.root);
277+impl Deref for Keymap {
278+ type Target = KeyTrieNode;
280+ fn deref(&self) -> &Self::Target {
281+ &self.root.node().unwrap()
285+impl Default for Keymap {
286+ fn default() -> Self {
287+ Self::new(KeyTrie::Node(KeyTrieNode::default()))
45#[derive(Debug, Clone, PartialEq, Deserialize)]
291#[derive(Debug, Clone, PartialEq, Deserialize)]
46#[serde(transparent)]
292#[serde(transparent)]
47−pub struct Keymaps(pub HashMap<Mode, HashMap<KeyEvent, Command>>);
293+pub struct Keymaps(pub HashMap<Mode, Keymap>);
49impl Deref for Keymaps {
295impl Deref for Keymaps {
50− type Target = HashMap<Mode, HashMap<KeyEvent, Command>>;
296+ type Target = HashMap<Mode, Keymap>;
52 fn deref(&self) -> &Self::Target {
298 fn deref(&self) -> &Self::Target {
@@ -62,252 +308,298 @@ impl DerefMut for Keymaps {
63impl Default for Keymaps {
309impl Default for Keymaps {
64 fn default() -> Keymaps {
310 fn default() -> Keymaps {
65− let normal = hashmap!(
311+ let normal = keymap!({ "Normal mode"
66− key!('h') => Command::move_char_left,
312+ "h" | "left" => move_char_left,
67− key!('j') => Command::move_line_down,
313+ "j" | "down" => move_line_down,
68− key!('k') => Command::move_line_up,
314+ "k" | "up" => move_line_up,
69− key!('l') => Command::move_char_right,
71− key!(Left) => Command::move_char_left,
72− key!(Down) => Command::move_line_down,
73− key!(Up) => Command::move_line_up,
74− key!(Right) => Command::move_char_right,
315+ "l" | "right" => move_char_right,
76− key!('t') => Command::find_till_char,
317+ "t" => find_till_char,
77− key!('f') => Command::find_next_char,
318+ "f" => find_next_char,
78− key!('T') => Command::till_prev_char,
319+ "T" => till_prev_char,
79− key!('F') => Command::find_prev_char,
320+ "F" => find_prev_char,
80− // and matching set for select mode (extend)
82− key!('r') => Command::replace,
321+ "r" => replace,
83− key!('R') => Command::replace_with_yanked,
322+ "R" => replace_with_yanked,
85− key!('~') => Command::switch_case,
324+ "~" => switch_case,
86− alt!('`') => Command::switch_to_uppercase,
87− key!('`') => Command::switch_to_lowercase,
325+ "`" => switch_to_lowercase,
88−
326+ "A-`" => switch_to_uppercase,
89− key!(Home) => Command::goto_line_start,
328+ "home" => goto_line_start,
90− key!(End) => Command::goto_line_end,
329+ "end" => goto_line_end,
92− key!('w') => Command::move_next_word_start,
331+ "w" => move_next_word_start,
93− key!('b') => Command::move_prev_word_start,
332+ "b" => move_prev_word_start,
94− key!('e') => Command::move_next_word_end,
333+ "e" => move_next_word_end,
96− key!('W') => Command::move_next_long_word_start,
335+ "W" => move_next_long_word_start,
97− key!('B') => Command::move_prev_long_word_start,
336+ "B" => move_prev_long_word_start,
98− key!('E') => Command::move_next_long_word_end,
337+ "E" => move_next_long_word_end,
100− key!('v') => Command::select_mode,
339+ "v" => select_mode,
101− key!('g') => Command::goto_mode,
340+ "g" => { "Goto"
341+ "g" => goto_file_start,
342+ "e" => goto_file_end,
343+ "h" => goto_line_start,
344+ "l" => goto_line_end,
345+ "s" => goto_first_nonwhitespace,
346+ "d" => goto_definition,
347+ "y" => goto_type_definition,
348+ "r" => goto_reference,
349+ "i" => goto_implementation,
350+ "t" => goto_window_top,
351+ "m" => goto_window_middle,
352+ "b" => goto_window_bottom,
353+ "a" => goto_last_accessed_file,
102− key!(':') => Command::command_mode,
355+ ":" => command_mode,
104− key!('i') => Command::insert_mode,
357+ "i" => insert_mode,
105− key!('I') => Command::prepend_to_line,
358+ "I" => prepend_to_line,
106− key!('a') => Command::append_mode,
359+ "a" => append_mode,
107− key!('A') => Command::append_to_line,
360+ "A" => append_to_line,
108− key!('o') => Command::open_below,
361+ "o" => open_below,
109− key!('O') => Command::open_above,
362+ "O" => open_above,
110 // [<space> ]<space> equivalents too (add blank new line, no edit)
363 // [<space> ]<space> equivalents too (add blank new line, no edit)
113− key!('d') => Command::delete_selection,
365+ "d" => delete_selection,
114 // TODO: also delete without yanking
366 // TODO: also delete without yanking
115− key!('c') => Command::change_selection,
367+ "c" => change_selection,
116 // TODO: also change delete without yanking
368 // TODO: also change delete without yanking
118− // key!('r') => Command::replace_with_char,
120− key!('s') => Command::select_regex,
370+ "s" => select_regex,
121− alt!('s') => Command::split_selection_on_newline,
371+ "A-s" => split_selection_on_newline,
122− key!('S') => Command::split_selection,
372+ "S" => split_selection,
123− key!(';') => Command::collapse_selection,
373+ ";" => collapse_selection,
124− alt!(';') => Command::flip_selections,
374+ "A-;" => flip_selections,
125− key!('%') => Command::select_all,
375+ "%" => select_all,
126− key!('x') => Command::extend_line,
376+ "x" => extend_line,
127− key!('X') => Command::extend_to_line_bounds,
377+ "X" => extend_to_line_bounds,
128 // crop_to_whole_line
378 // crop_to_whole_line
381+ "m" => match_brackets,
382+ "s" => surround_add,
383+ "r" => surround_replace,
384+ "d" => surround_delete,
385+ "a" => select_textobject_around,
386+ "i" => select_textobject_inner,
388+ "[" => { "Left bracket"
389+ "d" => goto_prev_diag,
390+ "D" => goto_first_diag,
392+ "]" => { "Right bracket"
393+ "d" => goto_next_diag,
394+ "D" => goto_last_diag,
131− key!('m') => Command::match_mode,
132− key!('[') => Command::left_bracket_mode,
133− key!(']') => Command::right_bracket_mode,
135− key!('/') => Command::search,
397+ "/" => search,
136 // ? for search_reverse
398 // ? for search_reverse
137− key!('n') => Command::search_next,
399+ "n" => search_next,
138− key!('N') => Command::extend_search_next,
400+ "N" => extend_search_next,
139 // N for search_prev
401 // N for search_prev
140− key!('*') => Command::search_selection,
402+ "*" => search_selection,
142− key!('u') => Command::undo,
404+ "u" => undo,
143− key!('U') => Command::redo,
405+ "U" => redo,
145− key!('y') => Command::yank,
407+ "y" => yank,
146 // yank_all
408 // yank_all
147− key!('p') => Command::paste_after,
409+ "p" => paste_after,
148 // paste_all
410 // paste_all
149− key!('P') => Command::paste_before,
411+ "P" => paste_before,
151− key!('>') => Command::indent,
413+ ">" => indent,
152− key!('<') => Command::unindent,
414+ "<" => unindent,
153− key!('=') => Command::format_selections,
415+ "=" => format_selections,
154− key!('J') => Command::join_selections,
416+ "J" => join_selections,
155 // TODO: conflicts hover/doc
417 // TODO: conflicts hover/doc
156− key!('K') => Command::keep_selections,
418+ "K" => keep_selections,
157 // TODO: and another method for inverse
419 // TODO: and another method for inverse
159 // TODO: clashes with space mode
421 // TODO: clashes with space mode
160− key!(' ') => Command::keep_primary_selection,
422+ "space" => keep_primary_selection,
162− // key!('q') => Command::record_macro,
424+ // "q" => record_macro,
163− // key!('Q') => Command::replay_macro,
425+ // "Q" => replay_macro,
165− // ~ / apostrophe => change case
166 // & align selections
427 // & align selections
167 // _ trim selections
428 // _ trim selections
169 // C / altC = copy (repeat) selections on prev/next lines
430 // C / altC = copy (repeat) selections on prev/next lines
171− key!(Esc) => Command::normal_mode,
432+ "esc" => normal_mode,
172− key!(PageUp) => Command::page_up,
173− key!(PageDown) => Command::page_down,
174− ctrl!('b') => Command::page_up,
433+ "C-b" | "pageup" => page_up,
175− ctrl!('f') => Command::page_down,
434+ "C-f" | "pagedown" => page_down,
176− ctrl!('u') => Command::half_page_up,
435+ "C-u" => half_page_up,
177− ctrl!('d') => Command::half_page_down,
436+ "C-d" => half_page_down,
179− ctrl!('w') => Command::window_mode,
438+ "C-w" => { "Window"
439+ "C-w" | "w" => rotate_view,
440+ "C-h" | "h" => hsplit,
441+ "C-v" | "v" => vsplit,
442+ "C-q" | "q" => wclose,
181 // move under <space>c
445 // move under <space>c
182− ctrl!('c') => Command::toggle_comments,
446+ "C-c" => toggle_comments,
183− key!('K') => Command::hover,
447+ "K" => hover,
185 // z family for save/restore/combine from/to sels from register
449 // z family for save/restore/combine from/to sels from register
187− // supposedly ctrl!('i') but did not work
451+ // supposedly "C-i" but did not work
188− key!(Tab) => Command::jump_forward,
452+ "tab" => jump_forward,
189− ctrl!('o') => Command::jump_backward,
453+ "C-o" => jump_backward,
190− // ctrl!('s') => Command::save_selection,
454+ // "C-s" => save_selection,
192− key!(' ') => Command::space_mode,
456+ "space" => { "Space"
193− key!('z') => Command::view_mode,
457+ "f" => file_picker,
458+ "b" => buffer_picker,
459+ "s" => symbol_picker,
463+ "C-w" | "w" => rotate_view,
464+ "C-h" | "h" => hsplit,
465+ "C-v" | "v" => vsplit,
466+ "C-q" | "q" => wclose,
468+ "y" => yank_joined_to_clipboard,
469+ "Y" => yank_main_selection_to_clipboard,
470+ "p" => paste_clipboard_after,
471+ "P" => paste_clipboard_before,
472+ "R" => replace_selections_with_clipboard,
473+ "space" => keep_primary_selection,
476+ "z" | "c" => align_view_center,
477+ "t" => align_view_top,
478+ "b" => align_view_bottom,
479+ "m" => align_view_middle,
195− key!('"') => Command::select_register,
484+ "\"" => select_register,
197 // TODO: decide whether we want normal mode to also be select mode (kakoune-like), or whether
486 // TODO: decide whether we want normal mode to also be select mode (kakoune-like), or whether
198 // we keep this separate select mode. More keys can fit into normal mode then, but it's weird
487 // we keep this separate select mode. More keys can fit into normal mode then, but it's weird
199 // because some selection operations can now be done from normal mode, some from select mode.
488 // because some selection operations can now be done from normal mode, some from select mode.
200 let mut select = normal.clone();
489 let mut select = normal.clone();
201− select.extend(
490+ select.merge_nodes(keymap!({ "Select mode"
203− key!('h') => Command::extend_char_left,
491+ "h" | "left" => extend_char_left,
204− key!('j') => Command::extend_line_down,
492+ "j" | "down" => extend_line_down,
205− key!('k') => Command::extend_line_up,
493+ "k" | "up" => extend_line_up,
206− key!('l') => Command::extend_char_right,
208− key!(Left) => Command::extend_char_left,
209− key!(Down) => Command::extend_line_down,
210− key!(Up) => Command::extend_line_up,
211− key!(Right) => Command::extend_char_right,
494+ "l" | "right" => extend_char_right,
213− key!('w') => Command::extend_next_word_start,
496+ "w" => extend_next_word_start,
214− key!('b') => Command::extend_prev_word_start,
497+ "b" => extend_prev_word_start,
215− key!('e') => Command::extend_next_word_end,
498+ "e" => extend_next_word_end,
217− key!('t') => Command::extend_till_char,
500+ "t" => extend_till_char,
218− key!('f') => Command::extend_next_char,
501+ "f" => extend_next_char,
220− key!('T') => Command::extend_till_prev_char,
502+ "T" => extend_till_prev_char,
221− key!('F') => Command::extend_prev_char,
503+ "F" => extend_prev_char,
222− key!(Home) => Command::goto_line_start,
505+ "home" => goto_line_start,
223− key!(End) => Command::goto_line_end,
506+ "end" => goto_line_end,
224− key!(Esc) => Command::exit_select_mode,
507+ "esc" => exit_select_mode,
226− .into_iter(),
509+ let insert = keymap!({ "Insert mode"
510+ "esc" => normal_mode,
512+ "backspace" => delete_char_backward,
513+ "del" => delete_char_forward,
514+ "ret" => insert_newline,
515+ "tab" => insert_tab,
516+ "C-w" => delete_word_backward,
518+ "left" => move_char_left,
519+ "down" => move_line_down,
520+ "up" => move_line_up,
521+ "right" => move_char_right,
522+ "pageup" => page_up,
523+ "pagedown" => page_down,
524+ "home" => goto_line_start,
525+ "end" => goto_line_end_newline,
527+ "C-x" => completion,
229 Keymaps(hashmap!(
529 Keymaps(hashmap!(
230− // as long as you cast the first item, rust is able to infer the other cases
231− // TODO: select could be normal mode with some bindings merged over
232− Mode::Normal => normal,
530+ Mode::Normal => Keymap::new(normal),
233− Mode::Select => select,
531+ Mode::Select => Keymap::new(select),
234− Mode::Insert => hashmap!(
532+ Mode::Insert => Keymap::new(insert),
235− key!(Esc) => Command::normal_mode as Command,
236− key!(Backspace) => Command::delete_char_backward,
237− key!(Delete) => Command::delete_char_forward,
238− key!(Enter) => Command::insert_newline,
239− key!(Tab) => Command::insert_tab,
240− key!(Left) => Command::move_char_left,
241− key!(Down) => Command::move_line_down,
242− key!(Up) => Command::move_line_up,
243− key!(Right) => Command::move_char_right,
244− key!(PageUp) => Command::page_up,
245− key!(PageDown) => Command::page_down,
246− key!(Home) => Command::goto_line_start,
247− key!(End) => Command::goto_line_end_newline,
248− ctrl!('x') => Command::completion,
249− ctrl!('w') => Command::delete_word_backward,
255−/// Merge default config keys with user overwritten keys for custom
537+/// Merge default config keys with user overwritten keys for custom user config.
257pub fn merge_keys(mut config: Config) -> Config {
538pub fn merge_keys(mut config: Config) -> Config {
258 let mut delta = std::mem::take(&mut config.keys);
539 let mut delta = std::mem::take(&mut config.keys);
259 for (mode, keys) in &mut *config.keys {
540 for (mode, keys) in &mut *config.keys {
260− keys.extend(delta.remove(mode).unwrap_or_default());
541+ keys.merge(delta.remove(mode).unwrap_or_default())
266fn merge_partial_keys() {
547fn merge_partial_keys() {
267− use helix_view::keyboard::{KeyCode, KeyModifiers};
268 let config = Config {
548 let config = Config {
269 keys: Keymaps(hashmap! {
549 keys: Keymaps(hashmap! {
270− Mode::Normal => hashmap! {
550+ Mode::Normal => Keymap::new(
271− KeyEvent {
551+ keymap!({ "Normal mode"
272− code: KeyCode::Char('i'),
273− modifiers: KeyModifiers::NONE,
274− } => Command::normal_mode,
552+ "i" => normal_mode,
275− KeyEvent { // key that does not exist
276− code: KeyCode::Char('无'),
277− modifiers: KeyModifiers::NONE,
278− } => Command::insert_mode,
553+ "无" => insert_mode,
554+ "z" => jump_backward,
555+ "g" => { "Merge into goto mode"
556+ "$" => goto_line_end,
557+ "g" => delete_char_forward,
281 ..Default::default()
562 ..Default::default()
283− let merged_config = merge_keys(config.clone());
564+ let mut merged_config = merge_keys(config.clone());
284 assert_ne!(config, merged_config);
565 assert_ne!(config, merged_config);
567+ let keymap = merged_config.keys.0.get_mut(&Mode::Normal).unwrap();
285 assert_eq!(
568 assert_eq!(
286− *merged_config
569+ keymap.get(key!('i')),
292− code: KeyCode::Char('i'),
293− modifiers: KeyModifiers::NONE
296− Command::normal_mode
570+ KeymapResult::Matched(Command::normal_mode),
571+ "Leaf should replace leaf"
298 assert_eq!(
573 assert_eq!(
299− *merged_config
574+ keymap.get(key!('无')),
305− code: KeyCode::Char('无'),
306− modifiers: KeyModifiers::NONE
309− Command::insert_mode
575+ KeymapResult::Matched(Command::insert_mode),
576+ "New leaf should be present in merged keymap"
578+ // Assumes that z is a node in the default keymap
580+ keymap.get(key!('z')),
581+ KeymapResult::Matched(Command::jump_backward),
582+ "Leaf should replace node"
584+ // Assumes that `g` is a node in default keymap
586+ keymap.root().search(&[key!('g'), key!('$')]).unwrap(),
587+ &KeyTrie::Leaf(Command::goto_line_end),
588+ "Leaf should be present in merged subnode"
590+ // Assumes that `gg` is in default keymap
592+ keymap.root().search(&[key!('g'), key!('g')]).unwrap(),
593+ &KeyTrie::Leaf(Command::delete_char_forward),
594+ "Leaf should replace old leaf in merged subnode"
596+ // Assumes that `ge` is in default keymap
598+ keymap.root().search(&[key!('g'), key!('e')]).unwrap(),
599+ &KeyTrie::Leaf(Command::goto_file_end),
600+ "Old leaves in subnode should be present in merged node"
311 assert!(merged_config.keys.0.get(&Mode::Normal).unwrap().len() > 1);
603 assert!(merged_config.keys.0.get(&Mode::Normal).unwrap().len() > 1);
312 assert!(merged_config.keys.0.get(&Mode::Insert).unwrap().len() > 0);
604 assert!(merged_config.keys.0.get(&Mode::Insert).unwrap().len() > 0);