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