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