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