normal.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. use lazy_static::lazy_static;
  2. use crate::utils::ui::event::KeyEventCallback;
  3. use crate::utils::ui::event::WarpUiCallBackType;
  4. use crate::utils::ui::uicore::UiCore;
  5. use crate::utils::ui::uicore::CONTENT_WINSIZE;
  6. use std::io;
  7. use std::sync::{Mutex, MutexGuard};
  8. use super::common::CommonOp;
  9. use super::mode::ModeType;
  10. use super::state::StateMachine;
  11. use crate::utils::ui::mode::state::StateCallback;
  12. #[derive(Debug)]
  13. #[allow(dead_code)]
  14. pub enum BufOpArg {
  15. Around, // 操作引号内乃至引号的内容
  16. Inside, // 操作引号内的内容
  17. Line, // 操作整行
  18. Word, // 操作单词
  19. WordEnd, // 操作单词的末尾
  20. WordBegin, // 操作单词的开头
  21. Block, // 操作块
  22. }
  23. #[derive(Debug)]
  24. pub struct NormalState {
  25. pub cmdchar: Option<char>,
  26. pub count: Option<usize>,
  27. pub count0: bool,
  28. pub start_pos: Option<(u16, u16)>,
  29. pub end_pos: Option<(u16, u16)>,
  30. pub cmdbuf: Vec<u8>,
  31. pub buf_op_arg: Option<BufOpArg>,
  32. }
  33. impl CommonOp for NormalState {}
  34. lazy_static! {
  35. static ref NORMALSTATE: Mutex<NormalState> = Mutex::new(NormalState {
  36. cmdchar: None, // 命令开头的字符,通常决定了一类功能,如dw,dd系列命令
  37. count: None, // 命令的重复次数,如3j,4k
  38. count0: false, // 是否将0作为命令的一部分,在normal模式下,0是一个独立的命令,也可能是一个数字的一部分
  39. start_pos: None, // 作用区域的起始位置
  40. end_pos: None, // 作用区域的结束位置
  41. cmdbuf: Vec::new(), // 用于存储输入的命令,可以与状态的显示通用?
  42. buf_op_arg: None // 用于指定操作的区域,如daw,diw
  43. });
  44. }
  45. #[derive(Debug)]
  46. pub(crate) struct Normal;
  47. impl Normal {
  48. pub fn new() -> Self {
  49. Self {}
  50. }
  51. }
  52. impl KeyEventCallback for Normal {
  53. fn backspace(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
  54. return Ok(WarpUiCallBackType::None);
  55. }
  56. fn esc(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
  57. return Ok(WarpUiCallBackType::ChangMode(ModeType::Command));
  58. }
  59. fn enter(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
  60. return Ok(WarpUiCallBackType::None);
  61. }
  62. fn tab(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
  63. return Ok(WarpUiCallBackType::None);
  64. }
  65. fn input_data(
  66. &self,
  67. ui: &mut MutexGuard<UiCore>,
  68. data: &[u8],
  69. ) -> io::Result<WarpUiCallBackType> {
  70. let mut normal_state = NORMALSTATE.lock().unwrap();
  71. normal_state.cmdbuf.extend_from_slice(data);
  72. match data {
  73. b"h" => normal_state.on_h_clicked(),
  74. b"j" => normal_state.on_j_clicked(),
  75. b"k" => normal_state.on_k_clicked(),
  76. b"l" => normal_state.on_l_clicked(),
  77. b"i" => normal_state.on_i_clicked(),
  78. b"d" => normal_state.on_d_clicked(),
  79. [b'1'..=b'9'] => normal_state.on_nonzero_clicked(data),
  80. b"0" => normal_state.on_zero_clicked(),
  81. b"w" => normal_state.on_w_clicked(ui),
  82. b"g" => normal_state.on_g_clicked(),
  83. b"G" => normal_state.on_G_clicked(ui),
  84. b"b" => normal_state.on_b_clicked(ui),
  85. b":" => {
  86. if normal_state.cmdchar.is_none() {
  87. ui.cursor.store_pos();
  88. return Ok(WarpUiCallBackType::ChangMode(ModeType::LastLine));
  89. }
  90. }
  91. b"$" => normal_state.on_dollar_clicked(),
  92. b"e" => normal_state.on_e_clicked(ui),
  93. b"f" => normal_state.on_f_clicked(),
  94. b"F" => normal_state.on_F_clicked(),
  95. b"x" => normal_state.on_x_clicked(),
  96. b"o" => normal_state.on_o_clicked(),
  97. b"O" => normal_state.on_O_clicked(),
  98. b"a" => normal_state.on_a_clicked(),
  99. b"A" => normal_state.on_A_clicked(),
  100. b"I" => normal_state.on_I_clicked(),
  101. b"H" => normal_state.on_H_clicked(),
  102. b"M" => normal_state.on_M_clicked(),
  103. _ => {}
  104. }
  105. return normal_state.handle(ui);
  106. }
  107. }
  108. impl KeyEventCallback for NormalState {
  109. fn backspace(&self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
  110. ui.cursor.move_left(1)?;
  111. return Ok(WarpUiCallBackType::None);
  112. }
  113. fn esc(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
  114. return Ok(WarpUiCallBackType::ChangMode(ModeType::Command));
  115. }
  116. fn enter(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
  117. return Ok(WarpUiCallBackType::None);
  118. }
  119. fn tab(&self, _ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
  120. return Ok(WarpUiCallBackType::None);
  121. }
  122. fn input_data(
  123. &self,
  124. _ui: &mut MutexGuard<UiCore>,
  125. _data: &[u8],
  126. ) -> io::Result<WarpUiCallBackType> {
  127. return Ok(WarpUiCallBackType::None);
  128. }
  129. }
  130. impl NormalState {
  131. pub fn exec_0_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  132. ui.cursor.move_to_columu(0)?;
  133. return Ok(StateCallback::Reset);
  134. }
  135. pub fn on_h_clicked(&mut self) {
  136. if self.cmdchar.is_none() {
  137. self.cmdchar = Some('h');
  138. }
  139. }
  140. /// 向左移动数列
  141. pub fn exec_h_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  142. let old_x = ui.cursor.x();
  143. let exec_count = match self.count {
  144. Some(count) => count.min(old_x as usize),
  145. None => {
  146. if old_x == 0 {
  147. 0
  148. } else {
  149. 1
  150. }
  151. } // 如果在第一列,不再向左移动,防止溢出
  152. };
  153. let new_x = old_x - exec_count as u16;
  154. ui.cursor.move_to_columu(new_x)?;
  155. return Ok(StateCallback::Reset);
  156. }
  157. pub fn on_j_clicked(&mut self) {
  158. if self.cmdchar.is_none() {
  159. self.cmdchar = Some('j');
  160. }
  161. }
  162. /// 向下移动数行
  163. pub fn exec_j_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  164. let old_y = ui.cursor.y();
  165. let old_abs_y = old_y + ui.buffer.offset() as u16;
  166. // 限制最大移动行数
  167. let exec_count = match self.count {
  168. Some(count) => count.min(ui.buffer.line_count() - old_abs_y as usize - 1),
  169. None => 1, // goto_line 会自动处理最大值
  170. };
  171. let old_offset = ui.buffer.offset();
  172. let new_y = ui.buffer.goto_line(old_abs_y as usize + exec_count);
  173. let new_linesize = ui.buffer.get_linesize(new_y);
  174. let new_x = if new_linesize < ui.cursor.x() {
  175. // 如果新行的长度小于原来的x坐标,将光标移动到新行的最后一个字符
  176. new_linesize - 1
  177. } else {
  178. ui.cursor.x()
  179. };
  180. ui.cursor.move_to(new_x, new_y)?;
  181. ui.cursor.highlight(Some(old_y))?;
  182. // 如果移动后,buffer的offset发生了变化,需要重新渲染
  183. if ui.buffer.offset() != old_offset {
  184. ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)?;
  185. }
  186. return Ok(StateCallback::Reset);
  187. }
  188. pub fn on_k_clicked(&mut self) {
  189. if self.cmdchar.is_none() {
  190. self.cmdchar = Some('k');
  191. }
  192. }
  193. /// 向上移动数行
  194. pub fn exec_k_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  195. let old_y = ui.cursor.y();
  196. let old_abs_y = old_y + ui.buffer.offset() as u16;
  197. // 限制最大移动行数
  198. let exec_count = match self.count {
  199. Some(count) => count.min(old_y as usize + ui.buffer.offset()),
  200. None => {
  201. if old_abs_y == 0 {
  202. 0
  203. } else {
  204. 1
  205. }
  206. } // 如果在第一行,不再向上移动,防止溢出
  207. };
  208. let to_line = old_abs_y as usize - exec_count;
  209. let old_offset = ui.buffer.offset();
  210. let new_y = ui.buffer.goto_line(to_line);
  211. let new_linesize = ui.buffer.get_linesize(new_y);
  212. let new_x = if new_linesize < ui.cursor.x() {
  213. // 如果新行的长度小于原来的x坐标,将光标移动到新行的最后一个字符
  214. new_linesize - 1
  215. } else {
  216. ui.cursor.x()
  217. };
  218. ui.cursor.move_to(new_x, new_y)?;
  219. ui.cursor.highlight(Some(old_y))?;
  220. // 如果移动后,buffer的offset发生了变化,需要重新渲染
  221. if old_offset != ui.buffer.offset() {
  222. ui.render_content(0, CONTENT_WINSIZE.read().unwrap().rows as usize)?;
  223. }
  224. return Ok(StateCallback::Reset);
  225. }
  226. pub fn on_l_clicked(&mut self) {
  227. if self.cmdchar.is_none() {
  228. self.cmdchar = Some('l');
  229. }
  230. }
  231. /// 向右移动数列
  232. pub fn exec_l_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  233. let old_x = ui.cursor.x();
  234. let linesize = ui.buffer.get_linesize(ui.cursor.y()) as usize;
  235. let max_count = linesize - old_x as usize - 1;
  236. let exec_count = match self.count {
  237. Some(count) => count.min(max_count),
  238. None => {
  239. if old_x == linesize as u16 - 1 {
  240. 0
  241. } else {
  242. 1
  243. }
  244. }
  245. };
  246. let new_x = old_x + exec_count as u16;
  247. ui.cursor.move_to_columu(new_x)?;
  248. return Ok(StateCallback::Reset);
  249. }
  250. pub fn on_i_clicked(&mut self) {
  251. if self.cmdchar.is_none() {
  252. self.cmdchar = Some('i');
  253. }
  254. }
  255. pub fn exec_i_cmd(&mut self, _ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  256. return Ok(StateCallback::Exit(ModeType::Insert));
  257. }
  258. #[allow(non_snake_case)]
  259. pub fn on_I_clicked(&mut self) {
  260. if self.cmdchar.is_none() {
  261. self.cmdchar = Some('I');
  262. }
  263. }
  264. // 切换Insert模式,从行首开始插入字符
  265. #[allow(non_snake_case)]
  266. pub fn exec_I_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  267. ui.cursor.move_to_columu(0)?;
  268. return Ok(StateCallback::Exit(ModeType::Insert));
  269. }
  270. pub fn on_a_clicked(&mut self) {
  271. if self.cmdchar.is_none() {
  272. self.cmdchar = Some('a');
  273. }
  274. }
  275. // 切换Insert模式,从当前位置的下一个字符开始插入
  276. pub fn exec_a_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  277. self.right(ui)?;
  278. return Ok(StateCallback::Exit(ModeType::Insert));
  279. }
  280. #[allow(non_snake_case)]
  281. pub fn on_A_clicked(&mut self) {
  282. if self.cmdchar.is_none() {
  283. self.cmdchar = Some('A');
  284. }
  285. }
  286. // 切换Insert模式,从行尾开始插入字符
  287. #[allow(non_snake_case)]
  288. pub fn exec_A_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  289. let line_end = ui.buffer.get_linesize(ui.cursor.y()) - 1;
  290. ui.cursor.move_to_columu(line_end)?;
  291. return Ok(StateCallback::Exit(ModeType::Insert));
  292. }
  293. pub fn on_o_clicked(&mut self) {
  294. if self.cmdchar.is_none() {
  295. self.cmdchar = Some('o');
  296. }
  297. }
  298. // 切换Insert模式,在当前行的下方插入一个新行开始输入文本
  299. pub fn exec_o_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  300. let linesize = ui.buffer.get_linesize(ui.cursor.y());
  301. ui.cursor.move_to_columu(linesize - 1)?;
  302. ui.buffer.input_enter(ui.cursor.x(), ui.cursor.y());
  303. ui.cursor.move_to_nextline(1)?;
  304. return Ok(StateCallback::Exit(ModeType::Insert));
  305. }
  306. #[allow(non_snake_case)]
  307. pub fn on_O_clicked(&mut self) {
  308. if self.cmdchar.is_none() {
  309. self.cmdchar = Some('O');
  310. }
  311. }
  312. // 切换Insert模式,在当前行的上方插入一个新行开始输入文本
  313. #[allow(non_snake_case)]
  314. pub fn exec_O_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  315. ui.cursor.move_to_columu(0)?;
  316. ui.buffer.input_enter(ui.cursor.x(), ui.cursor.y());
  317. return Ok(StateCallback::Exit(ModeType::Insert));
  318. }
  319. /// 处理输入的非零数字
  320. pub fn on_nonzero_clicked(&mut self, data: &[u8]) {
  321. let count = self.count;
  322. if count.is_none() {
  323. // 如果count为空,将第一个输入的数字作为count
  324. let count = data[0] - b'0';
  325. self.count = Some(count as usize);
  326. } else {
  327. // 如果count不为空,将输入的数字添加到count的末尾
  328. let mut count = count.unwrap();
  329. count = count * 10 + (data[0] - b'0') as usize;
  330. self.count = Some(count);
  331. }
  332. self.count0 = true; // 将后续输入的0作为执行次数的一部分
  333. }
  334. /// 处理输入的0
  335. pub fn on_zero_clicked(&mut self) {
  336. // 如果0是命令的一部分,不再处理
  337. if !self.count0 && self.cmdchar.is_none() {
  338. self.cmdchar = Some('0');
  339. self.count0 = true;
  340. }
  341. let count = self.count;
  342. // 如果输入的是0,且count不为空,将count扩大10倍
  343. if count.is_some() {
  344. let mut count = count.unwrap();
  345. count = count * 10;
  346. self.count = Some(count);
  347. }
  348. }
  349. /// 处理输入的d
  350. pub fn on_d_clicked(&mut self) {
  351. match self.cmdchar {
  352. None => {
  353. // 处理d
  354. self.cmdchar = Some('d');
  355. }
  356. Some('d') => {
  357. // 处理dd
  358. self.buf_op_arg = Some(BufOpArg::Line);
  359. }
  360. _ => {
  361. self.reset();
  362. }
  363. }
  364. }
  365. pub fn exec_d_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  366. let count = match self.count {
  367. Some(count) => count as u16,
  368. None => 1,
  369. };
  370. match self.buf_op_arg {
  371. Some(BufOpArg::Line) => {
  372. // 删除行
  373. self.remove_n_line(ui, count)?;
  374. return Ok(StateCallback::Reset);
  375. }
  376. Some(BufOpArg::Word) => {
  377. // 删除单词
  378. for _ in 0..count {
  379. self.remove_word(ui)?;
  380. }
  381. return Ok(StateCallback::Reset);
  382. }
  383. _ => {
  384. return Ok(StateCallback::None);
  385. }
  386. }
  387. }
  388. pub fn on_w_clicked(&mut self, ui: &mut MutexGuard<UiCore>) {
  389. if self.cmdchar.is_none() {
  390. // 按单词移动
  391. self.cmdchar = Some('w');
  392. let count = match self.count {
  393. Some(count) => count,
  394. None => 1,
  395. };
  396. let mut pos = (ui.cursor.x(), ui.cursor.y() + ui.buffer.offset() as u16);
  397. for _ in 0..count {
  398. pos = self.locate_next_word(ui, pos);
  399. }
  400. self.end_pos = Some(pos);
  401. } else {
  402. // 按单词操作,具体由self.cmdchar决定
  403. self.buf_op_arg = Some(BufOpArg::Word);
  404. }
  405. }
  406. pub fn exec_w_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  407. self.end_pos.map(|pos| {
  408. self.move_to_line(ui, pos.1).unwrap();
  409. ui.cursor.move_to_columu(pos.0).unwrap();
  410. });
  411. return Ok(StateCallback::Reset);
  412. }
  413. fn on_g_clicked(&mut self) {
  414. if self.cmdchar.is_none() {
  415. self.cmdchar = Some('g');
  416. } else {
  417. self.end_pos = Some((0, 0));
  418. }
  419. }
  420. fn exec_g_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  421. let rs = self
  422. .end_pos
  423. .map(|pos| self.move_to_line(ui, pos.1).unwrap());
  424. if let None = rs {
  425. return Ok(StateCallback::None);
  426. }
  427. return Ok(StateCallback::Reset);
  428. }
  429. #[allow(non_snake_case)]
  430. fn on_G_clicked(&mut self, _ui: &mut MutexGuard<UiCore>) {
  431. if self.cmdchar.is_none() {
  432. self.cmdchar = Some('G');
  433. }
  434. }
  435. #[allow(non_snake_case)]
  436. fn exec_G_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  437. let lineidx = match self.count {
  438. Some(count) => count - 1,
  439. None => ui.buffer.line_count() - 1,
  440. };
  441. self.move_to_line(ui, lineidx as u16)?;
  442. return Ok(StateCallback::Reset);
  443. }
  444. fn on_b_clicked(&mut self, ui: &mut MutexGuard<UiCore>) {
  445. if self.cmdchar.is_none() {
  446. self.cmdchar = Some('b');
  447. } else {
  448. self.buf_op_arg = Some(BufOpArg::WordBegin);
  449. }
  450. let count = match self.count {
  451. Some(count) => count,
  452. None => 1,
  453. };
  454. let mut pos = (ui.cursor.x(), ui.cursor.y() + ui.buffer.offset() as u16);
  455. self.start_pos = Some(pos);
  456. for _ in 0..count {
  457. pos = self.locate_prevw_begin(ui, pos.0, pos.1);
  458. }
  459. self.end_pos = Some(pos);
  460. }
  461. fn exec_b_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  462. let end_pos = self.end_pos.unwrap();
  463. self.move_to_line(ui, end_pos.1)?;
  464. ui.cursor.move_to_columu(end_pos.0)?;
  465. return Ok(StateCallback::Reset);
  466. }
  467. fn on_dollar_clicked(&mut self) {
  468. if self.cmdchar.is_none() {
  469. self.cmdchar = Some('$');
  470. }
  471. }
  472. fn exec_dollar_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  473. let line_end = ui.buffer.get_linesize(ui.cursor.y()) as u16 - 1;
  474. ui.cursor.move_to_columu(line_end)?;
  475. return Ok(StateCallback::Reset);
  476. }
  477. fn on_e_clicked(&mut self, ui: &mut MutexGuard<UiCore>) {
  478. if self.cmdchar.is_none() {
  479. self.cmdchar = Some('e');
  480. } else {
  481. self.buf_op_arg = Some(BufOpArg::WordEnd);
  482. }
  483. let count = match self.count {
  484. Some(count) => count,
  485. None => 1,
  486. };
  487. let mut pos = (ui.cursor.x(), ui.cursor.y() + ui.buffer.offset() as u16);
  488. for _ in 0..count {
  489. pos = self.locate_nextw_ending(ui, pos.0, pos.1);
  490. }
  491. self.end_pos = Some(pos);
  492. }
  493. fn exec_e_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  494. let end_pos = self.end_pos;
  495. if end_pos.is_none() {
  496. return Ok(StateCallback::None);
  497. }
  498. let end_pos = end_pos.unwrap();
  499. self.move_to_line(ui, end_pos.1)?;
  500. ui.cursor.move_to_columu(end_pos.0)?;
  501. return Ok(StateCallback::Reset);
  502. }
  503. fn on_f_clicked(&mut self) {
  504. if self.cmdchar.is_none() {
  505. self.cmdchar = Some('f');
  506. }
  507. }
  508. fn exec_f_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  509. if self.cmdbuf.len() < 2 {
  510. return Ok(StateCallback::None);
  511. }
  512. let to_find = self.cmdbuf.last().unwrap().clone() as char;
  513. let old_x = ui.cursor.x();
  514. let old_y = ui.cursor.y();
  515. let line =
  516. String::from_utf8_lossy(&ui.buffer.get_line(old_y)[old_x as usize..]).to_string();
  517. let pos = line.find(to_find);
  518. if pos.is_none() {
  519. return Ok(StateCallback::None);
  520. }
  521. ui.cursor
  522. .move_to_columu((old_x + pos.unwrap() as u16) as u16)?;
  523. return Ok(StateCallback::Reset);
  524. }
  525. #[allow(non_snake_case)]
  526. fn on_F_clicked(&mut self) {
  527. if self.cmdchar.is_none() {
  528. self.cmdchar = Some('F');
  529. }
  530. }
  531. #[allow(non_snake_case)]
  532. fn exec_F_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  533. if self.cmdbuf.len() < 2 {
  534. return Ok(StateCallback::None);
  535. }
  536. let to_find = self.cmdbuf.last().unwrap().clone() as char;
  537. let old_x = ui.cursor.x();
  538. let old_y = ui.cursor.y();
  539. let line =
  540. String::from_utf8_lossy(&ui.buffer.get_line(old_y)[..old_x as usize]).to_string();
  541. let pos = line.rfind(to_find);
  542. if pos.is_none() {
  543. return Ok(StateCallback::None);
  544. }
  545. ui.cursor.move_to_columu(pos.unwrap() as u16)?;
  546. return Ok(StateCallback::Reset);
  547. }
  548. fn on_x_clicked(&mut self) {
  549. if self.cmdchar.is_none() {
  550. self.cmdchar = Some('x');
  551. }
  552. }
  553. fn exec_x_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  554. let y = ui.cursor.y();
  555. let x = ui.cursor.x();
  556. if x < ui.buffer.get_linesize(y) - 1 {
  557. ui.buffer.remove_char(x, y);
  558. ui.render_content(y, 1)?;
  559. }
  560. return Ok(StateCallback::Reset);
  561. }
  562. #[allow(non_snake_case)]
  563. fn on_H_clicked(&mut self) {
  564. if self.cmdchar.is_none() {
  565. self.cmdchar = Some('H');
  566. }
  567. }
  568. #[allow(non_snake_case)]
  569. fn exec_H_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  570. self.move_to_nlines_of_screen(ui, 0)?;
  571. return Ok(StateCallback::Reset);
  572. }
  573. #[allow(non_snake_case)]
  574. fn on_M_clicked(&mut self) {
  575. if self.cmdchar.is_none() {
  576. self.cmdchar = Some('M');
  577. }
  578. }
  579. #[allow(non_snake_case)]
  580. fn exec_M_cmd(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<StateCallback> {
  581. let win_size = CONTENT_WINSIZE.read().unwrap().rows as usize;
  582. self.move_to_nlines_of_screen(ui, win_size / 2)?;
  583. return Ok(StateCallback::Reset);
  584. }
  585. }
  586. impl StateMachine for NormalState {
  587. fn reset(&mut self) {
  588. self.cmdchar = None;
  589. self.count = None;
  590. self.count0 = false;
  591. self.start_pos = None;
  592. self.end_pos = None;
  593. self.cmdbuf.clear();
  594. self.buf_op_arg = None;
  595. }
  596. fn handle(&mut self, ui: &mut MutexGuard<UiCore>) -> io::Result<WarpUiCallBackType> {
  597. if self.cmdchar.is_none() {
  598. return Ok(WarpUiCallBackType::None);
  599. }
  600. let state_callback = match self.cmdchar.unwrap() {
  601. 'h' => self.exec_h_cmd(ui),
  602. 'j' => self.exec_j_cmd(ui),
  603. 'k' => self.exec_k_cmd(ui),
  604. 'l' => self.exec_l_cmd(ui),
  605. 'i' => self.exec_i_cmd(ui),
  606. '0' => self.exec_0_cmd(ui),
  607. 'd' => self.exec_d_cmd(ui),
  608. 'w' => self.exec_w_cmd(ui),
  609. 'g' => self.exec_g_cmd(ui),
  610. 'G' => self.exec_G_cmd(ui),
  611. 'b' => self.exec_b_cmd(ui),
  612. '$' => self.exec_dollar_cmd(ui),
  613. 'e' => self.exec_e_cmd(ui),
  614. 'f' => self.exec_f_cmd(ui),
  615. 'F' => self.exec_F_cmd(ui),
  616. 'x' => self.exec_x_cmd(ui),
  617. 'o' => self.exec_o_cmd(ui),
  618. 'O' => self.exec_O_cmd(ui),
  619. 'a' => self.exec_a_cmd(ui),
  620. 'A' => self.exec_A_cmd(ui),
  621. 'I' => self.exec_I_cmd(ui),
  622. 'H' => self.exec_H_cmd(ui),
  623. 'M' => self.exec_M_cmd(ui),
  624. _ => Ok(StateCallback::None),
  625. };
  626. return match state_callback {
  627. Ok(StateCallback::None) => Ok(WarpUiCallBackType::None),
  628. Ok(StateCallback::Reset) => {
  629. self.reset();
  630. Ok(WarpUiCallBackType::None)
  631. }
  632. Ok(StateCallback::Exit(mode)) => self.exit(WarpUiCallBackType::ChangMode(mode)),
  633. Err(e) => Err(e),
  634. };
  635. }
  636. fn exit(&mut self, callback: WarpUiCallBackType) -> io::Result<WarpUiCallBackType> {
  637. self.reset();
  638. Ok(callback)
  639. }
  640. }