[go: up one dir, main page]

anes/
parser.rs

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.
44use std::collections::VecDeque;
45
46use engine::{Engine, Provide};
47pub use types::{KeyCode, KeyModifiers, Mouse, MouseButton, Sequence};
48
49mod engine;
50mod parsers;
51pub(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)]
85pub struct Parser {
86    engine: Engine,
87    provider: SequenceProvider,
88}
89
90impl 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    /// ```
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
145impl Iterator for Parser {
146    type Item = Sequence;
147
148    fn next(&mut self) -> Option<Self::Item> {
149        self.provider.next()
150    }
151}
152
153#[derive(Default)]
154struct SequenceProvider {
155    esc_o: bool,
156    seqs: VecDeque<Sequence>,
157}
158
159impl Iterator for SequenceProvider {
160    type Item = Sequence;
161
162    fn next(&mut self) -> Option<Self::Item> {
163        self.seqs.pop_front()
164    }
165}
166
167impl Provide for SequenceProvider {
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
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
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)]
202mod tests {
203    use super::Parser;
204
205    #[test]
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]
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]
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]
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]
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}