75 lines
2.3 KiB
Rust
75 lines
2.3 KiB
Rust
// src/input/leader.rs
|
|
use crate::config::binds::config::Config;
|
|
use crate::config::binds::key_sequences::parse_binding;
|
|
use crossterm::event::KeyCode;
|
|
|
|
/// Collect leader (= space-prefixed) bindings from *all* binding maps
|
|
fn leader_bindings<'a>(config: &'a Config) -> Vec<(&'a str, Vec<KeyCode>)> {
|
|
let mut out = Vec::new();
|
|
|
|
// Include all keybinding maps, not just global
|
|
let all_modes: Vec<&std::collections::HashMap<String, Vec<String>>> = vec![
|
|
&config.keybindings.general,
|
|
&config.keybindings.read_only,
|
|
&config.keybindings.edit,
|
|
&config.keybindings.highlight,
|
|
&config.keybindings.command,
|
|
&config.keybindings.common,
|
|
&config.keybindings.global,
|
|
];
|
|
|
|
for mode in all_modes {
|
|
for (action, bindings) in mode {
|
|
for b in bindings {
|
|
let parsed = parse_binding(b);
|
|
if parsed.first().map(|pk| pk.code) == Some(KeyCode::Char(' ')) {
|
|
let codes =
|
|
parsed.into_iter().map(|pk| pk.code).collect::<Vec<_>>();
|
|
out.push((action.as_str(), codes));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
out
|
|
}
|
|
|
|
/// Is there any leader binding configured at all?
|
|
pub fn leader_has_any_start(config: &Config) -> bool {
|
|
leader_bindings(config)
|
|
.iter()
|
|
.any(|(_, seq)| seq.first() == Some(&KeyCode::Char(' ')))
|
|
}
|
|
|
|
/// Is `sequence` a prefix of any configured leader sequence?
|
|
pub fn leader_is_prefix(config: &Config, sequence: &[KeyCode]) -> bool {
|
|
if sequence.is_empty() || sequence[0] != KeyCode::Char(' ') {
|
|
return false;
|
|
}
|
|
for (_, full) in leader_bindings(config) {
|
|
if full.len() > sequence.len()
|
|
&& full.iter().zip(sequence.iter()).all(|(a, b)| a == b)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
false
|
|
}
|
|
|
|
/// Is `sequence` an exact leader match? If yes, return the action string.
|
|
pub fn leader_match_action<'a>(
|
|
config: &'a Config,
|
|
sequence: &[KeyCode],
|
|
) -> Option<&'a str> {
|
|
if sequence.is_empty() || sequence[0] != KeyCode::Char(' ') {
|
|
return None;
|
|
}
|
|
for (action, full) in leader_bindings(config) {
|
|
if full.len() == sequence.len()
|
|
&& full.iter().zip(sequence.iter()).all(|(a, b)| a == b)
|
|
{
|
|
return Some(action);
|
|
}
|
|
}
|
|
None
|
|
}
|