xref: /Held/src/utils/buffer.rs (revision 984a200e159c143eb730a2df362731fe1a62fe01)
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     /// 获取一份对应行的拷贝
171     pub fn get_line(&self, line: u16) -> LineBuffer {
172         let buf = self.buf.read().unwrap();
173         let line = buf.get(self.offset.load(Ordering::SeqCst) + line as usize);
174         if line.is_none() {
175             LineBuffer::default()
176         } else {
177             line.unwrap().clone()
178         }
179     }
180 
181     /// 将某行数据与上一行合并
182     /// 返回合并是否成功,以及被合并行之前的长度
183     pub fn merge_line(&self, line: u16) -> (bool, usize) {
184         let line = self.offset.load(Ordering::SeqCst) + line as usize;
185         if line == 0 {
186             // 没有上一行
187             return (false, 0);
188         }
189 
190         let mut buf = self.buf.write().unwrap();
191         let cur_line = buf.get(line as usize).unwrap().clone();
192 
193         let previous_line = buf.get_mut(line - 1).unwrap();
194 
195         if previous_line.flags.contains(LineState::LOCKED)
196             || cur_line.flags.contains(LineState::LOCKED)
197         {
198             APP_INFO.lock().unwrap().info = "Row is locked".to_string();
199             return (false, 0);
200         }
201 
202         let p_len = previous_line.size();
203         // 移除最后的\n
204         previous_line.remove(p_len - 1);
205         previous_line.extend(cur_line);
206 
207         buf.remove(line as usize);
208 
209         return (true, p_len - 1);
210     }
211 
212     /// 屏幕坐标
213     #[inline]
214     pub fn insert_char(&self, ch: u8, x: u16, y: u16) {
215         let mut buf = self.buf.write().unwrap();
216         let line = buf.get_mut(self.offset() + y as usize).unwrap();
217         line.insert(x as usize, ch);
218     }
219 
220     #[inline]
221     pub fn all_buffer(&self) -> Vec<LineBuffer> {
222         self.buf.read().unwrap().clone()
223     }
224 
225     /// 输入enter时buf的更新操作
226     pub fn input_enter(&self, x: u16, y: u16) {
227         let y = self.offset.load(Ordering::SeqCst) + y as usize;
228 
229         let mut buf = self.buf.write().unwrap();
230         let linesize = buf.get(y).unwrap().size();
231         if x as usize == linesize {
232             buf.insert(y, LineBuffer::new(vec!['\n' as u8]));
233         }
234 
235         let oldline = buf.get_mut(y).unwrap();
236         let mut newline = Vec::new();
237         newline.extend_from_slice(&oldline.data[x as usize..]);
238 
239         oldline.data.resize(x as usize, 0);
240         oldline.data.push('\n' as u8);
241 
242         buf.insert(y + 1, LineBuffer::new(newline));
243     }
244 
245     pub fn add_line_flags(&self, line_index: usize, flags: LineState) {
246         let mut buf = self.buf.write().unwrap();
247 
248         let line = buf.get_mut(line_index);
249 
250         if line.is_none() {
251             return;
252         }
253 
254         let line = line.unwrap();
255 
256         line.flags.insert(flags);
257 
258         let mut flag_map = self.flag_lines.write().unwrap();
259         if flags.contains(LineState::FLAGED) {
260             flag_map.insert(line.id, line_index);
261         }
262 
263         let mut locked_map = self.locked_lines.write().unwrap();
264         if flags.contains(LineState::LOCKED) {
265             locked_map.insert(line.id, line_index);
266         }
267     }
268 
269     pub fn remove_line_flags(&self, line_index: usize, flags: LineState) {
270         let mut buf = self.buf.write().unwrap();
271 
272         let line = buf.get_mut(line_index);
273 
274         if line.is_none() {
275             return;
276         }
277 
278         let line = line.unwrap();
279 
280         line.flags.remove(flags);
281 
282         let mut flag_map = self.flag_lines.write().unwrap();
283         if flags.contains(LineState::FLAGED) {
284             flag_map.remove(&line.id);
285         }
286 
287         let mut locked_map = self.locked_lines.write().unwrap();
288         if flags.contains(LineState::LOCKED) {
289             locked_map.remove(&line.id);
290         }
291     }
292 
293     #[inline]
294     pub fn line_flags(&self, line: u16) -> LineState {
295         self.get_line(line).flags
296     }
297 
298     // 定位到指定行数,返回在正文窗口中的y坐标
299     pub fn goto_line(&self, mut line_idx: usize) -> u16 {
300         let max_line = self.line_count();
301 
302         if line_idx > max_line - 1 {
303             line_idx = max_line - 1
304         }
305 
306         let size = *CONTENT_WINSIZE.read().unwrap();
307 
308         // 先将其坐标定位在正文中央
309         let win_rows = size.rows as usize;
310         let mut y = win_rows / 2;
311 
312         if line_idx < y {
313             self.set_offset(0);
314             return line_idx as u16;
315         }
316 
317         let mut offset = line_idx - y;
318 
319         if offset + win_rows > max_line {
320             // 最底下无数据,则调整
321             let adapt_offset = max_line - win_rows;
322 
323             y += offset - adapt_offset;
324             offset = adapt_offset;
325         }
326 
327         self.set_offset(offset);
328 
329         y as u16
330     }
331 
332     /// 删除行,不会删除锁定行,返回删除成功的行数
333     pub fn delete_lines(&self, start: usize, mut end: usize) -> usize {
334         let max = self.line_count();
335         if start >= max {
336             return 0;
337         }
338 
339         end = end.min(max);
340         let mut index = start;
341         let mut count = 0;
342         let mut buffer = self.buf.write().unwrap();
343 
344         for _ in start..=end {
345             let line = buffer.get(index).unwrap();
346             if line.flags.contains(LineState::LOCKED) {
347                 index += 1;
348             } else {
349                 buffer.remove(index);
350                 count += 1;
351             }
352         }
353 
354         count
355     }
356 }
357 
358 bitflags! {
359     #[derive(Debug, Default, Clone,Copy)]
360     pub struct LineState: u32 {
361         /// 该行被标记
362         const FLAGED = 1 << 1;
363         /// 锁定该行不能被更改
364         const LOCKED = 1 << 2;
365     }
366 }
367 
368 impl LineState {
369     pub fn set_style(&self) -> io::Result<()> {
370         if self.contains(Self::FLAGED) {
371             StyleManager::set_background_color(Color::Cyan)?;
372         }
373 
374         if self.contains(Self::LOCKED) {
375             StyleManager::set_background_color(Color::DarkRed)?;
376         }
377 
378         Ok(())
379     }
380 }
381