1 use std::sync::atomic::Ordering; 2 use std::sync::{Mutex, MutexGuard}; 3 use std::{fmt::Debug, io}; 4 5 use crate::config::lastline_cmd::LastLineCommand; 6 use crate::utils::buffer::LineState; 7 #[cfg(feature = "dragonos")] 8 use crate::utils::input::KeyEventType; 9 10 use crate::utils::terminal::TermManager; 11 12 use crate::utils::ui::uicore::{UiCore, APP_INFO, TAB_SIZE}; 13 use crate::utils::ui::{ 14 event::KeyEventCallback, 15 uicore::{CONTENT_WINSIZE, DEF_STYLE}, 16 }; 17 18 use crate::utils::ui::event::WarpUiCallBackType; 19 20 pub trait InputMode: KeyEventCallback + Debug { 21 fn mode_type(&self) -> ModeType; 22 23 #[cfg(not(feature = "dragonos"))] 24 fn event_route( 25 &self, 26 ui: &mut MutexGuard<UiCore>, 27 event: crossterm::event::Event, 28 ) -> io::Result<WarpUiCallBackType> { 29 match event { 30 crossterm::event::Event::FocusGained => todo!(), 31 crossterm::event::Event::FocusLost => todo!(), 32 crossterm::event::Event::Key(key) => self.key_event_route(ui, key), 33 crossterm::event::Event::Mouse(_) => todo!(), 34 crossterm::event::Event::Paste(_) => todo!(), 35 crossterm::event::Event::Resize(_, _) => todo!(), 36 } 37 } 38 39 #[cfg(not(feature = "dragonos"))] 40 fn key_event_route( 41 &self, 42 ui: &mut MutexGuard<UiCore>, 43 keyev: crossterm::event::KeyEvent, 44 ) -> io::Result<WarpUiCallBackType> { 45 let callback = match keyev.code { 46 crossterm::event::KeyCode::Backspace => self.backspace(ui)?, 47 crossterm::event::KeyCode::Enter => self.enter(ui)?, 48 crossterm::event::KeyCode::Left => self.left(ui)?, 49 crossterm::event::KeyCode::Right => self.right(ui)?, 50 crossterm::event::KeyCode::Up => self.up(ui)?, 51 crossterm::event::KeyCode::Down => self.down(ui)?, 52 crossterm::event::KeyCode::Home => todo!(), 53 crossterm::event::KeyCode::End => todo!(), 54 crossterm::event::KeyCode::PageUp => todo!(), 55 crossterm::event::KeyCode::PageDown => todo!(), 56 crossterm::event::KeyCode::Tab => self.tab(ui)?, 57 crossterm::event::KeyCode::BackTab => todo!(), 58 crossterm::event::KeyCode::Delete => todo!(), 59 crossterm::event::KeyCode::Insert => todo!(), 60 crossterm::event::KeyCode::F(_) => todo!(), 61 crossterm::event::KeyCode::Char(c) => self.input_data(ui, &[c as u8])?, 62 crossterm::event::KeyCode::Null => todo!(), 63 crossterm::event::KeyCode::Esc => self.esc(ui)?, 64 crossterm::event::KeyCode::CapsLock => todo!(), 65 crossterm::event::KeyCode::ScrollLock => todo!(), 66 crossterm::event::KeyCode::NumLock => todo!(), 67 crossterm::event::KeyCode::PrintScreen => todo!(), 68 crossterm::event::KeyCode::Pause => todo!(), 69 crossterm::event::KeyCode::Menu => todo!(), 70 crossterm::event::KeyCode::KeypadBegin => todo!(), 71 crossterm::event::KeyCode::Media(_) => todo!(), 72 crossterm::event::KeyCode::Modifier(_) => todo!(), 73 }; 74 75 Ok(callback) 76 } 77 78 #[cfg(feature = "dragonos")] 79 fn key_event_route( 80 &self, 81 ui: &mut MutexGuard<UiCore>, 82 key: KeyEventType, 83 ) -> io::Result<WarpUiCallBackType> { 84 match key { 85 KeyEventType::Common(c) => self.input_data(ui, &[c]), 86 KeyEventType::Up => self.up(ui), 87 KeyEventType::Down => self.down(ui), 88 KeyEventType::Right => self.right(ui), 89 KeyEventType::Left => self.left(ui), 90 KeyEventType::Enter => self.enter(ui), 91 KeyEventType::Tab => self.tab(ui), 92 KeyEventType::Backspace => self.backspace(ui), 93 KeyEventType::Esc => self.esc(ui), 94 KeyEventType::Unknown(_) => { 95 ui.update_bottom_state_bar()?; 96 Ok(WarpUiCallBackType::None) 97 } 98 } 99 } 100 } 101 102 #[derive(Debug, PartialEq, Clone, Copy)] 103 pub enum ModeType { 104 Command, 105 LastLine, 106 Insert, 107 } 108 109 impl InputMode for Command { 110 fn mode_type(&self) -> ModeType { 111 ModeType::Command 112 } 113 } 114 impl InputMode for LastLine { 115 fn mode_type(&self) -> ModeType { 116 ModeType::LastLine 117 } 118 } 119 impl InputMode for Insert { 120 fn mode_type(&self) -> ModeType { 121 ModeType::Insert 122 } 123 } 124 125 #[derive(Debug)] 126 pub struct Command; 127 128 impl Command { 129 pub fn jump_to_next_flag( 130 &self, 131 ui: &mut MutexGuard<UiCore>, 132 flags: LineState, 133 ) -> io::Result<()> { 134 let offset = ui.buffer.offset(); 135 let y = ui.cursor.y() as usize; 136 137 let start_line_number = offset + y + 1; 138 if start_line_number >= ui.buffer.line_count() { 139 return Ok(()); 140 } 141 142 let content = &ui.buffer.all_buffer()[start_line_number..]; 143 144 // 下一个flaged位置 145 let idx = content.iter().position(|x| x.flags.contains(flags)); 146 147 if idx.is_some() { 148 // y + idx 149 let line_number = start_line_number + idx.unwrap(); 150 let new_y = ui.buffer.goto_line(line_number); 151 ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)?; 152 ui.cursor.move_to_row(new_y)?; 153 ui.cursor.highlight(Some(y as u16))?; 154 } 155 156 Ok(()) 157 } 158 159 pub fn jump_to_previous_flag( 160 &self, 161 ui: &mut MutexGuard<UiCore>, 162 flags: LineState, 163 ) -> io::Result<()> { 164 let offset = ui.buffer.offset(); 165 let y = ui.cursor.y() as usize; 166 if offset == 0 && y == 0 { 167 return Ok(()); 168 } 169 let end_linenumber = offset + y - 1; 170 171 let content = &ui.buffer.all_buffer()[0..end_linenumber]; 172 173 // 下一个flaged位置 174 let idx = content.iter().rposition(|x| x.flags.contains(flags)); 175 176 if idx.is_some() { 177 // y + idx 178 let new_y = ui.buffer.goto_line(idx.unwrap()); 179 ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)?; 180 ui.cursor.move_to_row(new_y)?; 181 ui.cursor.highlight(Some(y as u16))?; 182 } 183 184 Ok(()) 185 } 186 } 187 188 impl KeyEventCallback for Command { 189 fn backspace(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 190 Ok(WarpUiCallBackType::None) 191 } 192 fn enter(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 193 Ok(WarpUiCallBackType::None) 194 } 195 196 fn tab(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 197 Ok(WarpUiCallBackType::None) 198 } 199 200 fn esc(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 201 Ok(WarpUiCallBackType::None) 202 } 203 204 fn input_data( 205 &self, 206 ui: &mut MutexGuard<UiCore>, 207 data: &[u8], 208 ) -> io::Result<WarpUiCallBackType> { 209 match data { 210 b":" => { 211 // 保存位置 212 ui.cursor.store_pos(); 213 return Ok(WarpUiCallBackType::ChangMode(ModeType::LastLine)); 214 } 215 216 b"i" | b"I" => { 217 // 切换Insert模式 218 return Ok(WarpUiCallBackType::ChangMode(ModeType::Insert)); 219 } 220 221 b"l" | b"L" => { 222 // 设置当前行lock 223 let flag = ui.buffer.line_flags(ui.cursor.y()); 224 let offset = ui.buffer.offset(); 225 if flag.contains(LineState::LOCKED) { 226 ui.buffer 227 .remove_line_flags(offset + ui.cursor.y() as usize, LineState::LOCKED); 228 } else { 229 ui.buffer 230 .add_line_flags(offset + ui.cursor.y() as usize, LineState::LOCKED); 231 } 232 let y = ui.cursor.y(); 233 ui.render_content(y, 1)?; 234 return Ok(WarpUiCallBackType::None); 235 } 236 237 b"f" | b"F" => { 238 // 设置当前行flag 239 let flag = ui.buffer.line_flags(ui.cursor.y()); 240 let offset = ui.buffer.offset(); 241 if flag.contains(LineState::FLAGED) { 242 ui.buffer 243 .remove_line_flags(offset + ui.cursor.y() as usize, LineState::FLAGED); 244 } else { 245 ui.buffer 246 .add_line_flags(offset + ui.cursor.y() as usize, LineState::FLAGED); 247 } 248 249 let y = ui.cursor.y(); 250 ui.render_content(y, 1)?; 251 return Ok(WarpUiCallBackType::None); 252 } 253 254 b"q" | b"Q" => { 255 // 跳转到上一个flag行 256 self.jump_to_previous_flag(ui, LineState::FLAGED)?; 257 return Ok(WarpUiCallBackType::None); 258 } 259 260 b"w" | b"W" => { 261 // 跳转到下一个flag行 262 self.jump_to_next_flag(ui, LineState::FLAGED)?; 263 return Ok(WarpUiCallBackType::None); 264 } 265 266 b"a" | b"A" => { 267 self.jump_to_previous_flag(ui, LineState::LOCKED)?; 268 return Ok(WarpUiCallBackType::None); 269 } 270 271 b"s" | b"S" => { 272 self.jump_to_next_flag(ui, LineState::LOCKED)?; 273 return Ok(WarpUiCallBackType::None); 274 } 275 276 _ => { 277 return Ok(WarpUiCallBackType::None); 278 } 279 } 280 } 281 } 282 283 #[derive(Debug)] 284 pub struct Insert; 285 impl KeyEventCallback for Insert { 286 fn enter(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 287 let line_idx = ui.cursor.y(); 288 let col = ui.cursor.x(); 289 290 let line = ui.buffer.get_line(line_idx); 291 if line.flags.contains(LineState::LOCKED) { 292 APP_INFO.lock().unwrap().info = "Row is locked".to_string(); 293 return Ok(WarpUiCallBackType::None); 294 } 295 ui.buffer.input_enter(col, line_idx); 296 297 DEF_STYLE.read().unwrap().set_content_style()?; 298 // 清空改行光标后的内容 299 TermManager::clear_until_new_line()?; 300 301 // 执行渲染后续文本 302 ui.cursor.move_to_nextline(1)?; 303 ui.cursor.clear_current_line()?; 304 305 let ret = ui.render_content( 306 line_idx + 1, 307 (CONTENT_WINSIZE.read().unwrap().rows - line_idx) as usize, 308 )?; 309 310 if ret == 0 { 311 ui.scroll_up(1)?; 312 ui.render_content( 313 line_idx + 1, 314 (CONTENT_WINSIZE.read().unwrap().rows - line_idx) as usize, 315 )?; 316 317 ui.cursor.move_up(1)?; 318 } 319 320 let last = ui.cursor.y() - 1; 321 ui.cursor.highlight(Some(last))?; 322 ui.set_edited(); 323 Ok(WarpUiCallBackType::None) 324 } 325 326 fn tab(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 327 ui.set_edited(); 328 let x = ui.cursor.x(); 329 330 let tab_size = TAB_SIZE.load(Ordering::SeqCst); 331 let space_size = tab_size - (x % tab_size); 332 333 for _ in 0..space_size { 334 ui.buffer 335 .insert_char(' ' as u8, ui.cursor.x(), ui.cursor.y()); 336 } 337 338 let y = ui.cursor.y(); 339 ui.render_content(y, 1)?; 340 341 ui.cursor.move_right(space_size)?; 342 343 Ok(WarpUiCallBackType::None) 344 } 345 346 fn esc(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 347 Ok(WarpUiCallBackType::ChangMode(ModeType::Command)) 348 } 349 350 fn input_data( 351 &self, 352 ui: &mut MutexGuard<UiCore>, 353 data: &[u8], 354 ) -> io::Result<WarpUiCallBackType> { 355 let x = ui.cursor.x(); 356 let y = ui.cursor.y(); 357 358 let line = ui.buffer.get_line(y); 359 if line.flags.contains(LineState::LOCKED) { 360 APP_INFO.lock().unwrap().info = "Row is locked".to_string(); 361 return Ok(WarpUiCallBackType::None); 362 } 363 364 for (idx, ch) in data.iter().enumerate() { 365 ui.buffer.insert_char(*ch, x + idx as u16, y); 366 } 367 368 let line_data = ui.buffer.get_line(y); 369 370 // 考虑长度包含\n,所以要减1 371 ui.cursor.write(String::from_utf8_lossy( 372 &line_data.data[x as usize..(line_data.size() - 1)], 373 ))?; 374 375 ui.cursor.move_to_columu(x + data.len() as u16)?; 376 ui.set_edited(); 377 ui.cursor.highlight(None)?; 378 Ok(WarpUiCallBackType::None) 379 } 380 } 381 382 #[derive(Debug)] 383 pub struct LastLine { 384 buf: Mutex<Vec<u8>>, 385 } 386 387 impl LastLine { 388 pub fn new() -> Self { 389 Self { 390 buf: Mutex::new(vec![':' as u8]), 391 } 392 } 393 394 pub fn reset(&self) { 395 self.buf.lock().unwrap().resize(1, ':' as u8); 396 } 397 } 398 399 impl KeyEventCallback for LastLine { 400 fn enter(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 401 let mut buf = self.buf.lock().unwrap(); 402 let cmd = String::from_utf8_lossy(&buf).to_string(); 403 404 let ret = LastLineCommand::process(ui, cmd); 405 406 ui.cursor.move_to(1, u16::MAX - 1)?; 407 // ui.cursor.move_to_columu(1)?; 408 TermManager::clear_until_new_line()?; 409 ui.cursor.move_to(1, u16::MAX - 1)?; 410 411 buf.resize(1, 0); 412 if ret == WarpUiCallBackType::None { 413 ui.cursor.restore_pos()?; 414 return Ok(WarpUiCallBackType::ChangMode(ModeType::Command)); 415 } 416 417 Ok(ret) 418 } 419 420 fn tab(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 421 Ok(WarpUiCallBackType::None) 422 } 423 424 fn backspace(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 425 if ui.cursor.x() == 1 { 426 return Ok(WarpUiCallBackType::None); 427 } 428 429 self.left(ui)?; 430 self.buf.lock().unwrap().remove(ui.cursor.x() as usize); 431 432 ui.cursor.write(' ')?; 433 self.left(ui)?; 434 435 Ok(WarpUiCallBackType::None) 436 } 437 438 fn up(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 439 Ok(WarpUiCallBackType::None) 440 } 441 442 fn down(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 443 Ok(WarpUiCallBackType::None) 444 } 445 446 fn esc(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> { 447 ui.cursor.restore_pos()?; 448 Ok(WarpUiCallBackType::ChangMode(ModeType::Command)) 449 } 450 451 fn input_data( 452 &self, 453 ui: &mut MutexGuard<UiCore>, 454 data: &[u8], 455 ) -> io::Result<WarpUiCallBackType> { 456 let mut buf = self.buf.lock().unwrap(); 457 458 if ui.cursor.x() == buf.len() as u16 { 459 buf.extend(data); 460 } else { 461 let index = ui.cursor.x() as usize; 462 for (i, &item) in data.iter().enumerate() { 463 buf.insert(index + i, item); 464 } 465 } 466 467 ui.cursor.write(String::from_utf8_lossy(&data))?; 468 469 Ok(WarpUiCallBackType::None) 470 } 471 } 472