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