1 use std::{io, sync::MutexGuard}; 2 3 use crate::utils::{ 4 terminal::TermManager, 5 ui::{ 6 event::{KeyEventCallback, WarpUiCallBackType}, 7 uicore::{UiCore, CONTENT_WINSIZE}, 8 }, 9 }; 10 11 pub trait CommonOp: KeyEventCallback { 12 fn remove_line(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<()> { 13 TermManager::clear_current_line()?; 14 TermManager::clear_under_cursor()?; 15 let y = ui.cursor.y() as usize; 16 let old_line_count = ui.buffer.line_count(); 17 let old_offset = ui.buffer.offset(); 18 19 let count = old_line_count - y as usize; 20 ui.buffer.delete_line(y + ui.buffer.offset() as usize); 21 ui.render_content(y as u16, count.max(1))?; 22 23 if y + old_offset == old_line_count - 1 { 24 self.up(ui)?; 25 } 26 27 if old_line_count == 1 { 28 ui.cursor.move_to_columu(0)?; 29 ui.buffer.insert_char('\n' as u8, 0, 0); 30 ui.render_content(0, 1)?; 31 } 32 33 Ok(()) 34 } 35 36 fn remove_n_line(&self, ui: &mut MutexGuard<UiCore>, n: u16) -> io::Result<()> { 37 let linecount = ui.buffer.line_count() as u16; 38 let y = ui.cursor.y(); 39 40 // 实际能删除的行数 41 let to_delete = n.min(linecount - y); 42 for _ in 0..to_delete { 43 self.remove_line(ui)?; 44 } 45 Ok(()) 46 } 47 fn remove_word(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<()> { 48 let x = ui.cursor.x(); 49 let y = ui.cursor.y(); 50 let next_word_pos = ui.buffer.search_nextw_begin(x, y); 51 let linesize = ui.buffer.get_linesize(y); 52 53 // 如果下一个单词在当前行,则删除当前单词 54 if next_word_pos < linesize.into() { 55 ui.buffer.remove_str(x, y, next_word_pos - x as usize); 56 } else { 57 // 如果下一个单词在下一行,则删除当前行剩余部分 58 self.left(ui)?; 59 ui.buffer.delete_line(y.into()); 60 self.down(ui)?; 61 } 62 ui.render_content(y, 1)?; 63 return Ok(()); 64 } 65 fn jump_to_next_word(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 66 let x = ui.cursor.x(); 67 let y = ui.cursor.y(); 68 let pos = ui.buffer.search_nextw_begin(x, y); 69 let linesize = ui.buffer.get_linesize(y); 70 let abs_y = y + ui.buffer.offset() as u16; 71 72 if pos < linesize as usize { 73 // 如果下一个单词在当前行,则移动光标到该单词的起始位置 74 ui.cursor.move_to_columu(pos as u16)?; 75 } else if y as usize + ui.buffer.offset() < ui.buffer.line_count() - 1 { 76 // 如果当前行不是最后一行,则移动到下一行的单词起始位置 77 let next_word_pos = ui.buffer.search_nextw_begin(0, y + 1) as u16; 78 let next_linesize = ui.buffer.get_linesize_abs(abs_y + 1); 79 self.down(ui)?; 80 ui.cursor 81 .move_to_columu(next_word_pos.min(next_linesize - 1))?; 82 ui.cursor.highlight(Some(y))?; 83 } else { 84 // 如果当前行是最后一行,则移动到当前行的末尾 85 ui.cursor.move_to_columu(linesize as u16 - 1)?; 86 } 87 return Ok(WarpUiCallBackType::None); 88 } 89 fn move_to_line(&self, ui: &mut MutexGuard<UiCore>, line: u16) -> io::Result<()> { 90 let x = ui.cursor.x(); 91 let y = ui.cursor.y(); 92 let new_y = ui.buffer.goto_line(line as usize); 93 let new_x = x.min(ui.buffer.get_linesize(new_y)) as u16; 94 ui.cursor.move_to(new_x, new_y)?; 95 ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)?; 96 ui.cursor.highlight(Some(y))?; 97 return Ok(()); 98 } 99 100 fn locate_prevw_begin(&self, ui: &mut MutexGuard<UiCore>, x: u16, abs_y: u16) -> (u16, u16) { 101 // 如果光标已在行首,则尝试移动到上一行的单词首字母 102 if x == 0 { 103 if abs_y == 0 { 104 return (0, 0); 105 } 106 let last_y = abs_y - 1; 107 let end_of_prev_line = ui.buffer.get_linesize_abs(last_y) - 1; 108 let prev_word_pos = ui.buffer.search_prevw_begin_abs(end_of_prev_line, last_y); 109 return (prev_word_pos as u16, last_y); 110 } 111 112 let prev_word_pos = ui.buffer.search_prevw_begin_abs(x, abs_y); 113 114 return (prev_word_pos as u16, abs_y); 115 } 116 fn locate_nextw_ending(&self, ui: &mut MutexGuard<UiCore>, x: u16, y: u16) -> (u16, u16) { 117 let linesize = ui.buffer.get_linesize(y) as usize; 118 119 // y的绝对位置 120 let abs_y = ui.buffer.offset() as u16 + y; 121 // 如果光标已经在当前行的末尾或最后一个字符(x + 2),则尝试移动到下一行的末尾或单词末尾 122 if x as usize + 2 >= linesize { 123 if abs_y < ui.buffer.line_count() as u16 - 1 { 124 let next_end_pos = ui.buffer.search_nextw_end(0, y + 1) as u16; 125 return (next_end_pos, abs_y + 1); 126 } else { 127 // 如果已经是最后一行,则保持光标在当前行的末尾 128 let x = if linesize > 0 { linesize - 1 } else { 0 }; 129 return (x as u16, abs_y); 130 } 131 } 132 133 let next_end_pos = ui.buffer.search_nextw_end(x, y) as u16; 134 // 如果下一个单词的末尾在当前行,则移动光标到该单词的末尾 135 return (next_end_pos.min(linesize as u16 - 1), abs_y); 136 } 137 } 138