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