summaryrefslogtreecommitdiffstats
path: root/vendor/anes/src/parser.rs
blob: be87b2986eaacf77fef02c234188802f0eae1379 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
//! An ANSI escape sequence parser module.
//!
//! **This module is not available with default features. You have to enable `parser` feature
//! if you'd like to use it.**
//!
//! # Parser
//!
//! The ANSI escape sequence parser parses input data in two steps:
//!
//! * transforms input data into valid characters, generic csi & escape sequences, throws away invalid data,
//! * give them meaning, throws away sequences without known meaning.
//!
//! ## First step
//!
//! State machine implementation for the first step is inspired by the
//! [A parser for DEC’s ANSI-compatible video terminals](https://vt100.net/emu/dec_ansi_parser) article
//! and the [vte](https://crates.io/crates/vte) crate. The goal of this step is to transform an input
//! data into characters, generic csi & escape sequences, validate them and throw away malformed input.
//!
//! An example of valid csi sequence: `b"\x1B[20;10R"`. Output of the first step will be:
//!
//! * valid csi sequence
//! * with two parameters `[20, 10]`
//! * and the final character `R`.
//!
//! ## Second step
//!
//! An input of this step is output of the first one. We know that the final character `R` represents
//! cursor position and two parameters should be provided. They were provided, we can give it a
//! meaning and return `Sequence::CursorPosition(10, 20)`.
//!
//! All sequences without known meaning are discarded.
//!
//! ## Implementation
//!
//! Both steps are considered as an implementation detail and there's no plan to make them
//! publicly available.
//!
//! The `parser` module provides the [`Parser`](struct.Parser.html) structure you can feed with
//! the [`advance`](struct.Parser.html#method.advance) method. It also implements the standard
//! library `Iterator<Item = Sequence>` trait which allows you to consume valid sequences with
//! known meaning via the `next()` method. Check the [`Sequence`](enum.Sequence.html) enum to learn
//! what this module can parse.
use std::collections::VecDeque;

use engine::{Engine, Provide};
pub use types::{KeyCode, KeyModifiers, Mouse, MouseButton, Sequence};

mod engine;
mod parsers;
pub(crate) mod types;

/// An ANSI escape sequence parser.
///
/// `Parser` implements the `Iterator<Item = Sequence>` trait, thus you can use the
/// `next()` method to consume all valid sequences with known meaning.
///
/// # Examples
///
/// Parse cursor position:
///
/// ```
/// use anes::parser::{Parser, Sequence};
///
/// let mut parser = Parser::default();
/// parser.advance(b"\x1B[20;10R", false);
///
/// assert_eq!(Some(Sequence::CursorPosition(10, 20)), parser.next());
/// assert!(parser.next().is_none());
/// ```
///
/// Parse keyboard event:
///
/// ```
/// use anes::parser::{KeyCode, KeyModifiers, Parser, Sequence};
///
/// let mut parser = Parser::default();
/// parser.advance("𐌼a".as_bytes(), false);
///
/// assert_eq!(Some(Sequence::Key(KeyCode::Char('𐌼'), KeyModifiers::empty())), parser.next());
/// assert_eq!(Some(Sequence::Key(KeyCode::Char('a'), KeyModifiers::empty())), parser.next());
/// assert!(parser.next().is_none());
/// ```
#[derive(Default)]
pub struct Parser {
    engine: Engine,
    provider: SequenceProvider,
}

