use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use std::time::Instant;
use crate::keybinding::{event_to_keybinding, KeyBinding, KeySequence, SequenceMatch, SEQUENCE_TIMEOUT};
use super::App;
impl App {
pub(crate) fn check_sequence_timeout(&mut self) {
if let Some(since) = self.pending_since {
if since.elapsed() > SEQUENCE_TIMEOUT {
self.pending_keys.clear();
self.pending_since = None;
}
}
}
pub(crate) fn push_pending_key(&mut self, key: KeyBinding) {
if self.pending_keys.is_empty() {
self.pending_since = Some(Instant::now());
}
self.pending_keys.push(key);
}
pub(crate) fn clear_pending_keys(&mut self) {
self.pending_keys.clear();
self.pending_since = None;
}
pub(crate) fn matches_single_key(&self, event: &KeyEvent, seq: &KeySequence) -> bool {
if !seq.is_single() {
return false;
}
if let Some(first) = seq.first() {
first.matches(event)
} else {
false
}
}
pub(crate) fn is_shift_char_shortcut(event: &KeyEvent, lower: char) -> bool {
if event.modifiers.contains(KeyModifiers::CONTROL)
|| event.modifiers.contains(KeyModifiers::ALT)
{
return false;
}
let upper = lower.to_ascii_uppercase();
match event.code {
KeyCode::Char(c) if c == upper => true,
KeyCode::Char(c) if c == lower && event.modifiers.contains(KeyModifiers::SHIFT) => true,
_ => false,
}
}
pub(crate) fn try_match_sequence(&self, seq: &KeySequence) -> SequenceMatch {
if self.pending_keys.is_empty() {
return SequenceMatch::None;
}
let pending_len = self.pending_keys.len();
let seq_len = seq.0.len();
if pending_len > seq_len {
return SequenceMatch::None;
}
for (i, pending) in self.pending_keys.iter().enumerate() {
if *pending != seq.0[i] {
return SequenceMatch::None;
}
}
if pending_len == seq_len {
SequenceMatch::Full
} else {
SequenceMatch::Partial
}
}
pub(crate) fn key_could_match_sequence(&self, event: &KeyEvent, seq: &KeySequence) -> bool {
let Some(kb) = event_to_keybinding(event) else {
return false;
};
if self.pending_keys.is_empty() {
if let Some(first) = seq.first() {
return *first == kb;
}
return false;
}
let pending_len = self.pending_keys.len();
if pending_len >= seq.0.len() {
return false;
}
for (i, pending) in self.pending_keys.iter().enumerate() {
if *pending != seq.0[i] {
return false;
}
}
seq.0
.get(pending_len)
.map(|expected| *expected == kb)
.unwrap_or(false)
}
}