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