impl Parser {
    /// Advances parser state machine with additional input data.
    ///
    /// # Arguments
    ///
    /// * `buffer` - input data (stdin in raw mode, etc.)
    /// * `more` - more input data available right now
    ///
    /// It's crucial to provide correct `more` value in order to receive `KeyCode::Esc` events
    /// as soon as possible.
    ///
    /// # Examples
    ///
    /// Esc key:
    ///
    /// ```
    /// use anes::parser::{KeyCode, KeyModifiers, Parser, Sequence};
    ///
    /// let mut parser = Parser::default();
    /// // User pressed Esc key & nothing else which means that there's no additional input available
    /// // aka no possible escape sequence = `KeyCode::Esc` dispatched.
    /// parser.advance(&[0x1b], false);
    ///
    /// assert_eq!(Some(Sequence::Key(KeyCode::Esc, KeyModifiers::empty())), parser.next());
    /// assert!(parser.next().is_none());
    /// ```
    ///
    /// Possible escape sequence:
    ///
    /// ```
    /// use anes::parser::{KeyCode, KeyModifiers, Parser, Sequence};
    ///
    /// let mut parser = Parser::default();
    /// // User pressed F1 = b"\x1BOP"
    ///
    /// // Every escape sequence starts with Esc (0x1b). There's more input available
    /// // aka possible escape sequence = `KeyCode::Esc` isn't dispatched even when the parser
    /// // doesn't know rest of the sequence.
    /// parser.advance(&[0x1b], true);
    /// assert!(parser.next().is_none());
    ///
    /// // Advance parser with rest of the sequence
    /// parser.advance(&[b'O', b'P'], false);
    /// assert_eq!(Some(Sequence::Key(KeyCode::F(1), KeyModifiers::empty())), parser.next());
    /// assert!(parser.next().is_none());
    /// ```
    pub fn advance(&mut self, buffer: &[u8], more: bool) {
        let len = buffer.len();
        for (idx, byte) in buffer.iter().enumerate() {
            self.engine
                .advance(&mut self.provider, *byte, idx < len - 1 || more);
        }
    }
}

impl Iterator for Parser {
    type Item = Sequence;

    fn next(&mut self) -> Option<Self::Item> {
        self.provider.next()
    }
}

#[derive(Default)]
struct SequenceProvider {
    esc_o: bool,
    seqs: VecDeque<Sequence>,
}

impl Iterator for SequenceProvider {
    type Item = Sequence;

    fn next(&mut self) -> Option<Self::Item> {
        self.seqs.pop_front()
    }
}

impl Provide for SequenceProvider {
    fn provide_char(&mut self, ch: char) {
        //        eprintln!("dispatch_char: {}", ch);

        if let Some(seq) = parsers::parse_char(ch, self.esc_o) {
            self.seqs.push_back(seq);
        }
        self.esc_o = false;
    }

    fn provide_esc_sequence(&mut self, ch: char) {
        if ch == 'O' {
            // Exception
            //
            // Esc O - dispatched as an escape sequence followed by single character (P-S) representing
            // F1-F4 keys. We store Esc O flag only which is then used in the dispatch_char method.
            self.esc_o = true;
        } else {
            self.esc_o = false;
            if let Some(seq) = parsers::parse_esc_sequence(ch) {
                self.seqs.push_back(seq);
            }
        }
    }

    fn provide_csi_sequence(&mut self, parameters: &[u64], ignored_count: usize, ch: char) {
        if let Some(seq) = parsers::parse_csi_sequence(parameters, ignored_count, ch) {
            self.seqs.push_back(seq);
        }

        self.esc_o = false;
    }
}

#[cfg(test)]
mod tests {
    use super::Parser;

    #[test]
    fn dispatch_char() {
        let mut parser = Parser::default();
        parser.advance(&[b'a'], false);
        assert!(parser.next().is_some());
    }

    #[test]
    fn dispatch_esc_sequence() {
        let mut parser = Parser::default();
        parser.advance(&[b'\x1B'], true);
        assert!(parser.next().is_none());
        parser.advance(&[b'a'], false);
        assert!(parser.next().is_some());
    }

    #[test]
    fn does_not_dispatch_esc_sequence_with_upper_case_o() {
        let mut parser = Parser::default();
        parser.advance(&[b'\x1B'], true);
        assert!(parser.next().is_none());
        parser.advance(&[b'O'], true);
        assert!(parser.next().is_none());
    }

    #[test]
    fn dispatch_esc_with_upper_case_o_followed_by_char_as_single_sequence() {
        let mut parser = Parser::default();
        parser.advance(&[b'\x1B'], true);
        assert!(parser.next().is_none());
        parser.advance(&[b'O'], true);
        assert!(parser.next().is_none());
        parser.advance(&[b'P'], false);
        assert!(parser.next().is_some());
        assert!(parser.next().is_none());
    }

    #[test]
    fn dispatch_csi_sequence() {
        let mut parser = Parser::default();
        parser.advance(&[b'\x1B'], true);
        assert!(parser.next().is_none());
        parser.advance(&[b'['], true);
        assert!(parser.next().is_none());
        parser.advance(&[b'D'], false);
        assert!(parser.next().is_some());
    }
}