1 //! An ANSI escape sequence parser module. 2 //! 3 //! **This module is not available with default features. You have to enable `parser` feature 4 //! if you'd like to use it.** 5 //! 6 //! # Parser 7 //! 8 //! The ANSI escape sequence parser parses input data in two steps: 9 //! 10 //! * transforms input data into valid characters, generic csi & escape sequences, throws away invalid data, 11 //! * give them meaning, throws away sequences without known meaning. 12 //! 13 //! ## First step 14 //! 15 //! State machine implementation for the first step is inspired by the 16 //! [A parser for DEC’s ANSI-compatible video terminals](https://vt100.net/emu/dec_ansi_parser) article 17 //! and the [vte](https://crates.io/crates/vte) crate. The goal of this step is to transform an input 18 //! data into characters, generic csi & escape sequences, validate them and throw away malformed input. 19 //! 20 //! An example of valid csi sequence: `b"\x1B[20;10R"`. Output of the first step will be: 21 //! 22 //! * valid csi sequence 23 //! * with two parameters `[20, 10]` 24 //! * and the final character `R`. 25 //! 26 //! ## Second step 27 //! 28 //! An input of this step is output of the first one. We know that the final character `R` represents 29 //! cursor position and two parameters should be provided. They were provided, we can give it a 30 //! meaning and return `Sequence::CursorPosition(10, 20)`. 31 //! 32 //! All sequences without known meaning are discarded. 33 //! 34 //! ## Implementation 35 //! 36 //! Both steps are considered as an implementation detail and there's no plan to make them 37 //! publicly available. 38 //! 39 //! The `parser` module provides the [`Parser`](struct.Parser.html) structure you can feed with 40 //! the [`advance`](struct.Parser.html#method.advance) method. It also implements the standard 41 //! library `Iterator<Item = Sequence>` trait which allows you to consume valid sequences with 42 //! known meaning via the `next()` method. Check the [`Sequence`](enum.Sequence.html) enum to learn 43 //! what this module can parse. 44 use std::collections::VecDeque; 45 46 use engine::{Engine, Provide}; 47 pub use types::{KeyCode, KeyModifiers, Mouse, MouseButton, Sequence}; 48 49 mod engine; 50 mod parsers; 51 pub(crate) mod types; 52 53 /// An ANSI escape sequence parser. 54 /// 55 /// `Parser` implements the `Iterator<Item = Sequence>` trait, thus you can use the 56 /// `next()` method to consume all valid sequences with known meaning. 57 /// 58 /// # Examples 59 /// 60 /// Parse cursor position: 61 /// 62 /// ``` 63 /// use anes::parser::{Parser, Sequence}; 64 /// 65 /// let mut parser = Parser::default(); 66 /// parser.advance(b"\x1B[20;10R", false); 67 /// 68 /// assert_eq!(Some(Sequence::CursorPosition(10, 20)), parser.next()); 69 /// assert!(parser.next().is_none()); 70 /// ``` 71 /// 72 /// Parse keyboard event: 73 /// 74 /// ``` 75 /// use anes::parser::{KeyCode, KeyModifiers, Parser, Sequence}; 76 /// 77 /// let mut parser = Parser::default(); 78 /// parser.advance("a".as_bytes(), false); 79 /// 80 /// assert_eq!(Some(Sequence::Key(KeyCode::Char(''), KeyModifiers::empty())), parser.next()); 81 /// assert_eq!(Some(Sequence::Key(KeyCode::Char('a'), KeyModifiers::empty())), parser.next()); 82 /// assert!(parser.next().is_none()); 83 /// ``` 84 #[derive(Default)] 85 pub struct Parser { 86 engine: Engine, 87 provider: SequenceProvider, 88 } 89 90 impl Parser { 91 /// Advances parser state machine with additional input data. 92 /// 93 /// # Arguments 94 /// 95 /// * `buffer` - input data (stdin in raw mode, etc.) 96 /// * `more` - more input data available right now 97 /// 98 /// It's crucial to provide correct `more` value in order to receive `KeyCode::Esc` events 99 /// as soon as possible. 100 /// 101 /// # Examples 102 /// 103 /// Esc key: 104 /// 105 /// ``` 106 /// use anes::parser::{KeyCode, KeyModifiers, Parser, Sequence}; 107 /// 108 /// let mut parser = Parser::default(); 109 /// // User pressed Esc key & nothing else which means that there's no additional input available 110 /// // aka no possible escape sequence = `KeyCode::Esc` dispatched. 111 /// parser.advance(&[0x1b], false); 112 /// 113 /// assert_eq!(Some(Sequence::Key(KeyCode::Esc, KeyModifiers::empty())), parser.next()); 114 /// assert!(parser.next().is_none()); 115 /// ``` 116 /// 117 /// Possible escape sequence: 118 /// 119 /// ``` 120 /// use anes::parser::{KeyCode, KeyModifiers, Parser, Sequence}; 121 /// 122 /// let mut parser = Parser::default(); 123 /// // User pressed F1 = b"\x1BOP" 124 /// 125 /// // Every escape sequence starts with Esc (0x1b). There's more input available 126 /// // aka possible escape sequence = `KeyCode::Esc` isn't dispatched even when the parser 127 /// // doesn't know rest of the sequence. 128 /// parser.advance(&[0x1b], true); 129 /// assert!(parser.next().is_none()); 130 /// 131 /// // Advance parser with rest of the sequence 132 /// parser.advance(&[b'O', b'P'], false); 133 /// assert_eq!(Some(Sequence::Key(KeyCode::F(1), KeyModifiers::empty())), parser.next()); 134 /// assert!(parser.next().is_none()); 135 /// ``` advance(&mut self, buffer: &[u8], more: bool)136 pub fn advance(&mut self, buffer: &[u8], more: bool) { 137 let len = buffer.len(); 138 for (idx, byte) in buffer.iter().enumerate() { 139 self.engine 140 .advance(&mut self.provider, *byte, idx < len - 1 || more); 141 } 142 } 143 } 144 145 impl Iterator for Parser { 146 type Item = Sequence; 147 next(&mut self) -> Option<Self::Item>148 fn next(&mut self) -> Option<Self::Item> { 149 self.provider.next() 150 } 151 } 152 153 #[derive(Default)] 154 struct SequenceProvider { 155 esc_o: bool, 156 seqs: VecDeque<Sequence>, 157 } 158 159 impl Iterator for SequenceProvider { 160 type Item = Sequence; 161 next(&mut self) -> Option<Self::Item>162 fn next(&mut self) -> Option<Self::Item> { 163 self.seqs.pop_front() 164 } 165 } 166 167 impl Provide for SequenceProvider { provide_char(&mut self, ch: char)168 fn provide_char(&mut self, ch: char) { 169 // eprintln!("dispatch_char: {}", ch); 170 171 if let Some(seq) = parsers::parse_char(ch, self.esc_o) { 172 self.seqs.push_back(seq); 173 } 174 self.esc_o = false; 175 } 176 provide_esc_sequence(&mut self, ch: char)177 fn provide_esc_sequence(&mut self, ch: char) { 178 if ch == 'O' { 179 // Exception 180 // 181 // Esc O - dispatched as an escape sequence followed by single character (P-S) representing 182 // F1-F4 keys. We store Esc O flag only which is then used in the dispatch_char method. 183 self.esc_o = true; 184 } else { 185 self.esc_o = false; 186 if let Some(seq) = parsers::parse_esc_sequence(ch) { 187 self.seqs.push_back(seq); 188 } 189 } 190 } 191 provide_csi_sequence(&mut self, parameters: &[u64], ignored_count: usize, ch: char)192 fn provide_csi_sequence(&mut self, parameters: &[u64], ignored_count: usize, ch: char) { 193 if let Some(seq) = parsers::parse_csi_sequence(parameters, ignored_count, ch) { 194 self.seqs.push_back(seq); 195 } 196 197 self.esc_o = false; 198 } 199 } 200 201 #[cfg(test)] 202 mod tests { 203 use super::Parser; 204 205 #[test] dispatch_char()206 fn dispatch_char() { 207 let mut parser = Parser::default(); 208 parser.advance(&[b'a'], false); 209 assert!(parser.next().is_some()); 210 } 211 212 #[test] dispatch_esc_sequence()213 fn dispatch_esc_sequence() { 214 let mut parser = Parser::default(); 215 parser.advance(&[b'\x1B'], true); 216 assert!(parser.next().is_none()); 217 parser.advance(&[b'a'], false); 218 assert!(parser.next().is_some()); 219 } 220 221 #[test] does_not_dispatch_esc_sequence_with_upper_case_o()222 fn does_not_dispatch_esc_sequence_with_upper_case_o() { 223 let mut parser = Parser::default(); 224 parser.advance(&[b'\x1B'], true); 225 assert!(parser.next().is_none()); 226 parser.advance(&[b'O'], true); 227 assert!(parser.next().is_none()); 228 } 229 230 #[test] dispatch_esc_with_upper_case_o_followed_by_char_as_single_sequence()231 fn dispatch_esc_with_upper_case_o_followed_by_char_as_single_sequence() { 232 let mut parser = Parser::default(); 233 parser.advance(&[b'\x1B'], true); 234 assert!(parser.next().is_none()); 235 parser.advance(&[b'O'], true); 236 assert!(parser.next().is_none()); 237 parser.advance(&[b'P'], false); 238 assert!(parser.next().is_some()); 239 assert!(parser.next().is_none()); 240 } 241 242 #[test] dispatch_csi_sequence()243 fn dispatch_csi_sequence() { 244 let mut parser = Parser::default(); 245 parser.advance(&[b'\x1B'], true); 246 assert!(parser.next().is_none()); 247 parser.advance(&[b'['], true); 248 assert!(parser.next().is_none()); 249 parser.advance(&[b'D'], false); 250 assert!(parser.next().is_some()); 251 } 252 } 253