1 use std::{ 2 fmt::Display, 3 io::{self, stdout, Write}, 4 sync::Arc, 5 }; 6 7 use crossterm::{ 8 cursor::{ 9 Hide, MoveDown, MoveLeft, MoveRight, MoveTo, MoveToColumn, MoveToNextLine, 10 MoveToPreviousLine, MoveToRow, MoveUp, RestorePosition, SavePosition, Show, 11 }, 12 ExecutableCommand, 13 }; 14 15 use crate::config::appconfig::LineSetting; 16 17 use super::{ 18 buffer::{EditBuffer, LineBuffer}, 19 style::StyleManager, 20 term_io::TermIO, 21 terminal::TermManager, 22 ui::uicore::{CONTENT_WINSIZE, DEF_STYLE, WINSIZE}, 23 }; 24 25 struct CursorManager; 26 27 #[allow(dead_code)] 28 impl CursorManager { 29 #[inline] move_to(x: u16, y: u16) -> io::Result<()>30 pub fn move_to(x: u16, y: u16) -> io::Result<()> { 31 stdout().execute(MoveTo(x, y)).unwrap().flush() 32 } 33 34 #[inline] move_to_nextline(lines: u16) -> io::Result<()>35 pub fn move_to_nextline(lines: u16) -> io::Result<()> { 36 stdout().execute(MoveToNextLine(lines)).unwrap().flush() 37 } 38 39 #[inline] move_to_previous_line(lines: u16) -> io::Result<()>40 pub fn move_to_previous_line(lines: u16) -> io::Result<()> { 41 stdout().execute(MoveToPreviousLine(lines)).unwrap().flush() 42 } 43 44 #[inline] move_to_columu(col: u16) -> io::Result<()>45 pub fn move_to_columu(col: u16) -> io::Result<()> { 46 stdout().execute(MoveToColumn(col)).unwrap().flush() 47 } 48 49 #[inline] move_to_row(row: u16) -> io::Result<()>50 pub fn move_to_row(row: u16) -> io::Result<()> { 51 stdout().execute(MoveToRow(row)).unwrap().flush() 52 } 53 54 #[inline] move_up(count: u16) -> io::Result<()>55 pub fn move_up(count: u16) -> io::Result<()> { 56 stdout().execute(MoveUp(count)).unwrap().flush() 57 } 58 59 #[inline] move_down(count: u16) -> io::Result<()>60 pub fn move_down(count: u16) -> io::Result<()> { 61 stdout().execute(MoveDown(count)).unwrap().flush() 62 } 63 64 #[inline] move_left(count: u16) -> io::Result<()>65 pub fn move_left(count: u16) -> io::Result<()> { 66 stdout().execute(MoveLeft(count)).unwrap().flush() 67 } 68 69 #[inline] move_right(count: u16) -> io::Result<()>70 pub fn move_right(count: u16) -> io::Result<()> { 71 stdout().execute(MoveRight(count)).unwrap().flush() 72 } 73 74 #[inline] save_position() -> io::Result<()>75 pub fn save_position() -> io::Result<()> { 76 stdout().execute(SavePosition).unwrap().flush() 77 } 78 79 #[inline] restore_position() -> io::Result<()>80 pub fn restore_position() -> io::Result<()> { 81 stdout().execute(RestorePosition).unwrap().flush() 82 } 83 84 #[inline] hide() -> io::Result<()>85 pub fn hide() -> io::Result<()> { 86 stdout().execute(Hide).unwrap().flush() 87 } 88 89 #[inline] show() -> io::Result<()>90 pub fn show() -> io::Result<()> { 91 stdout().execute(Show).unwrap().flush() 92 } 93 } 94 95 #[derive(Debug)] 96 pub struct CursorCrtl { 97 x: u16, 98 y: u16, 99 100 // 用于处理状态位置 101 stored_x: u16, 102 stored_y: u16, 103 104 line_prefix_width: u16, 105 store_flag: bool, 106 107 // 正文模式会输出前缀,这个标志表示是否需要以正文前缀模式调整坐标 108 prefix_mode: bool, 109 110 line_setting: LineSetting, 111 112 buf: Arc<EditBuffer>, 113 } 114 115 #[allow(dead_code)] 116 impl CursorCrtl { 117 pub const PREFIX_COL: u16 = 1; new(buf: Arc<EditBuffer>, line_setting: LineSetting) -> Self118 pub fn new(buf: Arc<EditBuffer>, line_setting: LineSetting) -> Self { 119 Self { 120 x: 0, 121 y: 0, 122 stored_x: 0, 123 stored_y: 0, 124 store_flag: false, 125 line_prefix_width: Self::PREFIX_COL, 126 prefix_mode: true, 127 line_setting, 128 buf, 129 } 130 } 131 x(&self) -> u16132 pub fn x(&self) -> u16 { 133 if self.prefix_mode { 134 if self.x < self.line_prefix_width { 135 return 0; 136 } 137 self.x - self.line_prefix_width 138 } else { 139 self.x 140 } 141 } 142 y(&self) -> u16143 pub fn y(&self) -> u16 { 144 self.y 145 } 146 cmd_y(&self) -> u16147 pub fn cmd_y(&self) -> u16 { 148 if self.store_flag { 149 self.stored_y 150 } else { 151 self.y 152 } 153 } 154 155 #[inline] set_prefix_mode(&mut self, on: bool)156 pub fn set_prefix_mode(&mut self, on: bool) { 157 self.prefix_mode = on; 158 if on && self.x < self.line_prefix_width { 159 self.x = self.line_prefix_width; 160 self.move_to_columu(0).unwrap(); 161 } 162 } 163 move_to(&mut self, mut x: u16, y: u16) -> io::Result<()>164 pub fn move_to(&mut self, mut x: u16, y: u16) -> io::Result<()> { 165 if self.prefix_mode { 166 x += self.line_prefix_width; 167 } 168 let size = *WINSIZE.read().unwrap(); 169 CursorManager::move_to(x, y)?; 170 self.x = (size.cols - 1).min(x); 171 self.y = (size.rows - 1).min(y); 172 Ok(()) 173 } 174 move_to_nextline(&mut self, mut lines: u16) -> io::Result<()>175 pub fn move_to_nextline(&mut self, mut lines: u16) -> io::Result<()> { 176 let size = *WINSIZE.read().unwrap(); 177 if self.y + lines >= size.rows { 178 // 向上滚动 179 // 保存位置 180 let pos = self.store_tmp_pos(); 181 // 计算需要滚动的行数 182 let offset = self.buf.offset(); 183 if offset < lines as usize { 184 lines = offset as u16; 185 } 186 // 重新设置偏移位置 187 self.buf.set_offset(offset - lines as usize); 188 //翻页并恢复位置 189 TermManager::scroll_up(lines)?; 190 self.restore_tmp_pos(pos)?; 191 } 192 193 CursorManager::move_to_nextline(lines)?; 194 if self.prefix_mode { 195 self.x = self.line_prefix_width; 196 self.move_to_columu(0)?; 197 } else { 198 self.x = 0; 199 } 200 201 self.y += lines; 202 Ok(()) 203 } 204 move_to_previous_line(&mut self, mut lines: u16) -> io::Result<()>205 pub fn move_to_previous_line(&mut self, mut lines: u16) -> io::Result<()> { 206 if self.y() < lines { 207 // 溢出,则向下滚动 208 209 // 保存位置 210 let pos = self.store_tmp_pos(); 211 let offset = self.buf.offset(); 212 // 计算需要滚动的行数 213 let line_count = self.buf.line_count(); 214 if line_count < offset + lines as usize { 215 lines = (line_count - offset) as u16; 216 } 217 // 重新设置偏移位置 218 self.buf.set_offset(offset + lines as usize); 219 //翻页并恢复位置 220 TermManager::scroll_up(lines)?; 221 self.restore_tmp_pos(pos)?; 222 } 223 224 CursorManager::move_to_previous_line(lines)?; 225 226 self.y -= lines; 227 if self.prefix_mode { 228 self.x = self.line_prefix_width; 229 self.move_to_columu(0)?; 230 } else { 231 self.x = 0; 232 } 233 Ok(()) 234 } 235 move_to_columu(&mut self, mut col: u16) -> io::Result<()>236 pub fn move_to_columu(&mut self, mut col: u16) -> io::Result<()> { 237 if self.prefix_mode { 238 col += self.line_prefix_width; 239 } 240 let size = *WINSIZE.read().unwrap(); 241 CursorManager::move_to_columu(col)?; 242 self.x = (size.cols - 1).min(col); 243 Ok(()) 244 } 245 move_to_row(&mut self, row: u16) -> io::Result<()>246 pub fn move_to_row(&mut self, row: u16) -> io::Result<()> { 247 let size = *WINSIZE.read().unwrap(); 248 CursorManager::move_to_row(row)?; 249 self.y = (size.rows - 1).min(row); 250 Ok(()) 251 } 252 move_up(&mut self, count: u16) -> io::Result<()>253 pub fn move_up(&mut self, count: u16) -> io::Result<()> { 254 CursorManager::move_up(count)?; 255 self.y -= count; 256 257 Ok(()) 258 } 259 move_down(&mut self, count: u16) -> io::Result<()>260 pub fn move_down(&mut self, count: u16) -> io::Result<()> { 261 CursorManager::move_down(count)?; 262 263 self.y += count; 264 Ok(()) 265 } 266 move_left(&mut self, count: u16) -> io::Result<()>267 pub fn move_left(&mut self, count: u16) -> io::Result<()> { 268 // 如果当前光标位置小于或等于行前缀宽度,或者移动的距离大于当前光标位置,则直接移动到行前缀末尾 269 if self.x <= self.line_prefix_width || count > self.x { 270 return self.move_to_columu(0); 271 } 272 273 // 如果启用了前缀模式且光标在前缀区域内,不进行移动 274 if self.prefix_mode && self.x <= self.line_prefix_width { 275 return Ok(()); 276 } 277 278 // 计算实际移动的距离 279 let actual_move = if count > self.x - self.line_prefix_width { 280 self.x - self.line_prefix_width 281 } else { 282 count 283 }; 284 285 // 执行光标左移操作 286 CursorManager::move_left(actual_move)?; 287 288 // 更新光标位置 289 self.x -= actual_move; 290 291 Ok(()) 292 } 293 move_right(&mut self, count: u16) -> io::Result<()>294 pub fn move_right(&mut self, count: u16) -> io::Result<()> { 295 let mut linesize = self.buf.get_linesize(self.y()) - 1; 296 let mut size = *WINSIZE.read().unwrap(); 297 if self.prefix_mode { 298 size.cols -= self.line_prefix_width; 299 linesize += self.line_prefix_width; 300 } 301 if self.x == size.cols - 1 { 302 return Ok(()); 303 } 304 305 if self.x + count > linesize { 306 CursorManager::move_to_columu(linesize)?; 307 self.x = linesize; 308 } else { 309 CursorManager::move_right(count)?; 310 self.x += count; 311 } 312 313 Ok(()) 314 } 315 write<D: Display>(&mut self, str: D) -> io::Result<()>316 pub fn write<D: Display>(&mut self, str: D) -> io::Result<()> { 317 let str = str.to_string(); 318 319 let ss = str.split_terminator(|x| x == '\n').collect::<Vec<&str>>(); 320 for s in ss { 321 self.write_line(s)?; 322 } 323 Ok(()) 324 } 325 write_line(&mut self, str: &str) -> io::Result<()>326 fn write_line(&mut self, str: &str) -> io::Result<()> { 327 let len = str.len() as u16; 328 329 let mut size = *WINSIZE.read().unwrap(); 330 331 if self.prefix_mode { 332 size.cols -= self.line_prefix_width; 333 } 334 335 if self.x + len > size.cols { 336 let ss = str.split_at((size.cols - self.x) as usize); 337 TermIO::write_str(ss.0)?; 338 self.move_to_nextline(1)?; 339 self.write_line(ss.1)?; 340 } else { 341 TermIO::write_str(str)?; 342 if str.ends_with(|x| x == '\n') { 343 self.move_to_nextline(1)?; 344 } else { 345 self.x += str.len() as u16; 346 } 347 } 348 349 Ok(()) 350 } 351 write_with_pos<D: Display>( &mut self, str: D, x: u16, y: u16, stroe: bool, ) -> io::Result<()>352 pub fn write_with_pos<D: Display>( 353 &mut self, 354 str: D, 355 x: u16, 356 y: u16, 357 stroe: bool, 358 ) -> io::Result<()> { 359 let mut pos = (0, 0); 360 if stroe { 361 pos = self.store_tmp_pos(); 362 } 363 self.move_to(x, y)?; 364 self.write(str)?; 365 if stroe { 366 self.restore_tmp_pos(pos)?; 367 } 368 Ok(()) 369 } 370 store_pos(&mut self)371 pub fn store_pos(&mut self) { 372 if self.store_flag { 373 panic!("Stored val doesn't restore") 374 } 375 self.stored_x = self.x; 376 self.stored_y = self.y; 377 self.store_flag = true; 378 } 379 restore_pos(&mut self) -> io::Result<()>380 pub fn restore_pos(&mut self) -> io::Result<()> { 381 if !self.store_flag { 382 panic!("No val stored") 383 } 384 self.x = self.stored_x; 385 self.y = self.stored_y; 386 self.store_flag = false; 387 CursorManager::move_to(self.stored_x, self.stored_y) 388 } 389 390 #[inline] store_tmp_pos(&mut self) -> (u16, u16)391 pub fn store_tmp_pos(&mut self) -> (u16, u16) { 392 (self.x(), self.y()) 393 } 394 restore_tmp_pos(&mut self, pos: (u16, u16)) -> io::Result<()>395 pub fn restore_tmp_pos(&mut self, pos: (u16, u16)) -> io::Result<()> { 396 self.move_to(pos.0, pos.1) 397 } 398 399 /// 更新前缀列 update_line_prefix( &mut self, content: &Vec<LineBuffer>, start: u16, number_len: usize, ) -> io::Result<()>400 pub fn update_line_prefix( 401 &mut self, 402 content: &Vec<LineBuffer>, 403 start: u16, 404 number_len: usize, 405 ) -> io::Result<()> { 406 let startline = self.buf.offset() + 1; 407 let size = *CONTENT_WINSIZE.read().unwrap(); 408 let max_line = startline + size.rows as usize; 409 410 // 先关闭prefix模式 411 self.set_prefix_mode(false); 412 413 // 绝对坐标 414 let (x, y) = (self.x(), self.y()); 415 416 // 更新第一列flags 417 for (num, line) in content.iter().enumerate() { 418 // 设置颜色 419 StyleManager::set_background_color(self.line_setting.line_num.background)?; 420 StyleManager::set_foreground_color(self.line_setting.line_num.frontground)?; 421 self.move_to(0, start + num as u16)?; 422 let flags = line.flags; 423 flags.set_style()?; 424 self.write("~")?; 425 StyleManager::reset_color()?; 426 } 427 428 // 更新页面行号 429 if self.line_setting.line_num.enable { 430 let len = number_len + 2; 431 self.line_prefix_width = len as u16 + Self::PREFIX_COL; 432 433 // 设置颜色 434 StyleManager::set_background_color(self.line_setting.line_num.background)?; 435 StyleManager::set_foreground_color(self.line_setting.line_num.frontground)?; 436 for line in startline..max_line { 437 self.move_to(Self::PREFIX_COL, (line - startline) as u16)?; 438 let mut prefix = line.to_string(); 439 440 prefix.insert(0, ' '); 441 unsafe { 442 let data = prefix.as_mut_vec(); 443 data.resize(len, ' ' as u8); 444 }; 445 446 self.write(prefix)?; 447 } 448 StyleManager::reset_color()?; 449 } 450 // 恢复绝对坐标 451 self.move_to(x, y)?; 452 453 self.set_prefix_mode(true); 454 455 Ok(()) 456 } 457 clear_current_line(&mut self) -> io::Result<()>458 pub fn clear_current_line(&mut self) -> io::Result<()> { 459 if self.prefix_mode { 460 let tmp = self.x(); 461 self.move_to_columu(0)?; 462 TermManager::clear_until_new_line()?; 463 self.move_to_columu(tmp) 464 } else { 465 TermManager::clear_current_line() 466 } 467 } 468 highlight(&mut self, last_line: Option<u16>) -> io::Result<()>469 pub fn highlight(&mut self, last_line: Option<u16>) -> io::Result<()> { 470 if !self.line_setting.highlight.enable { 471 return Ok(()); 472 } 473 DEF_STYLE.read().unwrap().set_content_style()?; 474 475 if last_line.is_some() { 476 let last_line = last_line.unwrap(); 477 // 清除上一行高光 478 let pos = self.store_tmp_pos(); 479 self.move_to(0, last_line)?; 480 self.clear_current_line()?; 481 self.write(String::from_utf8_lossy(&self.buf.get_line(last_line)))?; 482 self.restore_tmp_pos(pos)?; 483 } 484 485 let pos = self.store_tmp_pos(); 486 // 设置高光 487 StyleManager::set_background_color(self.line_setting.highlight.color)?; 488 self.clear_current_line()?; 489 self.move_to_columu(0)?; 490 self.write(String::from_utf8_lossy(&self.buf.get_line(self.y())))?; 491 self.restore_tmp_pos(pos)?; 492 493 Ok(()) 494 } 495 } 496