diff --git a/src/app.rs b/src/app.rs index c2263b7..0071734 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1421,7 +1421,7 @@ impl std::fmt::Display for Log { #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub enum HelpMenuLine { - KeyMap(String, String), + KeyMap(String, Vec, String), Paragraph(String), } @@ -2624,16 +2624,8 @@ impl App { .iter() .map(|l| match l { HelpMenuLine::Paragraph(p) => format!("\t{}\n", p), - HelpMenuLine::KeyMap(k, h) => { - let remaps = self - .mode() - .key_bindings() - .remaps() - .iter() - .filter(|(_, maybeto)| maybeto.as_ref().map(|to| to == k).unwrap_or(false)) - .map(|(f, _)| f.clone()) - .collect::>() - .join(", "); + HelpMenuLine::KeyMap(k, remaps, h) => { + let remaps = remaps.join(", "); format!(" {:15} | {:25} | {}\n", k, remaps, h) } }) diff --git a/src/config.rs b/src/config.rs index a03254c..0d9f1d8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,11 +7,11 @@ use crate::ui::Border; use crate::ui::Constraint; use crate::ui::Layout; use crate::ui::Style; -use indexmap::IndexMap; use indexmap::IndexSet; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::collections::HashMap; +use std::collections::HashSet; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(deny_unknown_fields)] @@ -548,9 +548,6 @@ impl GeneralConfig { #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct KeyBindings { - #[serde(default)] - pub remaps: IndexMap>, - #[serde(default)] pub on_key: BTreeMap, @@ -584,28 +581,9 @@ impl KeyBindings { self.default = self.default.and_then(|a| a.sanitized(read_only)); }; - let mut remaps = IndexMap::new(); - for (from, maybe_to) in self.remaps.into_iter() { - if let Some(to) = maybe_to.as_ref() { - let mapped = self.on_key.get(to).cloned(); - if let Some(a) = mapped { - self.on_key.insert(from.clone(), a.clone()); - remaps.insert(from, maybe_to); - } - } else { - self.on_key.remove(&from); - } - } - - self.remaps = remaps; self } - /// Get a reference to the key bindings's remaps. - pub fn remaps(&self) -> &IndexMap> { - &self.remaps - } - /// Get a reference to the key bindings's on key. pub fn on_key(&self) -> &BTreeMap { &self.on_key @@ -669,57 +647,83 @@ impl Mode { .collect() }) .unwrap_or_else(|| { - extra_help_lines + let lines = extra_help_lines .unwrap_or_default() .into_iter() - .chain( - self.key_bindings + .chain(self.key_bindings.on_key.iter().filter_map(|(k, a)| { + let remaps = self + .key_bindings .on_key .iter() - .filter(|(k, v)| { - !self - .key_bindings - .remaps - .get(*k) - .and_then(|mt| { - mt.as_ref() - .map(|t| self.key_bindings.on_key.get(t) == Some(v)) - }) - .unwrap_or(false) + .filter_map(|(rk, ra)| { + if rk == k { + None + } else if a == ra { + Some(rk.clone()) + } else { + None + } }) - .filter_map(|(k, a)| { - a.help.clone().map(|h| HelpMenuLine::KeyMap(k.into(), h)) - }), - ) + .collect::>(); + a.help + .clone() + .map(|h| HelpMenuLine::KeyMap(k.into(), remaps, h)) + })) .chain( self.key_bindings .on_alphabet .iter() .map(|a| ("[a-Z]", a.help.clone())) - .filter_map(|(k, mh)| mh.map(|h| HelpMenuLine::KeyMap(k.into(), h))), + .filter_map(|(k, mh)| { + mh.map(|h| HelpMenuLine::KeyMap(k.into(), vec![], h)) + }), ) .chain( self.key_bindings .on_number .iter() .map(|a| ("[0-9]", a.help.clone())) - .filter_map(|(k, mh)| mh.map(|h| HelpMenuLine::KeyMap(k.into(), h))), + .filter_map(|(k, mh)| { + mh.map(|h| HelpMenuLine::KeyMap(k.into(), vec![], h)) + }), ) .chain( self.key_bindings .on_special_character .iter() .map(|a| ("[spcl chars]", a.help.clone())) - .filter_map(|(k, mh)| mh.map(|h| HelpMenuLine::KeyMap(k.into(), h))), + .filter_map(|(k, mh)| { + mh.map(|h| HelpMenuLine::KeyMap(k.into(), vec![], h)) + }), ) .chain( self.key_bindings .default .iter() .map(|a| ("[default]", a.help.clone())) - .filter_map(|(k, mh)| mh.map(|h| HelpMenuLine::KeyMap(k.into(), h))), - ) - .collect() + .filter_map(|(k, mh)| { + mh.map(|h| HelpMenuLine::KeyMap(k.into(), vec![], h)) + }), + ); + + let mut remapped = HashSet::new(); + let mut result = vec![]; + + for line in lines { + match line { + HelpMenuLine::Paragraph(p) => result.push(HelpMenuLine::Paragraph(p)), + HelpMenuLine::KeyMap(k, r, d) => { + if !remapped.contains(&k) { + for k in r.iter() { + remapped.insert(k.clone()); + } + result.push(HelpMenuLine::KeyMap(k, r, d)); + } + } + } + } + + result }) } diff --git a/src/init.lua b/src/init.lua index 61407d2..06c4606 100644 --- a/src/init.lua +++ b/src/init.lua @@ -557,16 +557,6 @@ xplr.config.modes.builtin.default = { help = nil, extra_help = nil, key_bindings = { - remaps = { - ["k"] = "up", - tab = "ctrl-i", - ["/"] = "ctrl-f", - ["V"] = "ctrl-a", - ["h"] = "left", - ["v"] = "space", - ["j"] = "down", - ["l"] = "right" - }, on_key = { ["#"] = { help = nil, @@ -607,7 +597,7 @@ xplr.config.modes.builtin.default = { }, ["G"] = { help = "go to bottom", - messages = {"FocusLast"} + messages = {"PopMode", "FocusLast", "Refresh"} }, ["ctrl-a"] = { help = "select/unselect all", @@ -755,13 +745,20 @@ xplr.config.modes.builtin.default = { } } +xplr.config.modes.builtin.default.key_bindings.on_key["v"] = xplr.config.modes.builtin.default.key_bindings.on_key.space +xplr.config.modes.builtin.default.key_bindings.on_key["V"] = xplr.config.modes.builtin.default.key_bindings.on_key["ctrl-a"] +xplr.config.modes.builtin.default.key_bindings.on_key["/"] = xplr.config.modes.builtin.default.key_bindings.on_key["ctrl-f"] +xplr.config.modes.builtin.default.key_bindings.on_key["h"] = xplr.config.modes.builtin.default.key_bindings.on_key.left +xplr.config.modes.builtin.default.key_bindings.on_key["j"] = xplr.config.modes.builtin.default.key_bindings.on_key.bottom +xplr.config.modes.builtin.default.key_bindings.on_key["k"] = xplr.config.modes.builtin.default.key_bindings.on_key.up +xplr.config.modes.builtin.default.key_bindings.on_key["l"] = xplr.config.modes.builtin.default.key_bindings.on_key.right + ------ Recover xplr.config.modes.builtin.recover = { name = "recover", help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { ["ctrl-c"] = { help = "terminate", @@ -788,7 +785,6 @@ xplr.config.modes.builtin.selection_ops = { help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { ["c"] = { help = "copy here", @@ -878,7 +874,6 @@ xplr.config.modes.builtin.create = { help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { ["ctrl-c"] = { help = "terminate", @@ -926,7 +921,6 @@ xplr.config.modes.builtin.create_directory = { help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { backspace = { help = "remove last character", @@ -989,7 +983,6 @@ xplr.config.modes.builtin.create_file = { help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { backspace = { help = "remove last character", @@ -1052,10 +1045,6 @@ xplr.config.modes.builtin.number = { help = nil, extra_help = nil, key_bindings = { - remaps = { - ["j"] = "down", - ["k"] = "up" - }, on_key = { backspace = { help = "remove last character", @@ -1104,13 +1093,15 @@ xplr.config.modes.builtin.number = { } } +xplr.config.modes.builtin.number.key_bindings.on_key["j"] = xplr.config.modes.builtin.number.key_bindings.on_key.down +xplr.config.modes.builtin.number.key_bindings.on_key["k"] = xplr.config.modes.builtin.number.key_bindings.on_key.up + ------ Go to xplr.config.modes.builtin.go_to = { name = "go to", help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { ["ctrl-c"] = { help = "terminate", @@ -1165,7 +1156,6 @@ xplr.config.modes.builtin.rename = { help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { backspace = { help = "remove last character", @@ -1225,7 +1215,6 @@ xplr.config.modes.builtin.delete = { help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { ["D"] = { help = "force delete", @@ -1297,7 +1286,6 @@ xplr.config.modes.builtin.action = { help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { ["!"] = { help = "shell", @@ -1389,11 +1377,6 @@ xplr.config.modes.builtin.search = { help = nil, extra_help = nil, key_bindings = { - remaps = { - esc = "enter", - ["ctrl-n"] = "down", - ["ctrl-p"] = "up" - }, on_key = { backspace = { help = "remove last character", @@ -1509,15 +1492,16 @@ xplr.config.modes.builtin.search = { } } +xplr.config.modes.builtin.search.key_bindings.on_key["esc"] = xplr.config.modes.builtin.search.key_bindings.on_key.enter +xplr.config.modes.builtin.search.key_bindings.on_key["ctrl-n"] = xplr.config.modes.builtin.search.key_bindings.on_key.down +xplr.config.modes.builtin.search.key_bindings.on_key["ctrl-p"] = xplr.config.modes.builtin.search.key_bindings.on_key.up + ------ Filter xplr.config.modes.builtin.filter = { name = "filter", help = nil, extra_help = nil, key_bindings = { - remaps = { - esc = "enter" - }, on_key = { ["R"] = { help = "relative does not contain", @@ -1577,13 +1561,14 @@ xplr.config.modes.builtin.filter = { } } +xplr.config.modes.builtin.filter.key_bindings.on_key["esc"] = xplr.config.modes.builtin.filter.key_bindings.on_key.enter + ------ Relative path does contain xplr.config.modes.builtin.relative_path_does_contain = { name = "relative path does contain", help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { backspace = { help = "remove last character", @@ -1671,7 +1656,6 @@ xplr.config.modes.builtin.relative_path_does_not_contain = { help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { backspace = { help = "remove last character", @@ -1758,9 +1742,6 @@ xplr.config.modes.builtin.sort = { help = nil, extra_help = nil, key_bindings = { - remaps = { - esc = "enter" - }, on_key = { ["!"] = { help = "reverse sorters", @@ -1938,13 +1919,14 @@ xplr.config.modes.builtin.sort = { } } +xplr.config.modes.builtin.sort.key_bindings.on_key["esc"] = xplr.config.modes.builtin.sort.key_bindings.on_key.enter + ------ Switch layout xplr.config.modes.builtin.switch_layout = { name = "switch layout", help = nil, extra_help = nil, key_bindings = { - remaps = {}, on_key = { ["1"] = { help = "default", diff --git a/src/ui.rs b/src/ui.rs index 87c0293..253f7f0 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -680,17 +680,8 @@ fn draw_help_menu( .into_iter() .map(|l| match l { HelpMenuLine::Paragraph(p) => Row::new([Cell::from(p)].to_vec()), - HelpMenuLine::KeyMap(k, h) => { - let remaps = app - .mode() - .key_bindings() - .remaps() - .iter() - .filter(|(_, maybeto)| maybeto.as_ref().map(|to| to == &k).unwrap_or(false)) - .map(|(f, _)| f.clone()) - .collect::>() - .join("|"); - Row::new([Cell::from(k), Cell::from(remaps), Cell::from(h)].to_vec()) + HelpMenuLine::KeyMap(k, remaps, h) => { + Row::new([Cell::from(k), Cell::from(remaps.join("|")), Cell::from(h)].to_vec()) } }) .collect::>();