xref: /Held/src/utils/ui/mode/mode.rs (revision ec52bc291ca17b95adf0952fd110b951dea6af31)
1 use std::io::Read;
2 use std::sync::atomic::Ordering;
3 use std::sync::{Mutex, MutexGuard};
4 use std::{fmt::Debug, io};
5 
6 use crate::config::lastline_cmd::LastLineCommand;
7 use crate::utils::buffer::LineState;
8 #[cfg(feature = "dragonos")]
9 use crate::utils::input::KeyEventType;
10 
11 use crate::utils::terminal::TermManager;
12 
13 use crate::utils::ui::uicore::{UiCore, APP_INFO, TAB_SIZE};
14 use crate::utils::ui::{
15     event::KeyEventCallback,
16     uicore::{CONTENT_WINSIZE, DEF_STYLE},
17 };
18 
19 use crate::utils::ui::event::WarpUiCallBackType;
20 
21 pub trait InputMode: KeyEventCallback + Debug {
22     fn mode_type(&self) -> ModeType;
23 
24     #[cfg(not(feature = "dragonos"))]
25     fn event_route(
26         &self,
27         ui: &mut MutexGuard<UiCore>,
28         event: crossterm::event::Event,
29     ) -> io::Result<WarpUiCallBackType> {
30         match event {
31             crossterm::event::Event::FocusGained => todo!(),
32             crossterm::event::Event::FocusLost => todo!(),
33             crossterm::event::Event::Key(key) => self.key_event_route(ui, key),
34             crossterm::event::Event::Mouse(_) => todo!(),
35             crossterm::event::Event::Paste(_) => todo!(),
36             crossterm::event::Event::Resize(_, _) => todo!(),
37         }
38     }
39 
40     #[cfg(not(feature = "dragonos"))]
41     fn key_event_route(
42         &self,
43         ui: &mut MutexGuard<UiCore>,
44         keyev: crossterm::event::KeyEvent,
45     ) -> io::Result<WarpUiCallBackType> {
46         let callback = match keyev.code {
47             crossterm::event::KeyCode::Backspace => self.backspace(ui)?,
48             crossterm::event::KeyCode::Enter => self.enter(ui)?,
49             crossterm::event::KeyCode::Left => self.left(ui)?,
50             crossterm::event::KeyCode::Right => self.right(ui)?,
51             crossterm::event::KeyCode::Up => self.up(ui)?,
52             crossterm::event::KeyCode::Down => self.down(ui)?,
53             crossterm::event::KeyCode::Home => todo!(),
54             crossterm::event::KeyCode::End => todo!(),
55             crossterm::event::KeyCode::PageUp => todo!(),
56             crossterm::event::KeyCode::PageDown => todo!(),
57             crossterm::event::KeyCode::Tab => self.tab(ui)?,
58             crossterm::event::KeyCode::BackTab => todo!(),
59             crossterm::event::KeyCode::Delete => todo!(),
60             crossterm::event::KeyCode::Insert => todo!(),
61             crossterm::event::KeyCode::F(_) => todo!(),
62             crossterm::event::KeyCode::Char(c) => self.input_data(ui, &[c as u8])?,
63             crossterm::event::KeyCode::Null => todo!(),
64             crossterm::event::KeyCode::Esc => self.esc(ui)?,
65             crossterm::event::KeyCode::CapsLock => todo!(),
66             crossterm::event::KeyCode::ScrollLock => todo!(),
67             crossterm::event::KeyCode::NumLock => todo!(),
68             crossterm::event::KeyCode::PrintScreen => todo!(),
69             crossterm::event::KeyCode::Pause => todo!(),
70             crossterm::event::KeyCode::Menu => todo!(),
71             crossterm::event::KeyCode::KeypadBegin => todo!(),
72             crossterm::event::KeyCode::Media(_) => todo!(),
73             crossterm::event::KeyCode::Modifier(_) => todo!(),
74         };
75 
76         Ok(callback)
77     }
78 
79     #[cfg(feature = "dragonos")]
80     fn key_event_route(
81         &self,
82         ui: &mut MutexGuard<UiCore>,
83         key: KeyEventType,
84     ) -> io::Result<WarpUiCallBackType> {
85         match key {
86             KeyEventType::Common(c) => self.input_data(ui, &[c]),
87             KeyEventType::Up => self.up(ui),
88             KeyEventType::Down => self.down(ui),
89             KeyEventType::Right => self.right(ui),
90             KeyEventType::Left => self.left(ui),
91             KeyEventType::Enter => self.enter(ui),
92             KeyEventType::Tab => self.tab(ui),
93             KeyEventType::Backspace => self.backspace(ui),
94             KeyEventType::Esc => self.esc(ui),
95             KeyEventType::Unknown(_) => {
96                 ui.update_bottom_state_bar()?;
97                 Ok(WarpUiCallBackType::None)
98             }
99         }
100     }
101 }
102 
103 #[derive(Debug, PartialEq, Clone, Copy)]
104 pub enum ModeType {
105     Command,
106     LastLine,
107     Insert,
108 }
109 
110 impl InputMode for Command {
111     fn mode_type(&self) -> ModeType {
112         ModeType::Command
113     }
114 }
115 impl InputMode for LastLine {
116     fn mode_type(&self) -> ModeType {
117         ModeType::LastLine
118     }
119 }
120 impl InputMode for Insert {
121     fn mode_type(&self) -> ModeType {
122         ModeType::Insert
123     }
124 }
125 
126 #[derive(Debug)]
127 pub struct Command;
128 
129 impl Command {
130     pub fn jump_to_next_flag(
131         &self,
132         ui: &mut MutexGuard<UiCore>,
133         flags: LineState,
134     ) -> io::Result<()> {
135         let offset = ui.buffer.offset();
136         let y = ui.cursor.y() as usize;
137 
138         let start_line_number = offset + y + 1;
139         if start_line_number >= ui.buffer.line_count() {
140             return Ok(());
141         }
142 
143         let content = &ui.buffer.all_buffer()[start_line_number..];
144 
145         // 下一个flaged位置
146         let idx = content.iter().position(|x| x.flags.contains(flags));
147 
148         if idx.is_some() {
149             // y + idx
150             let line_number = start_line_number + idx.unwrap();
151             let new_y = ui.buffer.goto_line(line_number);
152             ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)?;
153             ui.cursor.move_to_row(new_y)?;
154             ui.cursor.highlight(Some(y as u16))?;
155         }
156 
157         Ok(())
158     }
159 
160     pub fn jump_to_previous_flag(
161         &self,
162         ui: &mut MutexGuard<UiCore>,
163         flags: LineState,
164     ) -> io::Result<()> {
165         let offset = ui.buffer.offset();
166         let y = ui.cursor.y() as usize;
167         if offset == 0 && y == 0 {
168             return Ok(());
169         }
170         let end_linenumber = offset + y - 1;
171 
172         let content = &ui.buffer.all_buffer()[0..end_linenumber];
173 
174         // 下一个flaged位置
175         let idx = content.iter().rposition(|x| x.flags.contains(flags));
176 
177         if idx.is_some() {
178             // y + idx
179             let new_y = ui.buffer.goto_line(idx.unwrap());
180             ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)?;
181             ui.cursor.move_to_row(new_y)?;
182             ui.cursor.highlight(Some(y as u16))?;
183         }
184 
185         Ok(())
186     }
187 
188     fn jump_to_first_char(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
189         // 移动到行第一个单词的首字母
190         let first_char = {
191             let line = ui.buffer.get_line(ui.cursor.y()).data;
192             let mut idx = 0;
193             for char in line {
194                 if char == b" "[0] {
195                     idx += 1;
196                 } else if char == b"\t"[0] {
197                     idx += 4;
198                 }
199             }
200             idx
201         };
202         ui.cursor.move_to_columu(first_char)?;
203         return Ok(WarpUiCallBackType::None);
204     }
205 
206     fn do_delete_on_d_clicked(
207         &self,
208         ui: &mut MutexGuard<UiCore>,
209     ) -> io::Result<WarpUiCallBackType> {
210         let buf: &mut [u8] = &mut [0; 8];
211         let _ = io::stdin().read(buf)?;
212 
213         match buf[0] {
214             b'd' => {
215                 TermManager::clear_current_line()?;
216                 TermManager::clear_under_cursor()?;
217                 let y = ui.cursor.y() as usize;
218                 let old_line_count = ui.buffer.line_count();
219 
220                 let count = old_line_count - y as usize;
221                 ui.buffer.delete_line(y);
222                 ui.render_content(y as u16, count.max(1))?;
223 
224                 if y == old_line_count - 1 {
225                     self.up(ui)?;
226                 }
227 
228                 if old_line_count == 1 {
229                     ui.cursor.move_to_columu(0)?;
230                     ui.buffer.insert_char('\n' as u8, 0, 0);
231                     ui.render_content(0, 1)?;
232                 }
233             }
234             b'0' => {
235                 let x = ui.cursor.x() as usize;
236                 let y = ui.cursor.y() as usize;
237                 match ui.buffer.delete_until_line_beg(x, y) {
238                     Some(..) => {
239                         // 文本变动重新渲染
240                         ui.cursor.move_to_columu(0)?;
241                         ui.render_content(y as u16, 1)?;
242                     }
243                     None => {}
244                 };
245             }
246             b'$' => {
247                 let x = ui.cursor.x() as usize;
248                 let y = ui.cursor.y() as usize;
249                 match ui.buffer.delete_until_endl(x, y) {
250                     Some(..) => {
251                         ui.cursor.move_left(1)?;
252                         ui.render_content(y as u16, 1)?;
253                     }
254                     None => {}
255                 }
256             }
257 
258             b'w' | b'e' => {
259                 let x = ui.cursor.x();
260                 let y = ui.cursor.y();
261                 let next_word_pos = ui.buffer.search_nextw_begin(x, y);
262                 let linesize = ui.buffer.get_linesize(y);
263 
264                 // 如果下一个单词在当前行,则删除当前单词
265                 if next_word_pos < linesize.into() {
266                     ui.buffer.remove_str(x, y, next_word_pos - x as usize);
267                 } else {
268                     // 如果下一个单词在下一行,则删除当前行剩余部分
269                     self.left(ui)?;
270                     ui.buffer.delete_until_endl(x.into(), y.into());
271                 }
272                 ui.render_content(y, 1)?;
273             }
274 
275             b'b' => {
276                 let old_x = ui.cursor.x();
277                 let old_y = ui.cursor.y();
278 
279                 self.jump_to_prevw_beg(ui)?;
280 
281                 let x = ui.cursor.x();
282                 let y = ui.cursor.y();
283                 if old_y == y {
284                     ui.buffer.remove_str(x, y, old_x as usize - x as usize);
285                     ui.render_content(y, 1)?;
286                 } else {
287                     ui.buffer.delete_until_endl(x as usize, y as usize);
288                     ui.buffer
289                         .delete_until_line_beg(old_x as usize, old_y as usize);
290                     ui.buffer.merge_line(old_y);
291                     let linecount = ui.buffer.line_count();
292                     TermManager::clear_under_cursor()?;
293                     ui.render_content(y, linecount - y as usize - 1)?;
294                 }
295             }
296             _ => {}
297         }
298         return Ok(WarpUiCallBackType::None);
299     }
300 
301     fn jump_to_next_word(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
302         let x = ui.cursor.x();
303         let y = ui.cursor.y();
304         let pos = ui.buffer.search_nextw_begin(x, y);
305         let linesize = ui.buffer.get_linesize(y);
306 
307         if pos < linesize as usize {
308             // 如果下一个单词在当前行,则移动光标到该单词的起始位置
309             ui.cursor.move_to_columu(pos as u16)?;
310         } else if y + 1 < ui.buffer.line_count() as u16 {
311             // 如果当前行不是最后一行,则移动到下一行的开头
312             self.down(ui)?;
313             ui.cursor.move_to_columu(0)?;
314         } else {
315             // 如果当前行是最后一行,则移动到当前行的末尾
316             ui.cursor.move_to_columu(linesize as u16 - 1)?;
317         }
318         return Ok(WarpUiCallBackType::None);
319     }
320 
321     fn jump_to_nextw_ending(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
322         let x = ui.cursor.x();
323         let y = ui.cursor.y();
324         let linesize = ui.buffer.get_linesize(y) as usize;
325 
326         // 如果光标已经在当前行的末尾或最后一个字符,则尝试移动到下一行的末尾或单词末尾
327         let final_char_pos = linesize - 2;
328         if x as usize >= final_char_pos {
329             if y < ui.buffer.line_count() as u16 - 1 {
330                 let next_end_pos = ui.buffer.search_nextw_end(0, y + 1) as u16;
331                 ui.cursor.move_to(next_end_pos, y + 1)?;
332                 ui.cursor.highlight(Some(y))?;
333             } else {
334                 // 如果已经是最后一行,则保持光标在当前行的末尾
335                 ui.cursor.move_to_columu(linesize as u16 - 1)?;
336             }
337             return Ok(WarpUiCallBackType::None);
338         }
339 
340         let next_end_pos = ui.buffer.search_nextw_end(x, y) as u16;
341         // 如果下一个单词的末尾在当前行,则移动光标到该单词的末尾
342         ui.cursor
343             .move_to_columu(next_end_pos.min(linesize as u16 - 2))?;
344         return Ok(WarpUiCallBackType::None);
345     }
346 
347     fn jump_to_prevw_beg(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
348         let x = ui.cursor.x();
349         let y = ui.cursor.y();
350 
351         // 如果光标已在行首,则尝试移动到上一行的单词首字母
352         if x == 0 {
353             if y > 0 {
354                 let end_of_prev_line = ui.buffer.get_linesize(y - 1) - 1;
355                 let prev_word_pos = match ui.buffer.search_prevw_begin(end_of_prev_line, y - 1) {
356                     Some(pos) => pos,
357                     None => 0,
358                 };
359                 ui.cursor.move_to(prev_word_pos as u16, y - 1)?;
360                 ui.cursor.highlight(Some(y))?;
361             } else {
362                 // 如果已经是第一行,则保持光标在当前行的起始位置
363                 ui.cursor.move_to_columu(0)?;
364             }
365             return Ok(WarpUiCallBackType::None);
366         }
367 
368         let prev_word_pos = match ui.buffer.search_prevw_begin(x, y) {
369             Some(pos) => pos,
370             None => 0,
371         };
372 
373         ui.cursor.move_to(prev_word_pos as u16, y)?;
374         return Ok(WarpUiCallBackType::None);
375     }
376 }
377 
378 impl KeyEventCallback for Command {
379     fn backspace(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
380         Ok(WarpUiCallBackType::None)
381     }
382     fn enter(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
383         Ok(WarpUiCallBackType::None)
384     }
385 
386     fn tab(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
387         Ok(WarpUiCallBackType::None)
388     }
389 
390     fn esc(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
391         Ok(WarpUiCallBackType::None)
392     }
393 
394     fn input_data(
395         &self,
396         ui: &mut MutexGuard<UiCore>,
397         data: &[u8],
398     ) -> io::Result<WarpUiCallBackType> {
399         match data {
400             b":" => {
401                 // 保存位置
402                 ui.cursor.store_pos();
403                 return Ok(WarpUiCallBackType::ChangMode(ModeType::LastLine));
404             }
405 
406             b"i" | b"I" => {
407                 // 切换Insert模式
408                 return Ok(WarpUiCallBackType::ChangMode(ModeType::Insert));
409             }
410 
411             // hjkl 与 Vim 的效果一致
412             b"h" => self.left(ui),
413 
414             // 向下
415             b"j" => self.down(ui),
416 
417             // 向上
418             b"k" => self.up(ui),
419 
420             //  向右
421             b"l" => self.right(ui),
422 
423             b"L" => {
424                 // 设置当前行lock
425                 let flag = ui.buffer.line_flags(ui.cursor.y());
426                 let offset = ui.buffer.offset();
427                 if flag.contains(LineState::LOCKED) {
428                     ui.buffer
429                         .remove_line_flags(offset + ui.cursor.y() as usize, LineState::LOCKED);
430                 } else {
431                     ui.buffer
432                         .add_line_flags(offset + ui.cursor.y() as usize, LineState::LOCKED);
433                 }
434                 let y = ui.cursor.y();
435                 ui.render_content(y, 1)?;
436                 return Ok(WarpUiCallBackType::None);
437             }
438 
439             b"f" | b"F" => {
440                 // 设置当前行flag
441                 let flag = ui.buffer.line_flags(ui.cursor.y());
442                 let offset = ui.buffer.offset();
443                 if flag.contains(LineState::FLAGED) {
444                     ui.buffer
445                         .remove_line_flags(offset + ui.cursor.y() as usize, LineState::FLAGED);
446                 } else {
447                     ui.buffer
448                         .add_line_flags(offset + ui.cursor.y() as usize, LineState::FLAGED);
449                 }
450 
451                 let y = ui.cursor.y();
452                 ui.render_content(y, 1)?;
453                 return Ok(WarpUiCallBackType::None);
454             }
455 
456             b"q" | b"Q" => {
457                 // 跳转到上一个flag行
458                 self.jump_to_previous_flag(ui, LineState::FLAGED)?;
459                 return Ok(WarpUiCallBackType::None);
460             }
461 
462             b"w" => self.jump_to_next_word(ui),
463 
464             b"e" => self.jump_to_nextw_ending(ui),
465 
466             b"b" => self.jump_to_prevw_beg(ui),
467 
468             b"W" => {
469                 // 跳转到下一个flag行
470                 self.jump_to_next_flag(ui, LineState::FLAGED)?;
471                 return Ok(WarpUiCallBackType::None);
472             }
473 
474             b"a" | b"A" => {
475                 self.jump_to_previous_flag(ui, LineState::LOCKED)?;
476                 return Ok(WarpUiCallBackType::None);
477             }
478 
479             b"s" | b"S" => {
480                 self.jump_to_next_flag(ui, LineState::LOCKED)?;
481                 return Ok(WarpUiCallBackType::None);
482             }
483 
484             b"0" => {
485                 // 移动到行首
486                 ui.cursor.move_to_columu(0)?;
487                 return Ok(WarpUiCallBackType::None);
488             }
489 
490             b"^" => self.jump_to_first_char(ui),
491 
492             b"$" => {
493                 // 移动到行末
494                 let line_end = ui.buffer.get_linesize(ui.cursor.y()) - 1;
495                 ui.cursor.move_to_columu(line_end)?;
496                 return Ok(WarpUiCallBackType::None);
497             }
498 
499             b"d" => self.do_delete_on_d_clicked(ui),
500 
501             b"x" => {
502                 let y = ui.cursor.y();
503                 let x = ui.cursor.x();
504                 if x < ui.buffer.get_linesize(y) - 1 {
505                     ui.buffer.remove_char(x, y);
506                     ui.render_content(y, 1)?;
507                 }
508                 return Ok(WarpUiCallBackType::None);
509             }
510 
511             b"G" => {
512                 // 移动到最后一行
513                 let line_count = ui.buffer.line_count() as u16;
514                 let y = ui.cursor.y();
515                 let new_y = ui.buffer.goto_line(line_count as usize - 1);
516                 ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)?;
517                 ui.cursor.move_to_row(new_y)?;
518                 ui.cursor.highlight(Some(y))?;
519                 return Ok(WarpUiCallBackType::None);
520             }
521 
522             _ => {
523                 return Ok(WarpUiCallBackType::None);
524             }
525         }
526     }
527 }
528 
529 #[derive(Debug)]
530 pub struct Insert;
531 impl KeyEventCallback for Insert {
532     fn enter(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
533         let line_idx = ui.cursor.y();
534         let col = ui.cursor.x();
535 
536         let line = ui.buffer.get_line(line_idx);
537         if line.flags.contains(LineState::LOCKED) {
538             APP_INFO.lock().unwrap().info = "Row is locked".to_string();
539             return Ok(WarpUiCallBackType::None);
540         }
541         ui.buffer.input_enter(col, line_idx);
542 
543         DEF_STYLE.read().unwrap().set_content_style()?;
544         // 清空改行光标后的内容
545         TermManager::clear_until_new_line()?;
546 
547         // 执行渲染后续文本
548         ui.cursor.move_to_nextline(1)?;
549         ui.cursor.clear_current_line()?;
550 
551         let ret = ui.render_content(
552             line_idx + 1,
553             (CONTENT_WINSIZE.read().unwrap().rows - line_idx) as usize,
554         )?;
555 
556         if ret == 0 {
557             ui.scroll_up(1)?;
558             ui.render_content(
559                 line_idx + 1,
560                 (CONTENT_WINSIZE.read().unwrap().rows - line_idx) as usize,
561             )?;
562 
563             ui.cursor.move_up(1)?;
564         }
565 
566         let last = ui.cursor.y() - 1;
567         ui.cursor.highlight(Some(last))?;
568         ui.set_edited();
569         Ok(WarpUiCallBackType::None)
570     }
571 
572     fn tab(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
573         ui.set_edited();
574         let x = ui.cursor.x();
575 
576         let tab_size = TAB_SIZE.load(Ordering::SeqCst);
577         let space_size = tab_size - (x % tab_size);
578 
579         for _ in 0..space_size {
580             ui.buffer
581                 .insert_char(' ' as u8, ui.cursor.x(), ui.cursor.y());
582         }
583 
584         let y = ui.cursor.y();
585         ui.render_content(y, 1)?;
586 
587         ui.cursor.move_right(space_size)?;
588 
589         Ok(WarpUiCallBackType::None)
590     }
591 
592     fn esc(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
593         Ok(WarpUiCallBackType::ChangMode(ModeType::Command))
594     }
595 
596     fn input_data(
597         &self,
598         ui: &mut MutexGuard<UiCore>,
599         data: &[u8],
600     ) -> io::Result<WarpUiCallBackType> {
601         let x = ui.cursor.x();
602         let y = ui.cursor.y();
603 
604         let line = ui.buffer.get_line(y);
605         if line.flags.contains(LineState::LOCKED) {
606             APP_INFO.lock().unwrap().info = "Row is locked".to_string();
607             return Ok(WarpUiCallBackType::None);
608         }
609 
610         for (idx, ch) in data.iter().enumerate() {
611             ui.buffer.insert_char(*ch, x + idx as u16, y);
612         }
613 
614         let line_data = ui.buffer.get_line(y);
615 
616         // 考虑长度包含\n,所以要减1
617         ui.cursor.write(String::from_utf8_lossy(
618             &line_data.data[x as usize..(line_data.size() - 1)],
619         ))?;
620 
621         ui.cursor.move_to_columu(x + data.len() as u16)?;
622         ui.set_edited();
623         ui.cursor.highlight(None)?;
624         Ok(WarpUiCallBackType::None)
625     }
626 }
627 
628 #[derive(Debug)]
629 pub struct LastLine {
630     buf: Mutex<Vec<u8>>,
631 }
632 
633 impl LastLine {
634     pub fn new() -> Self {
635         Self {
636             buf: Mutex::new(vec![':' as u8]),
637         }
638     }
639 
640     pub fn reset(&self) {
641         self.buf.lock().unwrap().resize(1, ':' as u8);
642     }
643 }
644 
645 impl KeyEventCallback for LastLine {
646     fn enter(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
647         let mut buf = self.buf.lock().unwrap();
648         let cmd = String::from_utf8_lossy(&buf).to_string();
649 
650         let ret = LastLineCommand::process(ui, cmd);
651 
652         ui.cursor.move_to(1, u16::MAX - 1)?;
653         // ui.cursor.move_to_columu(1)?;
654         TermManager::clear_until_new_line()?;
655         ui.cursor.move_to(1, u16::MAX - 1)?;
656 
657         buf.resize(1, 0);
658         if ret == WarpUiCallBackType::None {
659             ui.cursor.restore_pos()?;
660             return Ok(WarpUiCallBackType::ChangMode(ModeType::Command));
661         }
662 
663         Ok(ret)
664     }
665 
666     fn tab(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
667         Ok(WarpUiCallBackType::None)
668     }
669 
670     fn backspace(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
671         if ui.cursor.x() == 1 {
672             return Ok(WarpUiCallBackType::None);
673         }
674 
675         self.left(ui)?;
676         self.buf.lock().unwrap().remove(ui.cursor.x() as usize);
677 
678         ui.cursor.write(' ')?;
679         self.left(ui)?;
680 
681         Ok(WarpUiCallBackType::None)
682     }
683 
684     fn up(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
685         Ok(WarpUiCallBackType::None)
686     }
687 
688     fn down(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
689         Ok(WarpUiCallBackType::None)
690     }
691 
692     fn esc(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
693         ui.cursor.restore_pos()?;
694         Ok(WarpUiCallBackType::ChangMode(ModeType::Command))
695     }
696 
697     fn input_data(
698         &self,
699         ui: &mut MutexGuard<UiCore>,
700         data: &[u8],
701     ) -> io::Result<WarpUiCallBackType> {
702         let mut buf = self.buf.lock().unwrap();
703 
704         if ui.cursor.x() == buf.len() as u16 {
705             buf.extend(data);
706         } else {
707             let index = ui.cursor.x() as usize;
708             for (i, &item) in data.iter().enumerate() {
709                 buf.insert(index + i, item);
710             }
711         }
712 
713         ui.cursor.write(String::from_utf8_lossy(&data))?;
714 
715         Ok(WarpUiCallBackType::None)
716     }
717 }
718