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