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, lines: u16) -> io::Result<()> { 176 let size = *WINSIZE.read().unwrap(); 177 if self.y + lines >= size.rows { 178 // 向上滚动 179 todo!() 180 } 181 182 CursorManager::move_to_nextline(lines)?; 183 if self.prefix_mode { 184 self.x = self.line_prefix_width; 185 self.move_to_columu(0)?; 186 } else { 187 self.x = 0; 188 } 189 190 self.y += lines; 191 Ok(()) 192 } 193 194 pub fn move_to_previous_line(&mut self, lines: u16) -> io::Result<()> { 195 let size = *WINSIZE.read().unwrap(); 196 197 if self.y() - lines > size.rows { 198 // 溢出,则向下滚动 199 todo!() 200 } 201 202 CursorManager::move_to_previous_line(lines)?; 203 204 self.y -= lines; 205 if self.prefix_mode { 206 self.x = self.line_prefix_width; 207 self.move_to_columu(0)?; 208 } else { 209 self.x = 0; 210 } 211 Ok(()) 212 } 213 214 pub fn move_to_columu(&mut self, mut col: u16) -> io::Result<()> { 215 if self.prefix_mode { 216 col += self.line_prefix_width; 217 } 218 let size = *WINSIZE.read().unwrap(); 219 CursorManager::move_to_columu(col)?; 220 self.x = (size.cols - 1).min(col); 221 Ok(()) 222 } 223 224 pub fn move_to_row(&mut self, row: u16) -> io::Result<()> { 225 let size = *WINSIZE.read().unwrap(); 226 CursorManager::move_to_row(row)?; 227 self.y = (size.rows - 1).min(row); 228 Ok(()) 229 } 230 231 pub fn move_up(&mut self, count: u16) -> io::Result<()> { 232 CursorManager::move_up(count)?; 233 self.y -= count; 234 235 Ok(()) 236 } 237 238 pub fn move_down(&mut self, count: u16) -> io::Result<()> { 239 CursorManager::move_down(count)?; 240 241 self.y += count; 242 Ok(()) 243 } 244 245 pub fn move_left(&mut self, mut count: u16) -> io::Result<()> { 246 if count > self.x { 247 return self.move_to_columu(0); 248 } 249 if self.prefix_mode { 250 if self.x == self.line_prefix_width - 1 { 251 return Ok(()); 252 } 253 if self.x - count < self.line_prefix_width { 254 return self.move_to_columu(0); 255 } 256 } 257 if self.x == 0 { 258 return Ok(()); 259 } 260 if count > self.x { 261 count = self.x - self.line_prefix_width 262 } 263 CursorManager::move_left(count)?; 264 265 if count > self.x { 266 self.x = self.line_prefix_width - 1; 267 } else { 268 self.x -= count; 269 } 270 271 Ok(()) 272 } 273 274 pub fn move_right(&mut self, count: u16) -> io::Result<()> { 275 let mut linesize = self.buf.get_linesize(self.y()) - 1; 276 let mut size = *WINSIZE.read().unwrap(); 277 if self.prefix_mode { 278 size.cols -= self.line_prefix_width; 279 linesize += self.line_prefix_width; 280 } 281 if self.x == size.cols - 1 { 282 return Ok(()); 283 } 284 285 if self.x + count > linesize { 286 CursorManager::move_to_columu(linesize)?; 287 self.x = linesize; 288 } else { 289 CursorManager::move_right(count)?; 290 self.x += count; 291 } 292 293 Ok(()) 294 } 295 296 pub fn write<D: Display>(&mut self, str: D) -> io::Result<()> { 297 let str = str.to_string(); 298 299 let ss = str.split_terminator(|x| x == '\n').collect::<Vec<&str>>(); 300 for s in ss { 301 self.write_line(s)?; 302 } 303 Ok(()) 304 } 305 306 fn write_line(&mut self, str: &str) -> io::Result<()> { 307 let len = str.len() as u16; 308 309 let mut size = *WINSIZE.read().unwrap(); 310 311 if self.prefix_mode { 312 size.cols -= self.line_prefix_width; 313 } 314 315 if self.x + len > size.cols { 316 let ss = str.split_at((size.cols - self.x) as usize); 317 TermIO::write_str(ss.0)?; 318 self.move_to_nextline(1)?; 319 self.write_line(ss.1)?; 320 } else { 321 TermIO::write_str(str)?; 322 if str.ends_with(|x| x == '\n') { 323 self.move_to_nextline(1)?; 324 } else { 325 self.x += str.len() as u16; 326 } 327 } 328 329 Ok(()) 330 } 331 332 pub fn write_with_pos<D: Display>( 333 &mut self, 334 str: D, 335 x: u16, 336 y: u16, 337 stroe: bool, 338 ) -> io::Result<()> { 339 let mut pos = (0, 0); 340 if stroe { 341 pos = self.store_tmp_pos(); 342 } 343 self.move_to(x, y)?; 344 self.write(str)?; 345 if stroe { 346 self.restore_tmp_pos(pos)?; 347 } 348 Ok(()) 349 } 350 351 pub fn store_pos(&mut self) { 352 if self.store_flag { 353 panic!("Stored val doesn't restore") 354 } 355 self.stored_x = self.x; 356 self.stored_y = self.y; 357 self.store_flag = true; 358 } 359 360 pub fn restore_pos(&mut self) -> io::Result<()> { 361 if !self.store_flag { 362 panic!("No val stored") 363 } 364 self.x = self.stored_x; 365 self.y = self.stored_y; 366 self.store_flag = false; 367 CursorManager::move_to(self.stored_x, self.stored_y) 368 } 369 370 #[inline] 371 pub fn store_tmp_pos(&mut self) -> (u16, u16) { 372 (self.x(), self.y()) 373 } 374 375 pub fn restore_tmp_pos(&mut self, pos: (u16, u16)) -> io::Result<()> { 376 self.move_to(pos.0, pos.1) 377 } 378 379 /// 更新前缀列 380 pub fn update_line_prefix( 381 &mut self, 382 content: &Vec<LineBuffer>, 383 start: u16, 384 number_len: usize, 385 ) -> io::Result<()> { 386 let startline = self.buf.offset() + 1; 387 let size = *CONTENT_WINSIZE.read().unwrap(); 388 let max_line = startline + size.rows as usize; 389 390 // 先关闭prefix模式 391 self.set_prefix_mode(false); 392 393 // 绝对坐标 394 let (x, y) = (self.x(), self.y()); 395 396 // 更新第一列flags 397 for (num, line) in content.iter().enumerate() { 398 // 设置颜色 399 StyleManager::set_background_color(self.line_setting.line_num.background)?; 400 StyleManager::set_foreground_color(self.line_setting.line_num.frontground)?; 401 self.move_to(0, start + num as u16)?; 402 let flags = line.flags; 403 flags.set_style()?; 404 self.write("~")?; 405 StyleManager::reset_color()?; 406 } 407 408 // 更新页面行号 409 if self.line_setting.line_num.enable { 410 let len = number_len + 2; 411 self.line_prefix_width = len as u16 + Self::PREFIX_COL; 412 413 // 设置颜色 414 StyleManager::set_background_color(self.line_setting.line_num.background)?; 415 StyleManager::set_foreground_color(self.line_setting.line_num.frontground)?; 416 for line in startline..max_line { 417 self.move_to(Self::PREFIX_COL, (line - startline) as u16)?; 418 let mut prefix = line.to_string(); 419 420 prefix.insert(0, ' '); 421 unsafe { 422 let data = prefix.as_mut_vec(); 423 data.resize(len, ' ' as u8); 424 }; 425 426 self.write(prefix)?; 427 } 428 StyleManager::reset_color()?; 429 } 430 // 恢复绝对坐标 431 self.move_to(x, y)?; 432 433 self.set_prefix_mode(true); 434 435 Ok(()) 436 } 437 438 pub fn clear_current_line(&mut self) -> io::Result<()> { 439 if self.prefix_mode { 440 let tmp = self.x(); 441 self.move_to_columu(0)?; 442 TermManager::clear_until_new_line()?; 443 self.move_to_columu(tmp) 444 } else { 445 TermManager::clear_current_line() 446 } 447 } 448 449 pub fn highlight(&mut self, last_line: Option<u16>) -> io::Result<()> { 450 if !self.line_setting.highlight.enable { 451 return Ok(()); 452 } 453 DEF_STYLE.read().unwrap().set_content_style()?; 454 455 if last_line.is_some() { 456 let last_line = last_line.unwrap(); 457 // 清除上一行高光 458 let pos = self.store_tmp_pos(); 459 self.move_to(0, last_line)?; 460 self.clear_current_line()?; 461 self.write(String::from_utf8_lossy(&self.buf.get_line(last_line)))?; 462 self.restore_tmp_pos(pos)?; 463 } 464 465 let pos = self.store_tmp_pos(); 466 // 设置高光 467 StyleManager::set_background_color(self.line_setting.highlight.color)?; 468 self.clear_current_line()?; 469 self.move_to_columu(0)?; 470 self.write(String::from_utf8_lossy(&self.buf.get_line(self.y())))?; 471 self.restore_tmp_pos(pos)?; 472 473 Ok(()) 474 } 475 } 476