use crossterm::event::{KeyCode, KeyModifiers}; use std::time::{Duration, Instant}; #[derive(Debug, Clone, PartialEq)] pub struct ParsedKey { pub code: KeyCode, pub modifiers: KeyModifiers, } #[derive(Debug, Clone)] pub struct KeySequenceTracker { pub current_sequence: Vec, pub last_key_time: Instant, pub timeout: Duration, } impl KeySequenceTracker { pub fn new(timeout_ms: u64) -> Self { Self { current_sequence: Vec::new(), last_key_time: Instant::now(), timeout: Duration::from_millis(timeout_ms), } } pub fn reset(&mut self) { self.current_sequence.clear(); self.last_key_time = Instant::now(); } pub fn add_key(&mut self, key: KeyCode) -> bool { // Check if timeout has expired let now = Instant::now(); if now.duration_since(self.last_key_time) > self.timeout { self.reset(); } self.current_sequence.push(key); self.last_key_time = now; true } pub fn get_sequence(&self) -> Vec { self.current_sequence.clone() } pub fn sequence_to_string(&self) -> String { self.current_sequence.iter().map(|k| match k { KeyCode::Char(c) => c.to_string(), _ => String::new(), }).collect() } } pub fn parse_binding(binding: &str) -> Vec { let mut sequence = Vec::new(); let parts: Vec<&str> = if binding.contains(' ') { binding.split(' ').collect() } else if is_special_key(binding) { vec![binding] } else { // Fixed implementation using char indices binding.char_indices().map(|(i, _)| { let start = i; let end = i + 1; &binding[start..end] }).collect() }; for part in parts { if let Some(key) = parse_key_part(part) { sequence.push(key); } } sequence } fn is_special_key(part: &str) -> bool { matches!(part.to_lowercase().as_str(), "esc" | "up" | "down" | "left" | "right" | "enter" | "backspace" | "delete" | "tab" | "backtab" ) } fn parse_key_part(part: &str) -> Option { let mut modifiers = KeyModifiers::empty(); let mut code = None; let components: Vec<&str> = part.split('+').collect(); for component in components { match component.to_lowercase().as_str() { "ctrl" => modifiers |= KeyModifiers::CONTROL, "shift" => modifiers |= KeyModifiers::SHIFT, "alt" => modifiers |= KeyModifiers::ALT, "esc" => code = Some(KeyCode::Esc), "up" => code = Some(KeyCode::Up), "down" => code = Some(KeyCode::Down), "left" => code = Some(KeyCode::Left), "right" => code = Some(KeyCode::Right), "enter" => code = Some(KeyCode::Enter), "backspace" => code = Some(KeyCode::Backspace), "delete" => code = Some(KeyCode::Delete), "tab" => code = Some(KeyCode::Tab), "backtab" => code = Some(KeyCode::BackTab), ":" => code = Some(KeyCode::Char(':')), c if c.len() == 1 => { code = Some(KeyCode::Char(c.chars().next().unwrap())); } _ => return None, } } code.map(|code| ParsedKey { code, modifiers }) }