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] 30 pub fn move_to(x: u16, y: u16) -> io::Result<()> { 31 stdout().execute(MoveTo(x, y)).unwrap().flush() 32 } 33 34 #[inline] 35 pub fn move_to_nextline(lines: u16) -> io::Result<()> { 36 stdout().execute(MoveToNextLine(lines)).unwrap().flush() 37 } 38 39 #[inline] 40 pub fn move_to_previous_line(lines: u16) -> io::Result<()> { 41 stdout().execute(MoveToPreviousLine(lines)).unwrap().flush() 42 } 43 44 #[inline] 45 pub fn move_to_columu(col: u16) -> io::Result<()> { 46 stdout().execute(MoveToColumn(col)).unwrap().flush() 47 } 48 49 #[inline] 50 pub fn move_to_row(row: u16) -> io::Result<()> { 51 stdout().execute(MoveToRow(row)).unwrap().flush() 52 } 53 54 #[inline] 55 pub fn move_up(count: u16) -> io::Result<()> { 56 stdout().execute(MoveUp(count)).unwrap().flush() 57 } 58 59 #[inline] 60 pub fn move_down(count: u16) -> io::Result<()> { 61 stdout().execute(MoveDown(count)).unwrap().flush() 62 } 63 64 #[inline] 65 pub fn move_left(count: u16) -> io::Result<()> { 66 stdout().execute(MoveLeft(count)).unwrap().flush() 67 } 68 69 #[inline] 70 pub fn move_right(count: u16) -> io::Result<()> { 71 stdout().execute(MoveRight(count)).unwrap().flush() 72 } 73 74 #[inline] 75 pub fn save_position() -> io::Result<()> { 76 stdout().execute(SavePosition).unwrap().flush() 77 } 78 79 #[inline] 80 pub fn restore_position() -> io::Result<()> { 81 stdout().execute(RestorePosition).unwrap().flush() 82 } 83 84 #[inline] 85 pub fn hide() -> io::Result<()> { 86 stdout().execute(Hide).unwrap().flush() 87 } 88 89 #[inline] 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; 118 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 132 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 143 pub fn y(&self) -> u16 { 144 self.y 145 } 146 147 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] 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 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 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 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 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 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 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 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 267 pub fn move_left(&mut self, count: u16) -> io::Result<()> { 268 let result = match self.x { 269 x if x == 0 => Ok(()), 270 x if x < count => self.move_to_columu(0), 271 x => match self.prefix_mode { 272 true if x == self.line_prefix_width - 1 => Ok(()), 273 true if x - count < self.line_prefix_width => self.move_to_columu(0), 274 _ => { 275 self.x -= count; 276 self.move_to_columu(x - count) 277 } 278 }, 279 }; 280 281 result 282 } 283 284 pub fn move_right(&mut self, count: u16) -> io::Result<()> { 285 let mut linesize = self.buf.get_linesize(self.y()) - 1; 286 let mut size = *WINSIZE.read().unwrap(); 287 if self.prefix_mode { 288 size.cols -= self.line_prefix_width; 289 linesize += self.line_prefix_width; 290 } 291 if self.x == size.cols - 1 { 292 return Ok(()); 293 } 294 295 if self.x + count > linesize { 296 CursorManager::move_to_columu(linesize)?; 297 self.x = linesize; 298 } else { 299 CursorManager::move_right(count)?; 300 self.x += count; 301 } 302 303 Ok(()) 304 } 305 306 pub fn write<D: Display>(&mut self, str: D) -> io::Result<()> { 307 let str = str.to_string(); 308 309 let ss = str.split_terminator(|x| x == '\n').collect::<Vec<&str>>(); 310 for s in ss { 311 self.write_line(s)?; 312 } 313 Ok(()) 314 } 315 316 fn write_line(&mut self, str: &str) -> io::Result<()> { 317 let len = str.len() as u16; 318 319 let mut size = *WINSIZE.read().unwrap(); 320 321 if self.prefix_mode { 322 size.cols -= self.line_prefix_width; 323 } 324 325 if self.x + len > size.cols { 326 let ss = str.split_at((size.cols - self.x) as usize); 327 TermIO::write_str(ss.0)?; 328 self.move_to_nextline(1)?; 329 self.write_line(ss.1)?; 330 } else { 331 TermIO::write_str(str)?; 332 if str.ends_with(|x| x == '\n') { 333 self.move_to_nextline(1)?; 334 } else { 335 self.x += str.len() as u16; 336 } 337 } 338 339 Ok(()) 340 } 341 342 pub fn write_with_pos<D: Display>( 343 &mut self, 344 str: D, 345 x: u16, 346 y: u16, 347 stroe: bool, 348 ) -> io::Result<()> { 349 let mut pos = (0, 0); 350 if stroe { 351 pos = self.store_tmp_pos(); 352 } 353 self.move_to(x, y)?; 354 self.write(str)?; 355 if stroe { 356 self.restore_tmp_pos(pos)?; 357 } 358 Ok(()) 359 } 360 361 pub fn store_pos(&mut self) { 362 if self.store_flag { 363 panic!("Stored val doesn't restore") 364 } 365 self.stored_x = self.x; 366 self.stored_y = self.y; 367 self.store_flag = true; 368 } 369 370 pub fn restore_pos(&mut self) -> io::Result<()> { 371 if !self.store_flag { 372 panic!("No val stored") 373 } 374 self.x = self.stored_x; 375 self.y = self.stored_y; 376 self.store_flag = false; 377 CursorManager::move_to(self.stored_x, self.stored_y) 378 } 379 380 #[inline] 381 pub fn store_tmp_pos(&mut self) -> (u16, u16) { 382 (self.x(), self.y()) 383 } 384 385 pub fn restore_tmp_pos(&mut self, pos: (u16, u16)) -> io::Result<()> { 386 self.move_to(pos.0, pos.1) 387 } 388 389 /// 更新前缀列 390 pub fn update_line_prefix( 391 &mut self, 392 content: &Vec<LineBuffer>, 393 start: u16, 394 number_len: usize, 395 ) -> io::Result<()> { 396 let startline = self.buf.offset() + 1; 397 let size = *CONTENT_WINSIZE.read().unwrap(); 398 let max_line = startline + size.rows as usize; 399 400 // 先关闭prefix模式 401 self.set_prefix_mode(false); 402 403 // 绝对坐标 404 let (x, y) = (self.x(), self.y()); 405 406 // 更新第一列flags 407 for (num, line) in content.iter().enumerate() { 408 // 设置颜色 409 StyleManager::set_background_color(self.line_setting.line_num.background)?; 410 StyleManager::set_foreground_color(self.line_setting.line_num.frontground)?; 411 self.move_to(0, start + num as u16)?; 412 let flags = line.flags; 413 flags.set_style()?; 414 self.write("~")?; 415 StyleManager::reset_color()?; 416 } 417 418 // 更新页面行号 419 if self.line_setting.line_num.enable { 420 let len = number_len + 2; 421 self.line_prefix_width = len as u16 + Self::PREFIX_COL; 422 423 // 设置颜色 424 StyleManager::set_background_color(self.line_setting.line_num.background)?; 425 StyleManager::set_foreground_color(self.line_setting.line_num.frontground)?; 426 for line in startline..max_line { 427 self.move_to(Self::PREFIX_COL, (line - startline) as u16)?; 428 let mut prefix = line.to_string(); 429 430 prefix.insert(0, ' '); 431 unsafe { 432 let data = prefix.as_mut_vec(); 433 data.resize(len, ' ' as u8); 434 }; 435 436 self.write(prefix)?; 437 } 438 StyleManager::reset_color()?; 439 } 440 // 恢复绝对坐标 441 self.move_to(x, y)?; 442 443 self.set_prefix_mode(true); 444 445 Ok(()) 446 } 447 448 pub fn clear_current_line(&mut self) -> io::Result<()> { 449 if self.prefix_mode { 450 let tmp = self.x(); 451 self.move_to_columu(0)?; 452 TermManager::clear_until_new_line()?; 453 self.move_to_columu(tmp) 454 } else { 455 TermManager::clear_current_line() 456 } 457 } 458 459 pub fn highlight(&mut self, last_line: Option<u16>) -> io::Result<()> { 460 if !self.line_setting.highlight.enable { 461 return Ok(()); 462 } 463 DEF_STYLE.read().unwrap().set_content_style()?; 464 465 if last_line.is_some() { 466 let last_line = last_line.unwrap(); 467 // 清除上一行高光 468 let pos = self.store_tmp_pos(); 469 self.move_to(0, last_line)?; 470 self.clear_current_line()?; 471 self.write(String::from_utf8_lossy(&self.buf.get_line(last_line)))?; 472 self.restore_tmp_pos(pos)?; 473 } 474 475 let pos = self.store_tmp_pos(); 476 // 设置高光 477 StyleManager::set_background_color(self.line_setting.highlight.color)?; 478 self.clear_current_line()?; 479 self.move_to_columu(0)?; 480 self.write(String::from_utf8_lossy(&self.buf.get_line(self.y())))?; 481 self.restore_tmp_pos(pos)?; 482 483 Ok(()) 484 } 485 } 486