1 use std::{ 2 collections::HashMap, 3 io, 4 ops::Deref, 5 sync::{ 6 atomic::{AtomicUsize, Ordering}, 7 RwLock, 8 }, 9 }; 10 11 use bitflags::bitflags; 12 use crossterm::style::Color; 13 14 use super::{ 15 style::StyleManager, 16 ui::uicore::{APP_INFO, CONTENT_WINSIZE}, 17 }; 18 19 #[derive(Debug, Default, Clone)] 20 pub struct LineBuffer { 21 id: usize, 22 23 pub data: Vec<u8>, 24 25 // 是否被标记 26 pub flags: LineState, 27 } 28 29 impl Deref for LineBuffer { 30 type Target = Vec<u8>; 31 deref(&self) -> &Self::Target32 fn deref(&self) -> &Self::Target { 33 &self.data 34 } 35 } 36 37 impl LineBuffer { new(data: Vec<u8>) -> Self38 pub fn new(data: Vec<u8>) -> Self { 39 static LINE_ID_ALLOCTOR: AtomicUsize = AtomicUsize::new(0); 40 Self { 41 id: LINE_ID_ALLOCTOR.fetch_add(1, Ordering::SeqCst), 42 data, 43 flags: LineState::empty(), 44 } 45 } 46 47 #[inline] remove(&mut self, idx: usize)48 pub fn remove(&mut self, idx: usize) { 49 self.data.remove(idx); 50 } 51 52 #[inline] size(&self) -> usize53 pub fn size(&self) -> usize { 54 self.data.len() 55 } 56 57 #[inline] extend(&mut self, other: LineBuffer)58 pub fn extend(&mut self, other: LineBuffer) { 59 self.data.extend(other.data) 60 } 61 62 #[inline] insert(&mut self, idx: usize, data: u8)63 pub fn insert(&mut self, idx: usize, data: u8) { 64 self.data.insert(idx, data) 65 } 66 } 67 68 #[derive(Debug, Default)] 69 pub struct EditBuffer { 70 buf: RwLock<Vec<LineBuffer>>, 71 72 // 记录当前页第一行对应buf中的index 73 offset: AtomicUsize, 74 75 // 记录被标记的行,行ID -> 行index 76 flag_lines: RwLock<HashMap<usize, usize>>, 77 78 // 记录锁定行 79 locked_lines: RwLock<HashMap<usize, usize>>, 80 } 81 82 impl EditBuffer { new(buf: Vec<u8>) -> Self83 pub fn new(buf: Vec<u8>) -> Self { 84 let mut lines = buf 85 .split_inclusive(|x| *x == '\n' as u8) 86 .map(|slice| slice.to_vec()) 87 .collect::<Vec<Vec<_>>>(); 88 89 let last = lines.last(); 90 if last.is_none() { 91 lines.push(vec!['\n' as u8]) 92 } else { 93 let last = last.unwrap(); 94 if !last.ends_with(&['\n' as u8]) { 95 lines.last_mut().unwrap().push('\n' as u8) 96 } 97 } 98 99 let mut buf = Vec::new(); 100 for v in lines { 101 buf.push(LineBuffer::new(v)); 102 } 103 104 Self { 105 buf: RwLock::new(buf), 106 offset: AtomicUsize::new(0), 107 flag_lines: RwLock::new(HashMap::new()), 108 locked_lines: RwLock::new(HashMap::new()), 109 } 110 } 111 112 #[inline] set_offset(&self, mut offset: usize)113 pub fn set_offset(&self, mut offset: usize) { 114 offset = offset.min(self.buf.read().unwrap().len() - 1); 115 self.offset.store(offset, Ordering::SeqCst); 116 } 117 118 #[inline] offset(&self) -> usize119 pub fn offset(&self) -> usize { 120 self.offset.load(Ordering::SeqCst) 121 } 122 line_count(&self) -> usize123 pub fn line_count(&self) -> usize { 124 self.buf.read().unwrap().len() 125 } 126 127 /// 获取一部分上下文 get_content( &self, mut start_y: usize, mut line_count: usize, ) -> Option<Vec<LineBuffer>>128 pub fn get_content( 129 &self, 130 mut start_y: usize, 131 mut line_count: usize, 132 ) -> Option<Vec<LineBuffer>> { 133 start_y += self.offset.load(Ordering::SeqCst); 134 line_count = line_count.min(self.line_count() - start_y); 135 let buf = self.buf.read().unwrap(); 136 if start_y > buf.len() { 137 return None; 138 } 139 let end = buf.len().min(start_y + line_count); 140 141 let mut ret = Vec::with_capacity(end - start_y); 142 ret.resize(end - start_y, LineBuffer::default()); 143 ret[..].clone_from_slice(&buf[start_y..end]); 144 Some(ret) 145 } 146 get_linesize(&self, line: u16) -> u16147 pub fn get_linesize(&self, line: u16) -> u16 { 148 let buf = self.buf.read().unwrap(); 149 let line = buf.get(self.offset.load(Ordering::SeqCst) + line as usize); 150 if line.is_none() { 151 return 0; 152 } 153 154 let line = line.unwrap(); 155 156 line.data.len() as u16 157 } 158 get_linesize_abs(&self, line: u16) -> u16159 pub fn get_linesize_abs(&self, line: u16) -> u16 { 160 let buf = self.buf.read().unwrap(); 161 let line = buf.get(line as usize); 162 if line.is_none() { 163 return 0; 164 } 165 166 let line = line.unwrap(); 167 168 line.data.len() as u16 169 } 170 171 /// 外部接口,本结构体内部方法不应该使用,因为涉及offset计算 remove_char(&self, x: u16, y: u16)172 pub fn remove_char(&self, x: u16, y: u16) { 173 let mut buf = self.buf.write().unwrap(); 174 let line = buf.get_mut(self.offset.load(Ordering::SeqCst) + y as usize); 175 if line.is_none() { 176 return; 177 } 178 179 line.unwrap().remove(x as usize); 180 } 181 remove_str(&self, x: u16, y: u16, n: usize)182 pub fn remove_str(&self, x: u16, y: u16, n: usize) { 183 let mut buf = self.buf.write().unwrap(); 184 let line = buf.get_mut(self.offset.load(Ordering::SeqCst) + y as usize); 185 if line.is_none() { 186 return; 187 } 188 let x = x as usize; 189 line.unwrap().data.drain(x..x + n); 190 } 191 192 /// 获取一份对应行的拷贝 get_line(&self, line: u16) -> LineBuffer193 pub fn get_line(&self, line: u16) -> LineBuffer { 194 let buf = self.buf.read().unwrap(); 195 let line = buf.get(self.offset.load(Ordering::SeqCst) + line as usize); 196 if line.is_none() { 197 LineBuffer::default() 198 } else { 199 line.unwrap().clone() 200 } 201 } 202 203 /// 向缓冲区插入一行数据 insert_line(&self, idx: usize, element: &LineBuffer)204 pub fn insert_line(&self, idx: usize, element: &LineBuffer) { 205 let mut buf = self.buf.write().unwrap(); 206 buf.insert(idx, element.clone()); 207 } 208 209 /// 将某行数据与上一行合并 210 /// 返回合并是否成功,以及被合并行之前的长度 merge_line(&self, line: u16) -> (bool, usize)211 pub fn merge_line(&self, line: u16) -> (bool, usize) { 212 let line = self.offset.load(Ordering::SeqCst) + line as usize; 213 if line == 0 { 214 // 没有上一行 215 return (false, 0); 216 } 217 218 let mut buf = self.buf.write().unwrap(); 219 let cur_line = buf.get(line as usize).unwrap().clone(); 220 221 let previous_line = buf.get_mut(line - 1).unwrap(); 222 223 if previous_line.flags.contains(LineState::LOCKED) 224 || cur_line.flags.contains(LineState::LOCKED) 225 { 226 APP_INFO.lock().unwrap().info = "Row is locked".to_string(); 227 return (false, 0); 228 } 229 230 let p_len = previous_line.size(); 231 // 移除最后的\n 232 previous_line.remove(p_len - 1); 233 previous_line.extend(cur_line); 234 235 buf.remove(line as usize); 236 237 return (true, p_len - 1); 238 } 239 240 /// 屏幕坐标 241 #[inline] insert_char(&self, ch: u8, x: u16, y: u16)242 pub fn insert_char(&self, ch: u8, x: u16, y: u16) { 243 let mut buf = self.buf.write().unwrap(); 244 let line = buf.get_mut(self.offset() + y as usize); 245 match line { 246 Some(line) => line.insert(x as usize, ch), 247 None => { 248 let newline = vec!['\n' as u8]; 249 buf.push(LineBuffer::new(newline)); 250 } 251 } 252 } 253 254 #[inline] all_buffer(&self) -> Vec<LineBuffer>255 pub fn all_buffer(&self) -> Vec<LineBuffer> { 256 self.buf.read().unwrap().clone() 257 } 258 259 /// 输入enter时buf的更新操作 input_enter(&self, x: u16, y: u16)260 pub fn input_enter(&self, x: u16, y: u16) { 261 let y = self.offset.load(Ordering::SeqCst) + y as usize; 262 263 let mut buf = self.buf.write().unwrap(); 264 let linesize = buf.get(y).unwrap().size(); 265 if x as usize == linesize { 266 buf.insert(y, LineBuffer::new(vec!['\n' as u8])); 267 } 268 269 let oldline = buf.get_mut(y).unwrap(); 270 let mut newline = Vec::new(); 271 newline.extend_from_slice(&oldline.data[x as usize..]); 272 273 oldline.data.resize(x as usize, 0); 274 oldline.data.push('\n' as u8); 275 276 buf.insert(y + 1, LineBuffer::new(newline)); 277 } 278 add_line_flags(&self, line_index: usize, flags: LineState)279 pub fn add_line_flags(&self, line_index: usize, flags: LineState) { 280 let mut buf = self.buf.write().unwrap(); 281 282 let line = buf.get_mut(line_index); 283 284 if line.is_none() { 285 return; 286 } 287 288 let line = line.unwrap(); 289 290 line.flags.insert(flags); 291 292 let mut flag_map = self.flag_lines.write().unwrap(); 293 if flags.contains(LineState::FLAGED) { 294 flag_map.insert(line.id, line_index); 295 } 296 297 let mut locked_map = self.locked_lines.write().unwrap(); 298 if flags.contains(LineState::LOCKED) { 299 locked_map.insert(line.id, line_index); 300 } 301 } 302 remove_line_flags(&self, line_index: usize, flags: LineState)303 pub fn remove_line_flags(&self, line_index: usize, flags: LineState) { 304 let mut buf = self.buf.write().unwrap(); 305 306 let line = buf.get_mut(line_index); 307 308 if line.is_none() { 309 return; 310 } 311 312 let line = line.unwrap(); 313 314 line.flags.remove(flags); 315 316 let mut flag_map = self.flag_lines.write().unwrap(); 317 if flags.contains(LineState::FLAGED) { 318 flag_map.remove(&line.id); 319 } 320 321 let mut locked_map = self.locked_lines.write().unwrap(); 322 if flags.contains(LineState::LOCKED) { 323 locked_map.remove(&line.id); 324 } 325 } 326 327 #[inline] line_flags(&self, line: u16) -> LineState328 pub fn line_flags(&self, line: u16) -> LineState { 329 self.get_line(line).flags 330 } 331 332 // 定位到指定行数,返回在正文窗口中的y坐标 goto_line(&self, mut line_idx: usize) -> u16333 pub fn goto_line(&self, mut line_idx: usize) -> u16 { 334 let max_line = self.line_count(); 335 336 if line_idx > max_line - 1 { 337 line_idx = max_line - 1 338 } 339 340 let size = *CONTENT_WINSIZE.read().unwrap(); 341 342 // 先将其坐标定位在正文中央 343 let win_rows = size.rows as usize; 344 let mut y = win_rows / 2; 345 346 if line_idx < y { 347 self.set_offset(0); 348 return line_idx as u16; 349 } 350 351 let mut offset = line_idx - y; 352 353 if offset + win_rows > max_line { 354 // 最底下无数据,则调整 355 let adapt_offset = max_line - win_rows; 356 357 y += offset - adapt_offset; 358 offset = adapt_offset; 359 } 360 361 self.set_offset(offset); 362 363 y as u16 364 } 365 366 /// 删除行,不会删除锁定行,返回删除成功的行数 delete_lines(&self, start: usize, mut end: usize) -> usize367 pub fn delete_lines(&self, start: usize, mut end: usize) -> usize { 368 let max = self.line_count(); 369 if start >= max { 370 return 0; 371 } 372 373 end = end.min(max); 374 let mut index = start; 375 let mut count = 0; 376 let mut buffer = self.buf.write().unwrap(); 377 378 for _ in start..=end { 379 let line = buffer.get(index).unwrap(); 380 if line.flags.contains(LineState::LOCKED) { 381 index += 1; 382 } else { 383 buffer.remove(index); 384 count += 1; 385 } 386 } 387 388 count 389 } 390 delete_line(&self, y: usize)391 pub fn delete_line(&self, y: usize) { 392 let mut buffer = self.buf.write().unwrap(); 393 let line = buffer.get(y); 394 if line.is_none() { 395 return; 396 } 397 let line = line.unwrap(); 398 if line.data.is_empty() { 399 return; 400 } 401 402 if !line.flags.contains(LineState::LOCKED) { 403 buffer.remove(y); 404 } 405 } 406 407 /// 删除 y 行 0..x 的字符 delete_until_line_beg(&self, x: usize, y: usize) -> Option<usize>408 pub fn delete_until_line_beg(&self, x: usize, y: usize) -> Option<usize> { 409 let mut buffer = self.buf.write().unwrap(); 410 let line = buffer.get_mut(y).unwrap(); 411 412 let len = line.data.len(); 413 if len < 2 { 414 return None; 415 } 416 line.data.drain(0..x.min(len - 1)); 417 return Some(x - 1); 418 } 419 420 /// 删除 y 行 x..end 的字符 delete_until_endl(&self, x: usize, y: usize) -> Option<usize>421 pub fn delete_until_endl(&self, x: usize, y: usize) -> Option<usize> { 422 let mut buffer = self.buf.write().unwrap(); 423 let line = buffer.get_mut(y).unwrap(); 424 let len = line.data.len(); 425 if len < 2 { 426 return None; 427 } 428 line.data.drain(x..len - 1); 429 return Some(x); 430 } 431 432 /// 返回下一个单词的起始位置 433 /// 如果为该行最后一单词,返回该行长度 search_nextw_begin(&self, x: u16, y: u16) -> usize434 pub fn search_nextw_begin(&self, x: u16, y: u16) -> usize { 435 let mut left = x as usize; 436 let mut right = left; 437 let linesize = self.get_linesize(y) as usize; 438 let buf = self.buf.read().unwrap(); 439 let line = match buf.get(self.offset.load(Ordering::SeqCst) + y as usize) { 440 Some(line) => line, 441 None => return x as usize, 442 }; 443 444 while left <= right && right < linesize { 445 let lchar = line[left] as char; 446 let rchar = line[right] as char; 447 if rchar.is_ascii_punctuation() && right != x.into() { 448 break; 449 } 450 if !(lchar == ' ' || lchar == '\t') { 451 left += 1; 452 right += 1; 453 continue; 454 } 455 if rchar != ' ' && rchar != '\t' { 456 break; 457 } 458 right += 1; 459 } 460 461 return right; 462 } 463 464 /// 搜索下一个单词的末尾 465 /// 如果为该行最后一单词,返回该行长度 search_nextw_end(&self, x: u16, y: u16) -> usize466 pub fn search_nextw_end(&self, x: u16, y: u16) -> usize { 467 let mut left = x as usize; 468 let mut right = left; 469 let linesize = self.get_linesize(y) as usize; 470 let buf = self.buf.read().unwrap(); 471 let line = match buf.get(self.offset.load(Ordering::SeqCst) + y as usize) { 472 Some(line) => line, 473 None => return x as usize, 474 }; 475 476 while left <= right && right < linesize { 477 let lchar = line[left] as char; 478 let rchar = line[right] as char; 479 if rchar.is_ascii_punctuation() && right != x.into() { 480 break; 481 } 482 if lchar == ' ' || lchar == '\t' { 483 left += 1; 484 right += 1; 485 continue; 486 } 487 if rchar == ' ' || rchar == '\t' { 488 if right == x as usize + 1 { 489 left = right; 490 continue; 491 } 492 right -= 1; 493 break; 494 } 495 right += 1; 496 } 497 498 return right; 499 } 500 501 /// 返回前一单词首字母位置,如果是当前行首单词,返回 None search_prevw_begin(&self, x: u16, y: u16) -> Option<usize>502 pub fn search_prevw_begin(&self, x: u16, y: u16) -> Option<usize> { 503 let mut left = x as i32; 504 let mut right = left; 505 let buf = self.buf.read().unwrap(); 506 let line = match buf.get(self.offset.load(Ordering::SeqCst) + y as usize) { 507 Some(line) => line, 508 None => return Some(x as usize), 509 }; 510 while left <= right && left >= 0 { 511 let lchar = line[left as usize] as char; 512 let rchar = line[right as usize] as char; 513 514 if lchar.is_ascii_punctuation() && left != x.into() { 515 return Some(left as usize); 516 } 517 if rchar == ' ' || rchar == '\t' { 518 left -= 1; 519 right -= 1; 520 continue; 521 } 522 523 if lchar == ' ' || lchar == '\t' { 524 if left + 1 == x.into() { 525 right = left; 526 continue; 527 } 528 return Some(left as usize + 1); 529 } 530 531 left -= 1; 532 } 533 return None; 534 } search_prevw_begin_abs(&self, x: u16, abs_y: u16) -> usize535 pub fn search_prevw_begin_abs(&self, x: u16, abs_y: u16) -> usize { 536 let mut left = x as i32; 537 let mut right = left; 538 let buf = self.buf.read().unwrap(); 539 let line = buf.get(abs_y as usize).unwrap(); 540 while left <= right && left >= 0 { 541 let lchar = line[left as usize] as char; 542 let rchar = line[right as usize] as char; 543 544 if lchar.is_ascii_punctuation() && left != x.into() { 545 return left as usize; 546 } 547 if rchar == ' ' || rchar == '\t' { 548 left -= 1; 549 right -= 1; 550 continue; 551 } 552 553 if lchar == ' ' || lchar == '\t' { 554 if left + 1 == x.into() { 555 right = left; 556 continue; 557 } 558 return left as usize + 1; 559 } 560 561 left -= 1; 562 } 563 return 0; 564 } 565 } 566 567 bitflags! { 568 #[derive(Debug, Default, Clone,Copy)] 569 pub struct LineState: u32 { 570 /// 该行被标记 571 const FLAGED = 1 << 1; 572 /// 锁定该行不能被更改 573 const LOCKED = 1 << 2; 574 } 575 } 576 577 impl LineState { set_style(&self) -> io::Result<()>578 pub fn set_style(&self) -> io::Result<()> { 579 if self.contains(Self::FLAGED) { 580 StyleManager::set_background_color(Color::Cyan)?; 581 } 582 583 if self.contains(Self::LOCKED) { 584 StyleManager::set_background_color(Color::DarkRed)?; 585 } 586 587 Ok(()) 588 } 589 } 590