xref: /NovaShell/src/shell/printer.rs (revision cb835e03e4e256c633660e88ed6ed9d7b342ae0d)
1 use std::{
2     cell::RefCell,
3     fmt,
4     io::{self, stdout, Write},
5     ops::Deref,
6     print,
7     rc::Rc,
8 };
9 
10 use colored::Colorize;
11 
12 use crate::env::EnvManager;
13 
14 pub struct Printer {
15     /// 提示语
16     pub prompt: Prompt,
17     /// 缓存区,记录当前显示的内容
18     pub buf: Rc<RefCell<Vec<u8>>>,
19     /// 光标位置(不包括提示语)
20     pub cursor: usize,
21 }
22 
23 impl Printer {
24     pub fn new(bytes: &Rc<RefCell<Vec<u8>>>) -> Self {
25         Printer {
26             prompt: Prompt {
27                 computer_name: "DragonOS".to_string(),
28                 user_name: "root".to_string(),
29                 path: EnvManager::current_dir(),
30             },
31             buf: Rc::clone(bytes),
32             cursor: 0,
33         }
34     }
35 
36     /// 读取输入前初始化信息
37     pub fn init_before_readline(&mut self) {
38         self.buf = Rc::new(RefCell::new(Vec::new()));
39         self.prompt.update_path();
40         self.print_prompt();
41         self.cursor = 0;
42     }
43 
44     pub fn print_prompt(&self) {
45         print!("{}", self.prompt);
46         stdout().flush().unwrap();
47     }
48 
49     /// 在光标处插入字符串
50     pub fn insert(&mut self, bytes: &[u8]) {
51         // 记录光标距离末尾的长度,用于后续光标复位
52         let len_to_end = self.buf.deref().borrow().len() - self.cursor;
53 
54         // 在buf中插入内容
55         let mut buf = self.buf.deref().borrow_mut();
56         buf.splice(self.cursor..self.cursor, bytes.iter().cloned());
57 
58         // 打印cursor后面的内容,此时屏幕光标在末尾
59         print!(
60             "{}",
61             String::from_utf8(buf[self.cursor..].to_vec()).unwrap()
62         );
63 
64         // 移回光标
65         if len_to_end > 0 {
66             crossterm::execute!(
67                 io::stdout(),
68                 crossterm::cursor::MoveLeft(len_to_end.try_into().unwrap())
69             )
70             .unwrap();
71         }
72         self.cursor += bytes.len();
73 
74         stdout().flush().unwrap();
75     }
76 
77     /// 删除下标为[cursor,cursor + len)的字符,光标位置不变
78     pub fn delete(&mut self, len: usize) {
79         let cursor = self.cursor;
80         let buf_len = self.buf.deref().borrow().len();
81 
82         // 判断最大下标是否越界
83         if cursor + len - 1 < buf_len {
84             // 在buf中删除内容
85             self.buf.deref().borrow_mut().drain(cursor..cursor + len);
86 
87             // 直接打印删除范围之后的内容
88             print!(
89                 "{}",
90                 String::from_utf8(self.buf.deref().borrow()[self.cursor..].to_vec()).unwrap()
91             );
92 
93             // 打印len个空格覆盖遗留的内容,此时屏幕光标下标恰好为原buf长度
94             print!("{}", " ".repeat(len));
95 
96             // 屏幕光标移回原位
97             crossterm::execute!(
98                 io::stdout(),
99                 crossterm::cursor::MoveLeft((buf_len - cursor).try_into().unwrap())
100             )
101             .unwrap();
102             stdout().flush().unwrap();
103         }
104     }
105 
106     pub fn backspace(&mut self) {
107         if self.cursor > 0 {
108             self.cursor_left(1);
109             self.delete(1);
110         }
111     }
112 
113     pub fn cursor_left(&mut self, len: usize) {
114         if self.cursor > 0 {
115             crossterm::execute!(
116                 io::stdout(),
117                 crossterm::cursor::MoveLeft(len.try_into().unwrap())
118             )
119             .unwrap();
120             self.cursor -= len;
121         }
122     }
123 
124     pub fn cursor_right(&mut self, len: usize) {
125         let buf = self.buf.deref().borrow();
126         if self.cursor < buf.len() {
127             crossterm::execute!(
128                 io::stdout(),
129                 crossterm::cursor::MoveRight(len.try_into().unwrap())
130             )
131             .unwrap();
132             self.cursor += len;
133         }
134     }
135 
136     pub fn home(&mut self) {
137         self.cursor_left(self.cursor);
138     }
139 
140     pub fn end(&mut self) {
141         let buf_len = self.buf.deref().borrow().len();
142         self.cursor_right(buf_len - self.cursor);
143     }
144 
145     /// 将命令行的内容修改为新的内容
146     pub fn change_line(&mut self, new_buf: &Rc<RefCell<Vec<u8>>>) {
147         // 移动到开头
148         self.home();
149 
150         // 打印新的字符串
151         print!(
152             "{}",
153             String::from_utf8(new_buf.deref().borrow()[..].to_vec()).unwrap()
154         );
155 
156         // 如果新字符串长度比旧的短,后面会有残留,用空格覆盖
157         let old_buf_len = self.buf.deref().borrow().len();
158         let new_buf_len = new_buf.deref().borrow().len();
159         if new_buf_len < old_buf_len {
160             let remain_len = old_buf_len - new_buf_len;
161             print!("{}", " ".repeat(remain_len));
162             crossterm::execute!(
163                 io::stdout(),
164                 crossterm::cursor::MoveLeft(remain_len.try_into().unwrap())
165             )
166             .unwrap();
167         }
168 
169         self.cursor = new_buf_len;
170         self.buf = Rc::clone(new_buf);
171         stdout().flush().unwrap();
172     }
173 }
174 
175 pub struct Prompt {
176     user_name: String,
177     computer_name: String,
178     path: String,
179 }
180 
181 impl Prompt {
182     pub fn len(&self) -> usize {
183         format!("{}@{}:{}$ ", self.user_name, self.computer_name, self.path).len()
184     }
185 
186     pub fn update_path(&mut self) {
187         self.path = EnvManager::current_dir()
188     }
189 }
190 
191 impl fmt::Display for Prompt {
192     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193         write!(
194             f,
195             "{}:{}$ ",
196             format!("{}@{}", self.user_name, self.computer_name).bright_green(),
197             self.path.bright_cyan()
198         )
199     }
200 }
201 
202 // 测试终端颜色显示效果
203 #[allow(dead_code)]
204 pub fn _print_color_example() {
205     let example = "abcdefghijklmnopqrstuvwxyz";
206     println!("{}", example.bright_black());
207     println!("{}", example.bright_blue());
208     println!("{}", example.bright_cyan());
209     println!("{}", example.bright_green());
210     println!("{}", example.bright_magenta());
211     println!("{}", example.bright_purple());
212     println!("{}", example.bright_red());
213     println!("{}", example.bright_white());
214     println!("{}", example.bright_yellow());
215     println!("{}", example.black());
216     println!("{}", example.blue());
217     println!("{}", example.cyan());
218     println!("{}", example.green());
219     println!("{}", example.magenta());
220     println!("{}", example.purple());
221     println!("{}", example.red());
222     println!("{}", example.white());
223     println!("{}", example.yellow());
224 }
225