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}