Skip to main content

alf/tui/state/
input.rs

1//! Input mode and pending key state
2
3use std::time::Instant;
4
5/// Input mode for the application
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum InputMode {
8   /// Normal vim navigation mode
9   Normal,
10   /// Typing in the search bar
11   Search,
12}
13
14/// Input state management
15#[derive(Debug, Clone)]
16pub struct InputState {
17   /// Current input mode
18   mode: InputMode,
19   /// Pending key for multi-key sequences (e.g. 'g' for 'gg')
20   pending_key: Option<char>,
21   /// Timestamp when pending key was set (for timeout handling)
22   pending_key_time: Option<Instant>,
23}
24
25impl Default for InputState {
26   fn default() -> Self {
27      Self {
28         mode: InputMode::Normal,
29         pending_key: None,
30         pending_key_time: None,
31      }
32   }
33}
34
35impl InputState {
36   /// Create a new InputState
37   pub fn new() -> Self {
38      Self::default()
39   }
40
41   /// Get the current input mode
42   pub fn mode(&self) -> InputMode {
43      self.mode
44   }
45
46   /// Get the pending key
47   pub fn pending_key(&self) -> Option<char> {
48      self.pending_key
49   }
50
51   /// Get the pending key timestamp
52   pub fn pending_key_time(&self) -> Option<Instant> {
53      self.pending_key_time
54   }
55
56   /// Enter search mode
57   pub fn enter_search(&mut self) {
58      self.mode = InputMode::Search;
59   }
60
61   /// Exit search mode and return to normal mode
62   pub fn exit_search(&mut self) {
63      self.mode = InputMode::Normal;
64   }
65
66   /// Check if currently in search mode
67   pub fn is_searching(&self) -> bool {
68      self.mode == InputMode::Search
69   }
70
71   /// Set pending key with timestamp
72   pub fn set_pending_key(
73      &mut self,
74      key: char,
75   ) {
76      self.pending_key = Some(key);
77      self.pending_key_time = Some(Instant::now());
78   }
79
80   /// Clear pending key state
81   pub fn clear_pending_key(&mut self) {
82      self.pending_key = None;
83      self.pending_key_time = None;
84   }
85
86   /// Check if pending key has timed out (2 seconds)
87   pub fn is_pending_key_expired(&self) -> bool {
88      if let (Some(_), Some(time)) = (self.pending_key, self.pending_key_time) {
89         time.elapsed() > std::time::Duration::from_secs(2)
90      } else {
91         false
92      }
93   }
94}
95
96#[cfg(test)]
97#[path = "input_tests.rs"]
98mod input_tests;