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