Browse Source

重构lastline_cmd和cursor部分代码 (#8)

* 重构lastline_cmd部分代码

* 重构部分代码,在TermIO中加入queue操作

* 添加接口insert_line

* 一些调整以及撤销树的初步实现
---------

Co-authored-by: GnoCiYeH <heyicong@dragonos.org>
sparkzky 8 months ago
parent
commit
7d5806d5b2
4 changed files with 175 additions and 118 deletions
  1. 99 82
      src/config/lastline_cmd.rs
  2. 7 0
      src/utils/buffer.rs
  3. 44 35
      src/utils/cursor.rs
  4. 25 1
      src/utils/file.rs

+ 99 - 82
src/config/lastline_cmd.rs

@@ -40,6 +40,7 @@ const EDITED_NO_STORE: &'static str = "Changes have not been saved";
 const NOT_FOUNT_CMD: &'static str = "Command Not Fount";
 
 #[derive(Debug)]
+#[allow(unused)]
 pub struct LastLineCommand {
     /// Command
     pub command: String,
@@ -184,20 +185,25 @@ impl LastLineCommand {
     pub fn lock(ui: &mut MutexGuard<UiCore>, args: &str) -> WarpUiCallBackType {
         let args = args.split(|x| Self::is_split_char(x)).collect::<Vec<_>>();
 
-        if args.len() == 0 {
-            ui.buffer
-                .add_line_flags(ui.cursor.cmd_y() as usize - 1, LineState::LOCKED);
-        }
-
-        for s in args {
-            let line = usize::from_str_radix(s, 10);
-            if line.is_err() {
-                APP_INFO.lock().unwrap().info = format!("\"{s}\" is not a number");
-                return WarpUiCallBackType::None;
+        match args.len() {
+            0 => {
+                //没有参数,锁定当前行
+                ui.buffer
+                    .add_line_flags(ui.cursor.cmd_y() as usize - 1, LineState::LOCKED)
+            }
+            _ => {
+                //有参数,锁定指定行
+                for arg in args {
+                    let line = usize::from_str_radix(arg, 10);
+                    if line.is_err() {
+                        APP_INFO.lock().unwrap().info = format!("\"{arg}\" is not a number");
+                        return WarpUiCallBackType::None;
+                    }
+
+                    let line = line.unwrap();
+                    ui.buffer.add_line_flags(line - 1, LineState::LOCKED);
+                }
             }
-
-            let line = line.unwrap();
-            ui.buffer.add_line_flags(line - 1, LineState::LOCKED);
         }
 
         WarpUiCallBackType::None
@@ -207,43 +213,53 @@ impl LastLineCommand {
     pub fn unflag(ui: &mut MutexGuard<UiCore>, args: &str) -> WarpUiCallBackType {
         let args = args.split(|x| Self::is_split_char(x)).collect::<Vec<_>>();
 
-        if args.len() == 0 {
-            ui.buffer
-                .remove_line_flags(ui.cursor.cmd_y() as usize - 1, LineState::FLAGED);
-        }
-
-        for s in args {
-            let line = usize::from_str_radix(s, 10);
-            if line.is_err() {
-                APP_INFO.lock().unwrap().info = format!("\"{s}\" is not a number");
-                return WarpUiCallBackType::None;
+        match args.len() {
+            0 => {
+                //没有参数,解除标记当前行
+                ui.buffer
+                    .remove_line_flags(ui.cursor.cmd_y() as usize - 1, LineState::FLAGED)
+            }
+            _ => {
+                //有参数,解除标记指定行
+                for arg in args {
+                    let line = usize::from_str_radix(arg, 10);
+                    if line.is_err() {
+                        APP_INFO.lock().unwrap().info = format!("\"{arg}\" is not a number");
+                        return WarpUiCallBackType::None;
+                    }
+
+                    let line = line.unwrap();
+                    ui.buffer.remove_line_flags(line - 1, LineState::FLAGED);
+                }
             }
-
-            let line = line.unwrap();
-            ui.buffer.remove_line_flags(line - 1, LineState::FLAGED);
         }
 
         WarpUiCallBackType::None
     }
 
-    // 锁定行
+    // 解除锁定行
     pub fn unlock(ui: &mut MutexGuard<UiCore>, args: &str) -> WarpUiCallBackType {
         let args = args.split(|x| Self::is_split_char(x)).collect::<Vec<_>>();
 
-        if args.len() == 0 {
-            ui.buffer
-                .remove_line_flags(ui.cursor.cmd_y() as usize - 1, LineState::LOCKED);
-        }
-
-        for s in args {
-            let line = usize::from_str_radix(s, 10);
-            if line.is_err() {
-                APP_INFO.lock().unwrap().info = format!("\"{s}\" is not a number");
-                return WarpUiCallBackType::None;
+        match args.len() {
+            0 => {
+                //没有参数,解除锁定当前行
+                ui.buffer
+                    .remove_line_flags(ui.cursor.cmd_y() as usize - 1, LineState::LOCKED)
+            }
+            _ => {
+                //有参数,解除锁定指定行
+                for arg in args {
+                    let line = usize::from_str_radix(arg, 10);
+                    if line.is_err() {
+                        APP_INFO.lock().unwrap().info = format!("\"{arg}\" is not a number");
+                        return WarpUiCallBackType::None;
+                    }
+
+                    let line = line.unwrap();
+                    ui.buffer.remove_line_flags(line - 1, LineState::LOCKED);
+                }
             }
-
-            let line = line.unwrap();
-            ui.buffer.remove_line_flags(line - 1, LineState::LOCKED);
         }
 
         WarpUiCallBackType::None
@@ -252,53 +268,54 @@ impl LastLineCommand {
     pub fn delete_lines(ui: &mut MutexGuard<UiCore>, args: &str) -> WarpUiCallBackType {
         let args = args.split(|x| x == '-').collect::<Vec<_>>();
 
-        if args.len() == 0 {
-            // 删除当前行
-            let offset = ui.buffer.offset() + ui.cursor.y() as usize;
-            let count = ui.buffer.delete_lines(offset, offset + 1);
-            if count != 0 {
-                APP_INFO.lock().unwrap().info = format!("Successfully deleted {count} row");
+        match args.len() {
+            0 => {
+                let offset = ui.buffer.offset() + ui.cursor.y() as usize;
+                let count = ui.buffer.delete_lines(offset, offset + 1);
+                if count != 0 {
+                    APP_INFO.lock().unwrap().info = format!("Successfully deleted {count} row");
+                }
+                ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)
+                    .unwrap();
+                return WarpUiCallBackType::None;
             }
-            ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)
-                .unwrap();
-            return WarpUiCallBackType::None;
-        }
-
-        if args.len() == 1 {
-            let line = usize::from_str_radix(args[0], 10);
-            if line.is_err() {
-                APP_INFO.lock().unwrap().info = format!("\"{}\" is not a number", args[0]);
+            1 => {
+                let line = usize::from_str_radix(args[0], 10);
+                if line.is_err() {
+                    APP_INFO.lock().unwrap().info = format!("\"{}\" is not a number", args[0]);
+                    return WarpUiCallBackType::None;
+                }
+
+                let line = line.unwrap();
+
+                let offset = ui.buffer.offset() + line;
+                let count = ui.buffer.delete_lines(offset, offset + 1);
+                if count != 0 {
+                    APP_INFO.lock().unwrap().info = format!("Successfully deleted {count} row");
+                }
+                ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)
+                    .unwrap();
                 return WarpUiCallBackType::None;
             }
-
-            let line = line.unwrap();
-
-            let offset = ui.buffer.offset() + line;
-            let count = ui.buffer.delete_lines(offset, offset + 1);
-            if count != 0 {
-                APP_INFO.lock().unwrap().info = format!("Successfully deleted {count} row");
+            _ => {
+                let start = usize::from_str_radix(args[0], 10);
+                let end = usize::from_str_radix(args[1], 10);
+
+                if start.is_err() || end.is_err() {
+                    APP_INFO.lock().unwrap().info =
+                        "Useage: (dl)|(delete) {start}({'-'}{end})".to_string();
+                    return WarpUiCallBackType::None;
+                }
+
+                let count = ui.buffer.delete_lines(start.unwrap() - 1, end.unwrap() - 1);
+                if count != 0 {
+                    APP_INFO.lock().unwrap().info = format!("Successfully deleted {count} row");
+                }
+
+                ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)
+                    .unwrap();
             }
-            ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)
-                .unwrap();
-            return WarpUiCallBackType::None;
         }
-
-        let start = usize::from_str_radix(args[0], 10);
-        let end = usize::from_str_radix(args[1], 10);
-
-        if start.is_err() || end.is_err() {
-            APP_INFO.lock().unwrap().info = "Useage: (dl)|(delete) {start}({'-'}{end})".to_string();
-            return WarpUiCallBackType::None;
-        }
-
-        let count = ui.buffer.delete_lines(start.unwrap() - 1, end.unwrap() - 1);
-        if count != 0 {
-            APP_INFO.lock().unwrap().info = format!("Successfully deleted {count} row");
-        }
-
-        ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)
-            .unwrap();
-
         return WarpUiCallBackType::None;
     }
 }

+ 7 - 0
src/utils/buffer.rs

@@ -79,6 +79,7 @@ pub struct EditBuffer {
     locked_lines: RwLock<HashMap<usize, usize>>,
 }
 
+#[allow(unused)]
 impl EditBuffer {
     pub fn new(buf: Vec<u8>) -> Self {
         let mut lines = buf
@@ -188,6 +189,12 @@ impl EditBuffer {
         }
     }
 
+    /// 向缓冲区插入一行数据
+    pub fn insert_line(&self, idx: usize, element: &LineBuffer) {
+        let mut buf = self.buf.write().unwrap();
+        buf.insert(idx, element.clone());
+    }
+
     /// 将某行数据与上一行合并
     /// 返回合并是否成功,以及被合并行之前的长度
     pub fn merge_line(&self, line: u16) -> (bool, usize) {

+ 44 - 35
src/utils/cursor.rs

@@ -172,12 +172,22 @@ impl CursorCrtl {
         Ok(())
     }
 
-    pub fn move_to_nextline(&mut self, lines: u16) -> io::Result<()> {
+    pub fn move_to_nextline(&mut self, mut lines: u16) -> io::Result<()> {
         let size = *WINSIZE.read().unwrap();
         if self.y + lines >= size.rows {
             // 向上滚动
-            // todo!()
-            return Ok(());
+            // 保存位置
+            let pos = self.store_tmp_pos();
+            // 计算需要滚动的行数
+            let offset = self.buf.offset();
+            if offset < lines as usize {
+                lines = offset as u16;
+            }
+            // 重新设置偏移位置
+            self.buf.set_offset(offset - lines as usize);
+            //翻页并恢复位置
+            TermManager::scroll_up(lines)?;
+            self.restore_tmp_pos(pos)?;
         }
 
         CursorManager::move_to_nextline(lines)?;
@@ -192,12 +202,23 @@ impl CursorCrtl {
         Ok(())
     }
 
-    pub fn move_to_previous_line(&mut self, lines: u16) -> io::Result<()> {
-        let size = *WINSIZE.read().unwrap();
-
-        if self.y() - lines > size.rows {
+    pub fn move_to_previous_line(&mut self, mut lines: u16) -> io::Result<()> {
+        if self.y() < lines {
             // 溢出,则向下滚动
-            todo!()
+
+            // 保存位置
+            let pos = self.store_tmp_pos();
+            let offset = self.buf.offset();
+            // 计算需要滚动的行数
+            let line_count = self.buf.line_count();
+            if line_count < offset + lines as usize {
+                lines = (line_count - offset) as u16;
+            }
+            // 重新设置偏移位置
+            self.buf.set_offset(offset + lines as usize);
+            //翻页并恢复位置
+            TermManager::scroll_up(lines)?;
+            self.restore_tmp_pos(pos)?;
         }
 
         CursorManager::move_to_previous_line(lines)?;
@@ -243,33 +264,21 @@ impl CursorCrtl {
         Ok(())
     }
 
-    pub fn move_left(&mut self, mut count: u16) -> io::Result<()> {
-        if count > self.x {
-            return self.move_to_columu(0);
-        }
-        if self.prefix_mode {
-            if self.x == self.line_prefix_width - 1 {
-                return Ok(());
-            }
-            if self.x - count < self.line_prefix_width {
-                return self.move_to_columu(0);
-            }
-        }
-        if self.x == 0 {
-            return Ok(());
-        }
-        if count > self.x {
-            count = self.x - self.line_prefix_width
-        }
-        CursorManager::move_left(count)?;
-
-        if count > self.x {
-            self.x = self.line_prefix_width - 1;
-        } else {
-            self.x -= count;
-        }
-
-        Ok(())
+    pub fn move_left(&mut self, count: u16) -> io::Result<()> {
+        let result = match self.x {
+            x if x == 0 => Ok(()),
+            x if x < count => self.move_to_columu(0),
+            x => match self.prefix_mode {
+                true if x == self.line_prefix_width - 1 => Ok(()),
+                true if x - count < self.line_prefix_width => self.move_to_columu(0),
+                _ => {
+                    self.x -= count;
+                    self.move_to_columu(x - count)
+                }
+            },
+        };
+
+        result
     }
 
     pub fn move_right(&mut self, count: u16) -> io::Result<()> {

+ 25 - 1
src/utils/file.rs

@@ -15,7 +15,7 @@ pub struct FileManager {
     is_first_open: bool,
     bak: Option<File>,
 }
-
+#[allow(unused)]
 impl FileManager {
     pub fn new(file_path: String) -> io::Result<Self> {
         let ifo_flag = !PathBuf::from(file_path.clone()).exists();
@@ -86,6 +86,7 @@ impl FileManager {
         if self.bak.is_some() {
             fs::remove_file(format!("{}{}", self.name, BAK_SUFFIX))?;
         }
+        self.is_first_open = false;
 
         Ok(())
     }
@@ -104,4 +105,27 @@ impl FileManager {
         }
         Ok(())
     }
+
+    pub fn get_heldbak(&mut self) -> Option<File> {
+        match self.bak.take() {
+            Some(file) => Some(file),
+            None => None,
+        }
+    }
+
+    pub fn restore(&mut self) -> io::Result<()> {
+        if self.bak.is_some() {
+            let bak_file = self.bak.as_mut().unwrap();
+            bak_file.seek(io::SeekFrom::Start(0)).unwrap();
+
+            let mut buf = Vec::new();
+            bak_file.read_to_end(&mut buf).unwrap();
+
+            self.file.write_all(&buf)?;
+
+            self.file.seek(io::SeekFrom::Start(0))?;
+            bak_file.seek(io::SeekFrom::Start(0))?;
+        }
+        Ok(())
+    }
 }