Browse Source

完善render_lexme (#24)

* 完善render_lexme换行和\t

* 解决退出时屏幕没有刷新的问题

---------

Co-authored-by: sparkzky <sparkhhhhhhhhh@outlook.com>
sparkzky 7 months ago
parent
commit
45f1c58525

+ 2 - 1
src/modules/perferences/default.yaml

@@ -1 +1,2 @@
-soft_tabs: true
+soft_tabs: true
+tab_width: 4

+ 3 - 1
src/modules/perferences/mod.rs

@@ -19,6 +19,8 @@ const THEME_KET: &str = "theme";
 const LANGUAGE_KEY: &str = "language";
 const LANGUAGE_SYNTAX_KEY: &str = "syntax";
 const LINE_WRAPPING_KEY: &str = "line_wrapping";
+const SOFT_TAB_KEY: &str = "soft_tab";
+const TAB_WIDTH_KEY: &str = "tab_width";
 
 pub trait Perferences {
     /// 载入
@@ -106,7 +108,7 @@ impl Perferences for DummyPerferences {
     }
 
     fn soft_tab(&self) -> bool {
-        todo!()
+        true
     }
 
     fn theme_path(&self) -> Result<PathBuf> {

+ 5 - 3
src/modules/perferences/yaml.rs

@@ -1,6 +1,8 @@
 use std::path::PathBuf;
 
-use super::{Perferences, APP_INFO, LINE_WRAPPING_KEY, THEME_KET, THEME_PATH};
+use super::{
+    Perferences, APP_INFO, LINE_WRAPPING_KEY, SOFT_TAB_KEY, TAB_WIDTH_KEY, THEME_KET, THEME_PATH,
+};
 use crate::{
     errors::*,
     modules::perferences::{LANGUAGE_KEY, LANGUAGE_SYNTAX_KEY, SYNTAX_PATH},
@@ -28,11 +30,11 @@ impl Perferences for YamlPerferences {
     }
 
     fn tab_width(&self) -> usize {
-        todo!()
+        self.data[TAB_WIDTH_KEY].as_i64().unwrap_or(4) as usize
     }
 
     fn soft_tab(&self) -> bool {
-        todo!()
+        self.data[SOFT_TAB_KEY].as_bool().unwrap_or(true)
     }
 
     fn theme_name(&self) -> Option<String> {

+ 7 - 0
src/util/position.rs

@@ -60,3 +60,10 @@ impl AddAssign<Distance> for Position {
         };
     }
 }
+
+impl From<(usize, usize)> for Position {
+    fn from(tuple: (usize, usize)) -> Self {
+        let (line, offset) = tuple;
+        Position::new(line, offset)
+    }
+}

+ 24 - 4
src/view/render/renderer.rs

@@ -5,7 +5,7 @@ use std::rc::Rc;
 use std::str::FromStr;
 
 use crate::errors::*;
-use crate::modules::perferences::Perferences;
+use crate::modules::perferences::{self, Perferences};
 use crate::util::position::Position;
 use crate::util::range::Range;
 use crate::view::colors::colors::Colors;
@@ -291,11 +291,31 @@ impl<'a, 'p> Renderer<'a, 'p> {
             let (style, color) = self.current_char_style(token_color);
 
             if self.perferences.line_wrapping()
-                && self.screen_position.offset == self.terminal.width().unwrap()
+                && self.screen_position.offset == self.terminal.width().unwrap() - 1
             {
-                todo!()
+                self.render_cell(self.screen_position, style, color, character.to_string());
+                self.buffer_position.offset += 1;
+
+                // 屏幕上换行但是渲染原来的line
+                let prefix_len = self.content_start_of_line;
+                let prefix = " ".repeat(prefix_len);
+                self.screen_position.offset = 0;
+                self.screen_position.line += 1;
+                self.render_cell(
+                    Position {
+                        line: self.screen_position.line,
+                        offset: self.screen_position.offset,
+                    },
+                    style,
+                    Colors::Default,
+                    prefix,
+                );
+                self.screen_position.offset += prefix_len;
             } else if character == "\t" {
-                todo!()
+                let tab_len = self.perferences.tab_width();
+                let width = tab_len - (self.screen_position.offset + 1) % tab_len;
+                let tab_str = " ".repeat(width);
+                self.render_lexeme(tab_str);
             } else {
                 self.render_cell(self.screen_position, style, color, character.to_string());
                 self.screen_position.offset += 1;

+ 19 - 6
src/view/terminal/cross_terminal.rs

@@ -1,17 +1,16 @@
 use std::{
     cell::{RefCell, RefMut},
-    io::{stdout, BufWriter, Write},
+    io::{stdout, Write},
 };
 
 use crossterm::{
-    cursor,
     event::Event,
     terminal::{self, disable_raw_mode},
-    ExecutableCommand, QueueableCommand,
+    QueueableCommand,
 };
 
 use super::{Terminal, MIN_HEIGHT, MIN_WIDTH, TERMINAL_EXECUTE_ERROR};
-use crate::errors::*;
+use crate::{errors::*, util::position::Position};
 
 #[derive(Debug)]
 pub struct CrossTerminal {
@@ -88,10 +87,17 @@ impl Terminal for CrossTerminal {
     }
 
     fn clear(&self) -> Result<()> {
+        self.buffer()
+            .queue(crossterm::style::SetAttribute(
+                crossterm::style::Attribute::Reset,
+            ))
+            .chain_err(|| TERMINAL_EXECUTE_ERROR)
+            .map(|_| ())?;
         self.buffer()
             .queue(terminal::Clear(terminal::ClearType::All))
             .chain_err(|| TERMINAL_EXECUTE_ERROR)
-            .map(|_| ())
+            .map(|_| ())?;
+        Ok(())
     }
 
     fn present(&self) -> Result<()> {
@@ -152,7 +158,14 @@ impl Terminal for CrossTerminal {
         Ok(())
     }
 
-    fn suspend(&self) {}
+    fn suspend(&self) {
+        let _ = self.clear();
+        let _ = self.set_cursor(Some(Position::from((0, 0))));
+        let _ = stdout().write_all(&self.buffer());
+        let _ = stdout().flush();
+
+        self.buffer().clear();
+    }
 }
 
 impl Drop for CrossTerminal {

+ 1 - 0
src/view/terminal/mod.rs

@@ -13,6 +13,7 @@ pub(super) const MIN_HEIGHT: u16 = 10;
 
 pub const TERMINAL_EXECUTE_ERROR: &'static str = "Terminal IO Error";
 
+#[allow(dead_code)]
 pub trait Terminal: Send + Sync + Debug {
     fn listen(&self) -> Result<Event>;
     fn clear(&self) -> Result<()>;