1use crossterm::event::{Event, KeyEvent};
2use tui_input::{backend::crossterm::EventHandler, Input};
3
4pub trait InputManager: Send + Sync {
8 fn get_text(&self) -> String;
10
11 fn set_text(&mut self, text: String);
13
14 fn get_cursor_position(&self) -> usize;
16
17 fn set_cursor_position(&mut self, position: usize);
19
20 fn handle_key_event(&mut self, event: KeyEvent) -> bool;
22
23 fn clear(&mut self);
25
26 fn is_empty(&self) -> bool;
28
29 fn get_visual_cursor(&self) -> (u16, u16);
31
32 fn is_multiline(&self) -> bool;
34
35 fn line_count(&self) -> usize;
37
38 fn get_line(&self, index: usize) -> Option<String>;
40
41 fn clone_box(&self) -> Box<dyn InputManager>;
43
44 fn set_history(&mut self, history: Vec<String>);
48
49 fn history_previous(&mut self) -> bool;
51
52 fn history_next(&mut self) -> bool;
54
55 fn get_history_index(&self) -> Option<usize>;
57
58 fn reset_history_position(&mut self);
60}
61
62pub struct SingleLineInput {
64 input: Input,
65 history: Vec<String>,
66 history_index: Option<usize>,
67 temp_storage: Option<String>, }
69
70impl SingleLineInput {
71 #[must_use]
72 pub fn new(text: String) -> Self {
73 let input = Input::new(text.clone()).with_cursor(text.len());
74 Self {
75 input,
76 history: Vec::new(),
77 history_index: None,
78 temp_storage: None,
79 }
80 }
81
82 #[must_use]
83 pub fn from_input(input: Input) -> Self {
84 Self {
85 input,
86 history: Vec::new(),
87 history_index: None,
88 temp_storage: None,
89 }
90 }
91
92 #[must_use]
93 pub fn as_input(&self) -> &Input {
94 &self.input
95 }
96
97 pub fn as_input_mut(&mut self) -> &mut Input {
98 &mut self.input
99 }
100}
101
102impl InputManager for SingleLineInput {
103 fn get_text(&self) -> String {
104 self.input.value().to_string()
105 }
106
107 fn set_text(&mut self, text: String) {
108 let cursor_pos = text.len();
109 self.input = Input::new(text).with_cursor(cursor_pos);
110 }
111
112 fn get_cursor_position(&self) -> usize {
113 self.input.visual_cursor()
114 }
115
116 fn set_cursor_position(&mut self, position: usize) {
117 let text = self.input.value().to_string();
118 self.input = Input::new(text).with_cursor(position);
119 }
120
121 fn handle_key_event(&mut self, event: KeyEvent) -> bool {
122 let crossterm_event = Event::Key(event);
124 self.input.handle_event(&crossterm_event);
125 true
126 }
127
128 fn clear(&mut self) {
129 self.input = Input::default();
130 }
131
132 fn is_empty(&self) -> bool {
133 self.input.value().is_empty()
134 }
135
136 fn get_visual_cursor(&self) -> (u16, u16) {
137 (0, self.input.visual_cursor() as u16)
138 }
139
140 fn is_multiline(&self) -> bool {
141 false
142 }
143
144 fn line_count(&self) -> usize {
145 1
146 }
147
148 fn get_line(&self, index: usize) -> Option<String> {
149 if index == 0 {
150 Some(self.get_text())
151 } else {
152 None
153 }
154 }
155
156 fn clone_box(&self) -> Box<dyn InputManager> {
157 Box::new(SingleLineInput {
158 input: self.input.clone(),
159 history: self.history.clone(),
160 history_index: self.history_index,
161 temp_storage: self.temp_storage.clone(),
162 })
163 }
164
165 fn set_history(&mut self, history: Vec<String>) {
168 self.history = history;
169 self.history_index = None;
170 self.temp_storage = None;
171 }
172
173 fn history_previous(&mut self) -> bool {
174 if self.history.is_empty() {
175 return false;
176 }
177
178 match self.history_index {
179 None => {
180 self.temp_storage = Some(self.input.value().to_string());
182 self.history_index = Some(self.history.len() - 1);
183 }
184 Some(0) => return false, Some(idx) => {
186 self.history_index = Some(idx - 1);
187 }
188 }
189
190 if let Some(idx) = self.history_index {
192 if let Some(entry) = self.history.get(idx) {
193 let len = entry.len();
194 self.input = Input::new(entry.clone()).with_cursor(len);
195 return true;
196 }
197 }
198 false
199 }
200
201 fn history_next(&mut self) -> bool {
202 match self.history_index {
203 None => false, Some(idx) => {
205 if idx >= self.history.len() - 1 {
206 if let Some(temp) = &self.temp_storage {
208 let len = temp.len();
209 self.input = Input::new(temp.clone()).with_cursor(len);
210 }
211 self.history_index = None;
212 self.temp_storage = None;
213 true
214 } else {
215 self.history_index = Some(idx + 1);
216 if let Some(entry) = self.history.get(idx + 1) {
217 let len = entry.len();
218 self.input = Input::new(entry.clone()).with_cursor(len);
219 true
220 } else {
221 false
222 }
223 }
224 }
225 }
226 }
227
228 fn get_history_index(&self) -> Option<usize> {
229 self.history_index
230 }
231
232 fn reset_history_position(&mut self) {
233 self.history_index = None;
234 self.temp_storage = None;
235 }
236}
237
238#[must_use]
240pub fn create_single_line(text: String) -> Box<dyn InputManager> {
241 Box::new(SingleLineInput::new(text))
242}
243
244#[must_use]
245pub fn create_from_input(input: Input) -> Box<dyn InputManager> {
246 Box::new(SingleLineInput::from_input(input))
247}