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