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 pub fn new(text: String) -> Self {
72 let input = Input::new(text.clone()).with_cursor(text.len());
73 Self {
74 input,
75 history: Vec::new(),
76 history_index: None,
77 temp_storage: None,
78 }
79 }
80
81 pub fn from_input(input: Input) -> Self {
82 Self {
83 input,
84 history: Vec::new(),
85 history_index: None,
86 temp_storage: None,
87 }
88 }
89
90 pub fn as_input(&self) -> &Input {
91 &self.input
92 }
93
94 pub fn as_input_mut(&mut self) -> &mut Input {
95 &mut self.input
96 }
97}
98
99impl InputManager for SingleLineInput {
100 fn get_text(&self) -> String {
101 self.input.value().to_string()
102 }
103
104 fn set_text(&mut self, text: String) {
105 let cursor_pos = text.len();
106 self.input = Input::new(text).with_cursor(cursor_pos);
107 }
108
109 fn get_cursor_position(&self) -> usize {
110 self.input.visual_cursor()
111 }
112
113 fn set_cursor_position(&mut self, position: usize) {
114 let text = self.input.value().to_string();
115 self.input = Input::new(text).with_cursor(position);
116 }
117
118 fn handle_key_event(&mut self, event: KeyEvent) -> bool {
119 let crossterm_event = Event::Key(event);
121 self.input.handle_event(&crossterm_event);
122 true
123 }
124
125 fn clear(&mut self) {
126 self.input = Input::default();
127 }
128
129 fn is_empty(&self) -> bool {
130 self.input.value().is_empty()
131 }
132
133 fn get_visual_cursor(&self) -> (u16, u16) {
134 (0, self.input.visual_cursor() as u16)
135 }
136
137 fn is_multiline(&self) -> bool {
138 false
139 }
140
141 fn line_count(&self) -> usize {
142 1
143 }
144
145 fn get_line(&self, index: usize) -> Option<String> {
146 if index == 0 {
147 Some(self.get_text())
148 } else {
149 None
150 }
151 }
152
153 fn clone_box(&self) -> Box<dyn InputManager> {
154 Box::new(SingleLineInput {
155 input: self.input.clone(),
156 history: self.history.clone(),
157 history_index: self.history_index,
158 temp_storage: self.temp_storage.clone(),
159 })
160 }
161
162 fn set_history(&mut self, history: Vec<String>) {
165 self.history = history;
166 self.history_index = None;
167 self.temp_storage = None;
168 }
169
170 fn history_previous(&mut self) -> bool {
171 if self.history.is_empty() {
172 return false;
173 }
174
175 match self.history_index {
176 None => {
177 self.temp_storage = Some(self.input.value().to_string());
179 self.history_index = Some(self.history.len() - 1);
180 }
181 Some(0) => return false, Some(idx) => {
183 self.history_index = Some(idx - 1);
184 }
185 }
186
187 if let Some(idx) = self.history_index {
189 if let Some(entry) = self.history.get(idx) {
190 let len = entry.len();
191 self.input = Input::new(entry.clone()).with_cursor(len);
192 return true;
193 }
194 }
195 false
196 }
197
198 fn history_next(&mut self) -> bool {
199 match self.history_index {
200 None => false, Some(idx) => {
202 if idx >= self.history.len() - 1 {
203 if let Some(temp) = &self.temp_storage {
205 let len = temp.len();
206 self.input = Input::new(temp.clone()).with_cursor(len);
207 }
208 self.history_index = None;
209 self.temp_storage = None;
210 true
211 } else {
212 self.history_index = Some(idx + 1);
213 if let Some(entry) = self.history.get(idx + 1) {
214 let len = entry.len();
215 self.input = Input::new(entry.clone()).with_cursor(len);
216 true
217 } else {
218 false
219 }
220 }
221 }
222 }
223 }
224
225 fn get_history_index(&self) -> Option<usize> {
226 self.history_index
227 }
228
229 fn reset_history_position(&mut self) {
230 self.history_index = None;
231 self.temp_storage = None;
232 }
233}
234
235pub fn create_single_line(text: String) -> Box<dyn InputManager> {
237 Box::new(SingleLineInput::new(text))
238}
239
240pub fn create_from_input(input: Input) -> Box<dyn InputManager> {
241 Box::new(SingleLineInput::from_input(input))
242}