| 1 | //! `:` commands. |
| 2 | |
| 3 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 4 | pub enum Ex { |
| 5 | Write(Option<String>), |
| 6 | Quit { |
| 7 | force: bool, |
| 8 | }, |
| 9 | WriteQuit, |
| 10 | /// `:x`: write if changed, then quit. |
| 11 | Exit, |
| 12 | QuitAll { |
| 13 | force: bool, |
| 14 | }, |
| 15 | Edit(String), |
| 16 | /// 1-based line number. |
| 17 | Line(usize), |
| 18 | LastLine, |
| 19 | NoHighlight, |
| 20 | Make, |
| 21 | Next, |
| 22 | Prev, |
| 23 | Unknown(String), |
| 24 | } |
| 25 | |
| 26 | pub fn parse(input: &str) -> Ex { |
| 27 | let s = input.trim(); |
| 28 | if let Ok(n) = s.parse::<usize>() { |
| 29 | return Ex::Line(n); |
| 30 | } |
| 31 | if s == "$" { |
| 32 | return Ex::LastLine; |
| 33 | } |
| 34 | let (cmd, arg) = match s.find(char::is_whitespace) { |
| 35 | Some(i) => (&s[..i], s[i..].trim()), |
| 36 | None => (s, ""), |
| 37 | }; |
| 38 | let (cmd, bang) = match cmd.strip_suffix('!') { |
| 39 | Some(c) => (c, true), |
| 40 | None => (cmd, false), |
| 41 | }; |
| 42 | let arg = (!arg.is_empty()).then(|| arg.to_string()); |
| 43 | match cmd { |
| 44 | "w" | "write" => Ex::Write(arg), |
| 45 | "q" | "quit" | "clo" | "close" => Ex::Quit { force: bang }, |
| 46 | "wq" => Ex::WriteQuit, |
| 47 | "x" | "xit" | "exi" | "exit" => Ex::Exit, |
| 48 | "qa" | "qall" | "quita" | "quitall" => Ex::QuitAll { force: bang }, |
| 49 | "e" | "edit" => match arg { |
| 50 | Some(a) => Ex::Edit(a), |
| 51 | None => Ex::Unknown(s.to_string()), |
| 52 | }, |
| 53 | "noh" | "nohl" | "nohlsearch" => Ex::NoHighlight, |
| 54 | "mak" | "make" => Ex::Make, |
| 55 | "bn" | "bnext" | "tabn" | "tabnext" => Ex::Next, |
| 56 | "bp" | "bprevious" | "bN" | "bNext" | "tabp" | "tabprevious" | "tabN" => Ex::Prev, |
| 57 | _ => Ex::Unknown(s.to_string()), |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | #[cfg(test)] |
| 62 | mod tests { |
| 63 | use super::{Ex, parse}; |
| 64 | |
| 65 | #[test] |
| 66 | fn parses_common_commands() { |
| 67 | assert_eq!(parse("w"), Ex::Write(None)); |
| 68 | assert_eq!(parse("w out.asm "), Ex::Write(Some("out.asm".into()))); |
| 69 | assert_eq!(parse("q!"), Ex::Quit { force: true }); |
| 70 | assert_eq!(parse("wq"), Ex::WriteQuit); |
| 71 | assert_eq!(parse("x"), Ex::Exit); |
| 72 | assert_eq!(parse("qa!"), Ex::QuitAll { force: true }); |
| 73 | assert_eq!(parse("42"), Ex::Line(42)); |
| 74 | assert_eq!(parse("$"), Ex::LastLine); |
| 75 | assert_eq!( |
| 76 | parse("e examples/blink.asm"), |
| 77 | Ex::Edit("examples/blink.asm".into()) |
| 78 | ); |
| 79 | assert_eq!(parse("noh"), Ex::NoHighlight); |
| 80 | assert_eq!(parse("make"), Ex::Make); |
| 81 | assert_eq!(parse("bn"), Ex::Next); |
| 82 | assert_eq!(parse("frobnicate"), Ex::Unknown("frobnicate".into())); |
| 83 | } |
| 84 | } |