xref: /Held/src/utils/buffer.rs (revision fcc6ced0d18453415ce4b88b047a4e8e424fc693)
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