summaryrefslogtreecommitdiffstats
path: root/vendor/anes/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/anes/src')
-rw-r--r--vendor/anes/src/lib.rs76
-rw-r--r--vendor/anes/src/macros.rs437
-rw-r--r--vendor/anes/src/parser.rs252
-rw-r--r--vendor/anes/src/parser/engine.rs614
-rw-r--r--vendor/anes/src/parser/parsers.rs239
-rw-r--r--vendor/anes/src/parser/types.rs79
-rw-r--r--vendor/anes/src/sequences.rs5
-rw-r--r--vendor/anes/src/sequences/attribute.rs133
-rw-r--r--vendor/anes/src/sequences/buffer.rs145
-rw-r--r--vendor/anes/src/sequences/color.rs189
-rw-r--r--vendor/anes/src/sequences/cursor.rs352
-rw-r--r--vendor/anes/src/sequences/terminal.rs54
12 files changed, 2575 insertions, 0 deletions
diff --git a/vendor/anes/src/lib.rs b/vendor/anes/src/lib.rs
new file mode 100644
index 000000000..99dfc8c08
--- /dev/null
+++ b/vendor/anes/src/lib.rs
@@ -0,0 +1,76 @@
+//! # ANSI Escape Sequences provider & parser
+//!
+//! ## Sequences provider
+//!
+//! The `anes` crate provides ANSI escape sequences you can use to control the terminal
+//! cursor (show, hide, ...), colors (foreground, background), display attributes (bold, ...)
+//! and many others.
+//!
+//! Every sequence implements the standard library [`Display`](https://doc.rust-lang.org/std/fmt/trait.Display.html)
+//! trait. It means that these sequences can be used in macros like
+//! [`format!`](https://doc.rust-lang.org/std/macro.format.html) or
+//! [`write!`](https://doc.rust-lang.org/std/macro.write.html).
+//!
+//! Ask if you need more sequences or use the [`sequence!`](macro.sequence.html) macro to create
+//! your own sequences.
+//!
+//!
+//! ### Terminal Support
+//!
+//! Not all ANSI escape sequences are supported by all terminals. You can use the
+//! [interactive-test](https://github.com/zrzka/anes-rs/tree/master/interactive-test) to test them.
+//!
+//! ### Examples
+//!
+//! Retrieve the sequence as a `String`:
+//!
+//! ```rust
+//! use anes::SaveCursorPosition;
+//!
+//! let string = format!("{}", SaveCursorPosition);
+//! assert_eq!(&string, "\x1B7");
+//! ```
+//!
+//! Execute the sequence on the standard output:
+//!
+//! ```rust
+//! use std::io::{Result, Write};
+//!
+//! use anes::execute;
+//!
+//! fn main() -> Result<()> {
+//! let mut stdout = std::io::stdout();
+//! execute!(&mut stdout, anes::ResetAttributes)
+//! }
+//! ```
+//!
+//! ## Sequences parser
+//!
+//! Parser isn't available with default features. You have to enable `parser` feature if you'd like to use it.
+//! You can learn more about this feature in the [`parser`](parser/index.html) module documentation.
+#![warn(rust_2018_idioms)]
+#![deny(unused_imports, unused_must_use)]
+
+// Keep it first to load all the macros before other modules.
+#[macro_use]
+mod macros;
+
+pub use self::sequences::{
+ attribute::{Attribute, ResetAttributes, SetAttribute},
+ buffer::{
+ ClearBuffer, ClearLine, ScrollBufferDown, ScrollBufferUp, SwitchBufferToAlternate,
+ SwitchBufferToNormal,
+ },
+ color::{Color, SetBackgroundColor, SetForegroundColor},
+ cursor::{
+ DisableCursorBlinking, EnableCursorBlinking, HideCursor, MoveCursorDown, MoveCursorLeft,
+ MoveCursorRight, MoveCursorTo, MoveCursorToColumn, MoveCursorToNextLine,
+ MoveCursorToPreviousLine, MoveCursorUp, ReportCursorPosition, RestoreCursorPosition,
+ SaveCursorPosition, ShowCursor,
+ },
+ terminal::{DisableMouseEvents, EnableMouseEvents, ResizeTextArea},
+};
+
+#[cfg(feature = "parser")]
+pub mod parser;
+mod sequences;
diff --git a/vendor/anes/src/macros.rs b/vendor/anes/src/macros.rs
new file mode 100644
index 000000000..1955214fc
--- /dev/null
+++ b/vendor/anes/src/macros.rs
@@ -0,0 +1,437 @@
+/// Creates a control sequence.
+///
+/// This macro prepends provided sequence with the control sequence introducer `ESC [` (`\x1B[`).
+///
+/// # Examples
+///
+/// ```
+/// use anes::csi;
+///
+/// assert_eq!(csi!("?1049h"), "\x1B[?1049h");
+/// ```
+#[macro_export]
+macro_rules! csi {
+ ($($arg:expr),*) => { concat!("\x1B[", $($arg),*) };
+}
+
+/// Creates an escape sequence.
+///
+/// This macro prepends provided sequence with the `ESC` (`\x1B`) character.
+///
+/// # Examples
+///
+/// ```
+/// use anes::esc;
+///
+/// assert_eq!(esc!("7"), "\x1B7");
+/// ```
+#[macro_export]
+macro_rules! esc {
+ ($($arg:expr),*) => { concat!("\x1B", $($arg),*) };
+}
+
+/// Creates a select graphic rendition sequence.
+///
+/// This macro prepends provided sequence with the `ESC[` (`\x1B[`) character and appends `m` character.
+///
+/// Also known as Set Graphics Rendition on Linux.
+///
+/// # Examples
+///
+/// ```
+/// use anes::sgr;
+///
+/// assert_eq!(sgr!("0"), "\x1B[0m");
+/// ```
+#[macro_export]
+macro_rules! sgr {
+ ($($arg:expr),*) => { concat!("\x1B[", $($arg),* , "m") };
+}
+
+/// Creates an ANSI sequence.
+///
+/// You can use this macro to create your own ANSI sequence. All `anes` sequences are
+/// created with this macro.
+///
+/// # Examples
+///
+/// An unit struct:
+///
+/// ```
+/// use anes::{esc, sequence};
+///
+/// sequence!(
+/// /// Saves the cursor position.
+/// struct SaveCursorPosition => esc!("7")
+/// );
+///
+/// assert_eq!(&format!("{}", SaveCursorPosition), "\x1B7");
+/// ```
+///
+/// An enum:
+///
+/// ```
+/// use anes::{csi, sequence};
+///
+/// sequence!(
+/// /// Clears part of the buffer.
+/// enum ClearBuffer {
+/// /// Clears from the cursor position to end of the screen.
+/// Below => csi!("J"),
+/// /// Clears from the cursor position to beginning of the screen.
+/// Above => csi!("1J"),
+/// /// Clears the entire buffer.
+/// All => csi!("2J"),
+/// /// Clears the entire buffer and all saved lines in the scrollback buffer.
+/// SavedLines => csi!("3J"),
+/// }
+/// );
+///
+/// assert_eq!(&format!("{}", ClearBuffer::Below), "\x1B[J");
+/// assert_eq!(&format!("{}", ClearBuffer::Above), "\x1B[1J");
+/// assert_eq!(&format!("{}", ClearBuffer::All), "\x1B[2J");
+/// assert_eq!(&format!("{}", ClearBuffer::SavedLines), "\x1B[3J");
+/// ```
+///
+/// A struct:
+///
+/// ```
+/// use anes::{csi, sequence};
+///
+/// sequence!(
+/// /// Moves the cursor to the given location (column, row).
+/// ///
+/// /// # Notes
+/// ///
+/// /// Top/left cell is represented as `1, 1`.
+/// struct MoveCursorTo(u16, u16) =>
+/// |this, f| write!(f, csi!("{};{}H"), this.0, this.1)
+/// );
+///
+/// assert_eq!(&format!("{}", MoveCursorTo(10, 5)), "\x1B[10;5H");
+/// ```
+#[macro_export]
+macro_rules! sequence {
+ // Static unit struct
+ (
+ $(#[$meta:meta])*
+ struct $name:ident => $value:expr
+ ) => {
+ $(#[$meta])*
+ #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
+ pub struct $name;
+
+ impl ::std::fmt::Display for $name {
+ fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+ write!(f, $value)
+ }
+ }
+ };
+ // Static enum
+ (
+ $(#[$meta:meta])*
+ enum $name:ident {
+ $(
+ $(#[$variant_meta:meta])*
+ $variant:ident => $variant_value:expr
+ ),*
+ $(,)?
+ }
+ ) => {
+ $(#[$meta])*
+ #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
+ pub enum $name {
+ $(
+ $(#[$variant_meta])*
+ $variant,
+ )*
+ }
+
+ impl ::std::fmt::Display for $name {
+ fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+ write!(f, "{}", match self {
+ $(
+ $name::$variant => $variant_value,
+ )*
+ })
+ }
+ }
+ };
+ // Dynamic struct
+ (
+ $(#[$meta:meta])*
+ struct $type:ident(
+ $($fields:ty),*
+ $(,)?
+ )
+ =>
+ $write:expr
+ ) => {
+ $(#[$meta])*
+ #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
+ pub struct $type($(pub $fields),*);
+
+ impl ::std::fmt::Display for $type {
+ fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+ let write: &dyn Fn(&Self, &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result =
+ &$write;
+ write(self, f)
+ }
+ }
+ };
+}
+
+/// Queues ANSI escape sequence(s).
+///
+/// What does queue mean exactly? All sequences are queued with the
+/// `write!($dst, "{}", $sequence)` macro without calling the
+/// [`flush`](https://doc.rust-lang.org/std/io/trait.Write.html#tymethod.flush) method.
+///
+/// Check the [`execute!`](macro.execute.html) macro if you'd like execute them
+/// immediately (call the `flush` method after all sequences were queued).
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::io::{Result, Write};
+///
+/// use anes::queue;
+///
+/// fn main() -> Result<()> {
+/// let mut stdout = std::io::stdout();
+/// queue!(
+/// &mut stdout,
+/// anes::SaveCursorPosition,
+/// anes::MoveCursorTo(10, 10)
+/// )?;
+///
+/// queue!(&mut stdout, anes::RestoreCursorPosition,)?;
+///
+/// // ANSI sequences are not executed until you flush it!
+/// stdout.flush()
+/// }
+/// ```
+#[macro_export]
+macro_rules! queue {
+ ($dst:expr, $($sequence:expr),* $(,)?) => {{
+ let mut error = None;
+
+ $(
+ if let Err(e) = write!($dst, "{}", $sequence) {
+ error = Some(e);
+ }
+ )*
+
+ if let Some(error) = error {
+ Err(error)
+ } else {
+ Ok(())
+ }
+ }}
+}
+
+/// Executes ANSI escape sequence(s).
+///
+/// What does execute mean exactly? All sequences are queued with the
+/// `write!($dst, "{}", $sequence)` macro and then the
+/// [`flush`](https://doc.rust-lang.org/std/io/trait.Write.html#tymethod.flush) method
+/// is called.
+///
+/// Check the [`queue!`](macro.queue.html) macro if you'd like queue sequences
+/// and execute them later.
+///
+/// ```no_run
+/// use std::io::{Result, Write};
+///
+/// use anes::execute;
+///
+/// fn main() -> Result<()> {
+/// let mut stdout = std::io::stdout();
+/// execute!(
+/// &mut stdout,
+/// anes::SaveCursorPosition,
+/// anes::MoveCursorTo(10, 10),
+/// anes::RestoreCursorPosition
+/// )?;
+/// Ok(())
+/// }
+/// ```
+#[macro_export]
+macro_rules! execute {
+ ($dst:expr, $($sequence:expr),* $(,)?) => {{
+ if let Err(e) = $crate::queue!($dst, $($sequence),*) {
+ Err(e)
+ } else {
+ $dst.flush()
+ }
+ }}
+}
+
+#[cfg(test)]
+macro_rules! test_sequences {
+ (
+ $(
+ $name:ident(
+ $($left:expr => $right:expr),*
+ $(,)?
+ )
+ ),*
+ $(,)?
+ ) => {
+ #[cfg(test)]
+ mod tests {
+ use super::*;
+
+ $(
+ #[test]
+ fn $name() {
+ $(
+ assert_eq!(&format!("{}", $left), $right);
+ )*
+ }
+ )*
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use std::io::{Error, ErrorKind, Write};
+
+ #[test]
+ fn csi() {
+ assert_eq!(csi!("foo"), "\x1B[foo");
+ }
+
+ #[test]
+ fn esc() {
+ assert_eq!(esc!("bar"), "\x1Bbar");
+ }
+
+ #[test]
+ fn sgr() {
+ assert_eq!(sgr!("bar"), "\x1B[barm");
+ }
+
+ #[test]
+ fn static_struct_sequence() {
+ sequence!(
+ struct TestSeq => csi!("foo")
+ );
+
+ assert_eq!(&format!("{}", TestSeq), "\x1B[foo");
+ }
+
+ #[test]
+ fn static_enum_sequence() {
+ sequence!(
+ enum TestSeq {
+ Foo => csi!("foo"),
+ Bar => esc!("bar"),
+ }
+ );
+
+ assert_eq!(&format!("{}", TestSeq::Foo), "\x1B[foo");
+ assert_eq!(&format!("{}", TestSeq::Bar), "\x1Bbar");
+ }
+
+ #[test]
+ fn dynamic_struct_sequence() {
+ sequence!(
+ struct TestSeq(u16) =>
+ |this, f| write!(f, csi!("foo{}bar"), this.0)
+ );
+
+ assert_eq!(&format!("{}", TestSeq(10)), "\x1B[foo10bar");
+ }
+
+ #[test]
+ fn queue_allows_trailing_comma() {
+ let mut writer = Writer::default();
+
+ assert!(queue!(&mut writer, "foo",).is_ok());
+ assert_eq!(&writer.buffer, "foo");
+ }
+
+ #[test]
+ fn queue_writes_single_sequence() {
+ let mut writer = Writer::default();
+
+ assert!(queue!(&mut writer, "foo").is_ok());
+ assert_eq!(&writer.buffer, "foo");
+ }
+
+ #[test]
+ fn queue_writes_multiple_sequences() {
+ let mut writer = Writer::default();
+
+ assert!(queue!(&mut writer, "foo", "bar", "baz").is_ok());
+ assert_eq!(&writer.buffer, "foobarbaz");
+ }
+
+ #[test]
+ fn queue_does_not_flush() {
+ let mut writer = Writer::default();
+
+ assert!(queue!(&mut writer, "foo").is_ok());
+ assert!(!writer.flushed);
+ assert!(writer.flushed_buffer.is_empty());
+ }
+
+ #[test]
+ fn execute_allows_trailing_comma() {
+ let mut writer = Writer::default();
+
+ assert!(execute!(&mut writer, "foo",).is_ok());
+ assert_eq!(&writer.flushed_buffer, "foo");
+ }
+
+ #[test]
+ fn execute_writes_single_sequence() {
+ let mut writer = Writer::default();
+
+ assert!(execute!(&mut writer, "foo").is_ok());
+ assert_eq!(&writer.flushed_buffer, "foo");
+ }
+
+ #[test]
+ fn execute_writes_multiple_sequences() {
+ let mut writer = Writer::default();
+
+ assert!(execute!(&mut writer, "foo", "bar", "baz").is_ok());
+ assert_eq!(&writer.flushed_buffer, "foobarbaz");
+ }
+
+ #[test]
+ fn execute_does_flush() {
+ let mut writer = Writer::default();
+
+ assert!(execute!(&mut writer, "foo").is_ok());
+ assert!(writer.flushed);
+ assert_eq!(&writer.flushed_buffer, "foo");
+ assert!(writer.buffer.is_empty());
+ }
+
+ #[derive(Default)]
+ struct Writer {
+ buffer: String,
+ flushed_buffer: String,
+ flushed: bool,
+ }
+
+ impl Write for Writer {
+ fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
+ let s = std::str::from_utf8(buf).map_err(|_| ErrorKind::InvalidData)?;
+
+ self.buffer.push_str(s);
+ Ok(s.len())
+ }
+
+ fn flush(&mut self) -> Result<(), Error> {
+ self.flushed_buffer = self.buffer.clone();
+ self.buffer = String::new();
+ self.flushed = true;
+ Ok(())
+ }
+ }
+}
diff --git a/vendor/anes/src/parser.rs b/vendor/anes/src/parser.rs
new file mode 100644
index 000000000..be87b2986
--- /dev/null
+++ b/vendor/anes/src/parser.rs
@@ -0,0 +1,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());
+ }
+}
diff --git a/vendor/anes/src/parser/engine.rs b/vendor/anes/src/parser/engine.rs
new file mode 100644
index 000000000..645208d37
--- /dev/null
+++ b/vendor/anes/src/parser/engine.rs
@@ -0,0 +1,614 @@
+//
+// https://vt100.net/emu/dec_ansi_parser
+//
+// The parser is heavily inspired by the vte (https://crates.io/crates/vte) crate.
+// Tried to use this crate, but it doesn't work for opposite way (terminal -> sequence),
+// because there're couple of exceptions we have to handle and it doesn't make much
+// sense to add them to the vte crate. An example is Esc key where we need to know if
+// there's additional input available or not and then the decision is made if the
+// Esc char is dispatched immediately (user hits just Esc key) or if it's an escape/csi/...
+// sequence.
+//
+const MAX_PARAMETERS: usize = 30;
+const DEFAULT_PARAMETER_VALUE: u64 = 0;
+const MAX_UTF8_CODE_POINTS: usize = 4;
+
+/// A parser engine state.
+///
+/// All these variant names come from the
+/// [A parser for DEC’s ANSI-compatible video terminals](https://vt100.net/emu/dec_ansi_parser)
+/// description.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+enum State {
+ /// Initial state.
+ Ground,
+ /// Escape sequence started.
+ ///
+ /// `Esc` received with a flag that there's more data available.
+ Escape,
+ /// Escape sequence and we're collecting intermediates.
+ ///
+ /// # Notes
+ ///
+ /// This implementation doesn't collect intermediates. It just handles the state
+ /// to distinguish between (im)proper sequences.
+ EscapeIntermediate,
+ /// CSI sequence started.
+ ///
+ /// `Esc` followed by the `[` received.
+ CsiEntry,
+ /// CSI sequence should be consumed, but not dispatched.
+ CsiIgnore,
+ /// CSI sequence and we're collecting parameters.
+ CsiParameter,
+ /// CSI sequence and we're collecting intermediates.
+ ///
+ /// # Notes
+ ///
+ /// This implementation doesn't collect intermediates. It just handles the state
+ /// to distinguish between (im)proper sequences.
+ CsiIntermediate,
+ /// Possible UTF-8 sequence and we're collecting UTF-8 code points.
+ Utf8,
+}
+
+pub(crate) trait Provide {
+ fn provide_char(&mut self, ch: char);
+
+ fn provide_esc_sequence(&mut self, ch: char);
+
+ fn provide_csi_sequence(&mut self, parameters: &[u64], ignored_count: usize, ch: char);
+}
+
+pub(crate) struct Engine {
+ parameters: [u64; MAX_PARAMETERS],
+ parameters_count: usize,
+ parameter: u64,
+ ignored_parameters_count: usize,
+ state: State,
+ utf8_points: [u8; MAX_UTF8_CODE_POINTS],
+ utf8_points_count: usize,
+ utf8_points_expected_count: usize,
+}
+
+impl Default for Engine {
+ fn default() -> Self {
+ Engine {
+ parameters: [DEFAULT_PARAMETER_VALUE; MAX_PARAMETERS],
+ parameters_count: 0,
+ parameter: DEFAULT_PARAMETER_VALUE,
+ ignored_parameters_count: 0,
+ state: State::Ground,
+ utf8_points: [0; MAX_UTF8_CODE_POINTS],
+ utf8_points_count: 0,
+ utf8_points_expected_count: 0,
+ }
+ }
+}
+
+impl Engine {
+ fn set_state(&mut self, state: State) {
+ if let State::Ground = state {
+ self.parameters_count = 0;
+ self.parameter = DEFAULT_PARAMETER_VALUE;
+ self.ignored_parameters_count = 0;
+ self.utf8_points_count = 0;
+ self.utf8_points_expected_count = 0;
+ }
+ self.state = state;
+ }
+
+ fn store_parameter(&mut self) {
+ if self.parameters_count < MAX_PARAMETERS {
+ self.parameters[self.parameters_count] = self.parameter;
+ self.parameters_count += 1;
+ } else {
+ self.ignored_parameters_count += 1;
+ }
+ self.parameter = DEFAULT_PARAMETER_VALUE;
+ }
+
+ fn handle_possible_esc(&mut self, provider: &mut dyn Provide, byte: u8, more: bool) -> bool {
+ if byte != 0x1B {
+ return false;
+ }
+
+ match (self.state, more) {
+ // More input means possible Esc sequence, just switch state and wait
+ (State::Ground, true) => self.set_state(State::Escape),
+
+ // No more input means Esc key, dispatch it
+ (State::Ground, false) => provider.provide_char('\x1B'),
+
+ // More input means possible Esc sequence, dispatch the previous Esc char
+ (State::Escape, true) => provider.provide_char('\x1B'),
+
+ // No more input means Esc key, dispatch the previous & current Esc char
+ (State::Escape, false) => {
+ provider.provide_char('\x1B');
+ provider.provide_char('\x1B');
+ self.set_state(State::Ground);
+ }
+
+ // Discard any state
+ // More input means possible Esc sequence
+ (_, true) => self.set_state(State::Escape),
+
+ // Discard any state
+ // No more input means Esc key, dispatch it
+ (_, false) => {
+ provider.provide_char('\x1B');
+ self.set_state(State::Ground);
+ }
+ }
+
+ true
+ }
+
+ fn handle_possible_utf8_code_points(&mut self, provider: &mut dyn Provide, byte: u8) -> bool {
+ if byte & 0b1000_0000 == 0b0000_0000 {
+ provider.provide_char(byte as char);
+ true
+ } else if byte & 0b1110_0000 == 0b1100_0000 {
+ self.utf8_points_count = 1;
+ self.utf8_points[0] = byte;
+ self.utf8_points_expected_count = 2;
+ self.set_state(State::Utf8);
+ true
+ } else if byte & 0b1111_0000 == 0b1110_0000 {
+ self.utf8_points_count = 1;
+ self.utf8_points[0] = byte;
+ self.utf8_points_expected_count = 3;
+ self.set_state(State::Utf8);
+ true
+ } else if byte & 0b1111_1000 == 0b1111_0000 {
+ self.utf8_points_count = 1;
+ self.utf8_points[0] = byte;
+ self.utf8_points_expected_count = 4;
+ self.set_state(State::Utf8);
+ true
+ } else {
+ false
+ }
+ }
+
+ fn advance_ground_state(&mut self, provider: &mut dyn Provide, byte: u8) {
+ if self.handle_possible_utf8_code_points(provider, byte) {
+ return;
+ }
+
+ match byte {
+ 0x1B => unreachable!(),
+
+ // Execute
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => provider.provide_char(byte as char),
+
+ // Print
+ 0x20..=0x7F => provider.provide_char(byte as char),
+
+ _ => {}
+ };
+ }
+
+ fn advance_escape_state(&mut self, provider: &mut dyn Provide, byte: u8) {
+ match byte {
+ 0x1B => unreachable!(),
+
+ // Intermediate bytes to collect
+ 0x20..=0x2F => {
+ self.set_state(State::EscapeIntermediate);
+ }
+
+ // Escape followed by '[' (0x5B)
+ // -> CSI sequence start
+ 0x5B => self.set_state(State::CsiEntry),
+
+ // Escape sequence final character
+ 0x30..=0x4F | 0x51..=0x57 | 0x59 | 0x5A | 0x5C | 0x60..=0x7E => {
+ provider.provide_esc_sequence(byte as char);
+ self.set_state(State::Ground);
+ }
+
+ // Execute
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => provider.provide_char(byte as char),
+
+ // TODO Does it mean we should ignore the whole sequence?
+ // Ignore
+ 0x7F => {}
+
+ // Other bytes are considered as invalid -> cancel whatever we have
+ _ => self.set_state(State::Ground),
+ };
+ }
+
+ fn advance_escape_intermediate_state(&mut self, provider: &mut dyn Provide, byte: u8) {
+ match byte {
+ 0x1B => unreachable!(),
+
+ // Intermediate bytes to collect
+ 0x20..=0x2F => {}
+
+ // Escape followed by '[' (0x5B)
+ // -> CSI sequence start
+ 0x5B => self.set_state(State::CsiEntry),
+
+ // Escape sequence final character
+ 0x30..=0x5A | 0x5C..=0x7E => {
+ provider.provide_esc_sequence(byte as char);
+ self.set_state(State::Ground);
+ }
+
+ // Execute
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => provider.provide_char(byte as char),
+
+ // TODO Does it mean we should ignore the whole sequence?
+ // Ignore
+ 0x7F => {}
+
+ // Other bytes are considered as invalid -> cancel whatever we have
+ _ => self.set_state(State::Ground),
+ };
+ }
+
+ fn advance_csi_entry_state(&mut self, provider: &mut dyn Provide, byte: u8) {
+ match byte {
+ 0x1B => unreachable!(),
+
+ // Semicolon = parameter delimiter
+ 0x3B => {
+ self.store_parameter();
+ self.set_state(State::CsiParameter);
+ }
+
+ // '0' ..= '9' = parameter value
+ 0x30..=0x39 => {
+ self.parameter = (byte as u64) - 0x30;
+ self.set_state(State::CsiParameter);
+ }
+
+ 0x3A => self.set_state(State::CsiIgnore),
+
+ // CSI sequence final character
+ // -> dispatch CSI sequence
+ 0x40..=0x7E => {
+ provider.provide_csi_sequence(
+ &self.parameters[..self.parameters_count],
+ self.ignored_parameters_count,
+ byte as char,
+ );
+
+ self.set_state(State::Ground);
+ }
+
+ // Execute
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => provider.provide_char(byte as char),
+
+ // TODO Does it mean we should ignore the whole sequence?
+ // Ignore
+ 0x7F => {}
+
+ // Collect rest as parameters
+ _ => {
+ self.parameter = byte as u64;
+ self.store_parameter();
+ }
+ };
+ }
+
+ fn advance_csi_ignore_state(&mut self, provider: &mut dyn Provide, byte: u8) {
+ match byte {
+ 0x1B => unreachable!(),
+
+ // Execute
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => provider.provide_char(byte as char),
+
+ // TODO Does it mean we should ignore the whole sequence?
+ // Ignore
+ 0x20..=0x3F | 0x7F => {}
+
+ 0x40..=0x7E => self.set_state(State::Ground),
+
+ // Other bytes are considered as invalid -> cancel whatever we have
+ _ => self.set_state(State::Ground),
+ };
+ }
+
+ fn advance_csi_parameter_state(&mut self, provider: &mut dyn Provide, byte: u8) {
+ match byte {
+ 0x1B => unreachable!(),
+
+ // '0' ..= '9' = parameter value
+ 0x30..=0x39 => {
+ self.parameter = self.parameter.saturating_mul(10);
+ self.parameter = self.parameter.saturating_add((byte as u64) - 0x30);
+ }
+
+ // Semicolon = parameter delimiter
+ 0x3B => self.store_parameter(),
+
+ // CSI sequence final character
+ // -> dispatch CSI sequence
+ 0x40..=0x7E => {
+ self.store_parameter();
+ provider.provide_csi_sequence(
+ &self.parameters[..self.parameters_count],
+ self.ignored_parameters_count,
+ byte as char,
+ );
+
+ self.set_state(State::Ground);
+ }
+
+ // Intermediates to collect
+ 0x20..=0x2F => {
+ self.store_parameter();
+ self.set_state(State::CsiIntermediate);
+ }
+
+ // Ignore
+ 0x3A | 0x3C..=0x3F => self.set_state(State::CsiIgnore),
+
+ // Execute
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => provider.provide_char(byte as char),
+
+ // TODO Does it mean we should ignore the whole sequence?
+ // Ignore
+ 0x7F => {}
+
+ // Other bytes are considered as invalid -> cancel whatever we have
+ _ => self.set_state(State::Ground),
+ };
+ }
+
+ fn advance_csi_intermediate_state(&mut self, provider: &mut dyn Provide, byte: u8) {
+ match byte {
+ 0x1B => unreachable!(),
+
+ // Intermediates to collect
+ 0x20..=0x2F => {}
+
+ // CSI sequence final character
+ // -> dispatch CSI sequence
+ 0x40..=0x7E => {
+ provider.provide_csi_sequence(
+ &self.parameters[..self.parameters_count],
+ self.ignored_parameters_count,
+ byte as char,
+ );
+
+ self.set_state(State::Ground);
+ }
+
+ // Execute
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => provider.provide_char(byte as char),
+
+ // TODO Does it mean we should ignore the whole sequence?
+ // Ignore
+ 0x7F => {}
+
+ // Other bytes are considered as invalid -> cancel whatever we have
+ _ => self.set_state(State::Ground),
+ }
+ }
+
+ fn advance_utf8_state(&mut self, provider: &mut dyn Provide, byte: u8) {
+ if byte & 0b1100_0000 != 0b1000_0000 {
+ self.set_state(State::Ground);
+ return;
+ }
+
+ self.utf8_points[self.utf8_points_count] = byte;
+ self.utf8_points_count += 1;
+
+ if self.utf8_points_count == self.utf8_points_expected_count {
+ if let Some(ch) = std::str::from_utf8(&self.utf8_points[..self.utf8_points_count])
+ .ok()
+ .and_then(|s| s.chars().next())
+ {
+ provider.provide_char(ch);
+ }
+ self.set_state(State::Ground);
+ }
+ }
+
+ pub(crate) fn advance(&mut self, provider: &mut dyn Provide, byte: u8, more: bool) {
+ // eprintln!("advance: {:?} {} {}", self.state, byte, more);
+
+ if self.handle_possible_esc(provider, byte, more) {
+ return;
+ }
+
+ match self.state {
+ State::Ground => self.advance_ground_state(provider, byte),
+ State::Escape => self.advance_escape_state(provider, byte),
+ State::EscapeIntermediate => self.advance_escape_intermediate_state(provider, byte),
+ State::CsiEntry => self.advance_csi_entry_state(provider, byte),
+ State::CsiIgnore => self.advance_csi_ignore_state(provider, byte),
+ State::CsiParameter => self.advance_csi_parameter_state(provider, byte),
+ State::CsiIntermediate => self.advance_csi_intermediate_state(provider, byte),
+ State::Utf8 => self.advance_utf8_state(provider, byte),
+ };
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn esc_char() {
+ let mut engine = Engine::default();
+ let mut provider = CharProvider::default();
+
+ // No more input means that the Esc character should be dispatched immediately
+ engine.advance(&mut provider, 0x1B, false);
+ assert_eq!(provider.chars, &['\x1B']);
+
+ // There's more input so the machine should wait before dispatching Esc character
+ engine.advance(&mut provider, 0x1B, true);
+ assert_eq!(provider.chars, &['\x1B']);
+
+ // Another Esc character, but no more input, machine should dispatch the postponed Esc
+ // character and the new one too.
+ engine.advance(&mut provider, 0x1B, false);
+ assert_eq!(provider.chars, &['\x1B', '\x1B', '\x1B']);
+ }
+
+ #[test]
+ fn esc_without_intermediates() {
+ let mut engine = Engine::default();
+ let mut provider = EscProvider::default();
+
+ let input = b"\x1B0\x1B~";
+ advance(&mut engine, &mut provider, input, false);
+
+ assert_eq!(provider.chars.len(), 2);
+
+ assert_eq!(provider.chars[0], '0');
+
+ assert_eq!(provider.chars[1], '~');
+ }
+
+ #[test]
+ fn csi_without_parameters() {
+ let mut engine = Engine::default();
+ let mut provider = CsiProvider::default();
+
+ let input = b"\x1B\x5Bm";
+ advance(&mut engine, &mut provider, input, false);
+
+ assert_eq!(provider.parameters.len(), 1);
+ assert_eq!(provider.parameters[0], &[]);
+ assert_eq!(provider.chars.len(), 1);
+ assert_eq!(provider.chars[0], 'm');
+ }
+
+ #[test]
+ fn csi_with_two_default_parameters() {
+ let mut engine = Engine::default();
+ let mut provider = CsiProvider::default();
+
+ let input = b"\x1B\x5B;m";
+ advance(&mut engine, &mut provider, input, false);
+
+ assert_eq!(provider.parameters.len(), 1);
+ assert_eq!(
+ provider.parameters[0],
+ &[DEFAULT_PARAMETER_VALUE, DEFAULT_PARAMETER_VALUE]
+ );
+ assert_eq!(provider.chars.len(), 1);
+ assert_eq!(provider.chars[0], 'm');
+ }
+
+ #[test]
+ fn csi_with_trailing_semicolon() {
+ let mut engine = Engine::default();
+ let mut provider = CsiProvider::default();
+
+ let input = b"\x1B\x5B123;m";
+ advance(&mut engine, &mut provider, input, false);
+
+ assert_eq!(provider.parameters.len(), 1);
+ assert_eq!(provider.parameters[0], &[123, DEFAULT_PARAMETER_VALUE]);
+ assert_eq!(provider.chars.len(), 1);
+ assert_eq!(provider.chars[0], 'm');
+ }
+
+ #[test]
+ fn csi_max_parameters() {
+ let mut engine = Engine::default();
+ let mut provider = CsiProvider::default();
+
+ let input = b"\x1B\x5B1;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;30m";
+ advance(&mut engine, &mut provider, input, false);
+
+ assert_eq!(provider.parameters.len(), 1);
+ assert_eq!(provider.parameters[0].len(), MAX_PARAMETERS);
+ assert_eq!(
+ provider.parameters[0],
+ &[
+ 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
+ ]
+ );
+ assert_eq!(provider.chars.len(), 1);
+ assert_eq!(provider.chars[0], 'm');
+ }
+
+ #[test]
+ fn test_parse_utf8_character() {
+ let mut engine = Engine::default();
+ let mut provider = CharProvider::default();
+
+ advance(&mut engine, &mut provider, &['a' as u8], false);
+ assert_eq!(provider.chars.len(), 1);
+ assert_eq!(provider.chars[0], 'a');
+
+ advance(&mut engine, &mut provider, &[0xC3, 0xB1], false);
+ assert_eq!(provider.chars.len(), 2);
+ assert_eq!(provider.chars[1], 'ñ');
+
+ advance(&mut engine, &mut provider, &[0xE2, 0x81, 0xA1], false);
+ assert_eq!(provider.chars.len(), 3);
+ assert_eq!(provider.chars[2], '\u{2061}');
+
+ advance(&mut engine, &mut provider, &[0xF0, 0x90, 0x8C, 0xBC], false);
+ assert_eq!(provider.chars.len(), 4);
+ assert_eq!(provider.chars[3], '𐌼');
+ }
+
+ fn advance(engine: &mut Engine, provider: &mut dyn Provide, bytes: &[u8], more: bool) {
+ let len = bytes.len();
+
+ for (i, byte) in bytes.iter().enumerate() {
+ engine.advance(provider, *byte, i < len - 1 || more);
+ }
+ }
+
+ #[derive(Default)]
+ struct CharProvider {
+ chars: Vec<char>,
+ }
+
+ impl Provide for CharProvider {
+ fn provide_char(&mut self, ch: char) {
+ self.chars.push(ch);
+ }
+
+ fn provide_esc_sequence(&mut self, _ch: char) {}
+
+ fn provide_csi_sequence(&mut self, _parameters: &[u64], _ignored_count: usize, _ch: char) {}
+ }
+
+ #[derive(Default)]
+ struct CsiProvider {
+ parameters: Vec<Vec<u64>>,
+ chars: Vec<char>,
+ }
+
+ impl Provide for CsiProvider {
+ fn provide_char(&mut self, _ch: char) {}
+
+ fn provide_esc_sequence(&mut self, _ch: char) {}
+
+ fn provide_csi_sequence(&mut self, parameters: &[u64], _ignored_count: usize, ch: char) {
+ self.parameters.push(parameters.to_vec());
+ self.chars.push(ch);
+ }
+ }
+
+ #[derive(Default)]
+ struct EscProvider {
+ chars: Vec<char>,
+ }
+
+ impl Provide for EscProvider {
+ fn provide_char(&mut self, _ch: char) {}
+
+ fn provide_esc_sequence(&mut self, ch: char) {
+ self.chars.push(ch);
+ }
+
+ fn provide_csi_sequence(&mut self, _parameters: &[u64], _ignored_count: usize, _ch: char) {}
+ }
+}
diff --git a/vendor/anes/src/parser/parsers.rs b/vendor/anes/src/parser/parsers.rs
new file mode 100644
index 000000000..9bb9acb4f
--- /dev/null
+++ b/vendor/anes/src/parser/parsers.rs
@@ -0,0 +1,239 @@
+use super::types::{KeyCode, KeyModifiers, Mouse, MouseButton, Sequence};
+
+pub(crate) fn parse_char(ch: char, esc_o: bool) -> Option<Sequence> {
+ if esc_o {
+ return match ch {
+ 'P'..='S' => Some(Sequence::Key(
+ KeyCode::F(ch as u8 - b'P' + 1),
+ KeyModifiers::empty(),
+ )),
+ _ => None,
+ };
+ }
+
+ let code = match ch {
+ '\r' | '\n' => KeyCode::Enter,
+ '\t' => KeyCode::Tab,
+ '\x7F' => KeyCode::BackTab,
+ '\x1B' => KeyCode::Esc,
+ '\0' => KeyCode::Null,
+ _ => KeyCode::Char(ch),
+ };
+ Some(Sequence::Key(code, KeyModifiers::empty()))
+}
+
+pub(crate) fn parse_esc_sequence(ch: char) -> Option<Sequence> {
+ // EscO[P-S] is handled in the Performer, see parse_char & esc_o argument
+ // No need to handle other cases here? It's just Alt+$char
+ Some(Sequence::Key(KeyCode::Char(ch), KeyModifiers::ALT))
+}
+
+pub(crate) fn parse_csi_sequence(
+ parameters: &[u64],
+ _ignored_count: usize,
+ ch: char,
+) -> Option<Sequence> {
+ match ch {
+ 'A' => Some(Sequence::Key(
+ KeyCode::Up,
+ parse_csi_arrow_key_modifiers(parameters.first().cloned()),
+ )),
+ 'B' => Some(Sequence::Key(
+ KeyCode::Down,
+ parse_csi_arrow_key_modifiers(parameters.first().cloned()),
+ )),
+ 'C' => Some(Sequence::Key(
+ KeyCode::Right,
+ parse_csi_arrow_key_modifiers(parameters.first().cloned()),
+ )),
+ 'D' => Some(Sequence::Key(
+ KeyCode::Left,
+ parse_csi_arrow_key_modifiers(parameters.first().cloned()),
+ )),
+ 'H' => Some(Sequence::Key(KeyCode::Home, KeyModifiers::empty())),
+ 'F' => Some(Sequence::Key(KeyCode::End, KeyModifiers::empty())),
+ 'Z' => Some(Sequence::Key(KeyCode::BackTab, KeyModifiers::empty())),
+ 'R' => parse_csi_cursor_position(parameters),
+ 'm' => parse_csi_xterm_mouse(parameters, ch),
+ 'M' if parameters.first() == Some(&0x3C) => parse_csi_xterm_mouse(parameters, ch),
+ 'M' => parse_csi_rxvt_mouse(parameters),
+ '~' => parse_csi_tilde_key_code(parameters),
+ _ => None,
+ }
+}
+
+fn parse_csi_arrow_key_modifiers(parameter: Option<u64>) -> KeyModifiers {
+ parse_key_modifiers(parameter.map(|x| x.saturating_sub(48)))
+}
+
+fn parse_key_modifiers(parameter: Option<u64>) -> KeyModifiers {
+ if let Some(parameter) = parameter {
+ match parameter {
+ 2 => KeyModifiers::SHIFT,
+ 3 => KeyModifiers::ALT,
+ 4 => KeyModifiers::SHIFT | KeyModifiers::ALT,
+ 5 => KeyModifiers::CONTROL,
+ 6 => KeyModifiers::SHIFT | KeyModifiers::CONTROL,
+ 7 => KeyModifiers::ALT | KeyModifiers::CONTROL,
+ 8 => KeyModifiers::SHIFT | KeyModifiers::ALT | KeyModifiers::CONTROL,
+ 9 => KeyModifiers::META,
+ 10 => KeyModifiers::META | KeyModifiers::SHIFT,
+ 11 => KeyModifiers::META | KeyModifiers::ALT,
+ 12 => KeyModifiers::META | KeyModifiers::SHIFT | KeyModifiers::ALT,
+ 13 => KeyModifiers::META | KeyModifiers::CONTROL,
+ 14 => KeyModifiers::META | KeyModifiers::SHIFT | KeyModifiers::CONTROL,
+ 15 => KeyModifiers::META | KeyModifiers::ALT | KeyModifiers::CONTROL,
+ 16 => {
+ KeyModifiers::META | KeyModifiers::SHIFT | KeyModifiers::ALT | KeyModifiers::CONTROL
+ }
+ _ => KeyModifiers::empty(),
+ }
+ } else {
+ KeyModifiers::empty()
+ }
+}
+
+fn parse_csi_tilde_key_code(parameters: &[u64]) -> Option<Sequence> {
+ if parameters.is_empty() {
+ return None;
+ }
+
+ let modifiers = parse_key_modifiers(parameters.get(1).cloned());
+
+ let code = match parameters[0] {
+ 1 | 7 => KeyCode::Home,
+ 2 => KeyCode::Insert,
+ 3 => KeyCode::Delete,
+ 4 | 8 => KeyCode::End,
+ 5 => KeyCode::PageUp,
+ 6 => KeyCode::PageDown,
+ p @ 11..=15 => KeyCode::F(p as u8 - 10),
+ p @ 17..=21 => KeyCode::F(p as u8 - 11),
+ p @ 23..=24 => KeyCode::F(p as u8 - 12),
+ _ => return None,
+ };
+
+ Some(Sequence::Key(code, modifiers))
+}
+
+fn parse_csi_cursor_position(parameters: &[u64]) -> Option<Sequence> {
+ // ESC [ Cy ; Cx R
+
+ if parameters.len() < 2 {
+ return None;
+ }
+
+ let y = parameters[0] as u16;
+ let x = parameters[1] as u16;
+
+ Some(Sequence::CursorPosition(x, y))
+}
+
+fn parse_csi_xterm_mouse(parameters: &[u64], ch: char) -> Option<Sequence> {
+ // ESC [ < Cb ; Cx ; Cy (;) (M or m)
+
+ if parameters.len() < 4 {
+ return None;
+ }
+
+ let cb = parameters[1] as u8;
+ let cx = parameters[2] as u16;
+ let cy = parameters[3] as u16;
+
+ let up = match ch {
+ 'm' => true,
+ 'M' => false,
+ _ => return None,
+ };
+
+ let mut modifiers = KeyModifiers::empty();
+
+ if cb & 0b0000_0100 == 0b0000_0100 {
+ modifiers |= KeyModifiers::SHIFT;
+ }
+
+ if cb & 0b0000_1000 == 0b0000_1000 {
+ modifiers |= KeyModifiers::ALT;
+ }
+
+ if cb & 0b0001_0000 == 0b0001_0000 {
+ modifiers |= KeyModifiers::CONTROL;
+ }
+
+ let mouse = if cb & 0b0100_0000 == 0b0100_0000 {
+ if cb & 0b0000_0001 == 0b0000_0001 {
+ Mouse::ScrollDown(cx, cy)
+ } else {
+ Mouse::ScrollUp(cx, cy)
+ }
+ } else {
+ let drag = cb & 0b0010_0000 == 0b0010_0000;
+
+ match (cb & 0b0000_0011, up, drag) {
+ (0, true, _) => Mouse::Up(MouseButton::Left, cx, cy),
+ (0, false, false) => Mouse::Down(MouseButton::Left, cx, cy),
+ (0, false, true) => Mouse::Drag(MouseButton::Left, cx, cy),
+ (1, true, _) => Mouse::Up(MouseButton::Middle, cx, cy),
+ (1, false, false) => Mouse::Down(MouseButton::Middle, cx, cy),
+ (1, false, true) => Mouse::Drag(MouseButton::Middle, cx, cy),
+ (2, true, _) => Mouse::Up(MouseButton::Right, cx, cy),
+ (2, false, false) => Mouse::Down(MouseButton::Right, cx, cy),
+ (2, false, true) => Mouse::Drag(MouseButton::Right, cx, cy),
+ _ => return None,
+ }
+ };
+
+ Some(Sequence::Mouse(mouse, modifiers))
+}
+
+fn parse_csi_rxvt_mouse(parameters: &[u64]) -> Option<Sequence> {
+ // ESC [ Cb ; Cx ; Cy ; M
+
+ if parameters.len() < 3 {
+ return None;
+ }
+
+ let cb = parameters[0];
+ let cx = parameters[1] as u16;
+ let cy = parameters[2] as u16;
+
+ let mut modifiers = KeyModifiers::empty();
+
+ if cb & 0b0000_0100 == 0b0000_0100 {
+ modifiers |= KeyModifiers::SHIFT;
+ }
+
+ if cb & 0b0000_1000 == 0b0000_1000 {
+ modifiers |= KeyModifiers::ALT;
+ }
+
+ if cb & 0b0001_0000 == 0b0001_0000 {
+ modifiers |= KeyModifiers::CONTROL;
+ }
+
+ let mouse = if cb & 0b0110_0000 == 0b0110_0000 {
+ if cb & 0b0000_0001 == 0b0000_0001 {
+ Mouse::ScrollDown(cx, cy)
+ } else {
+ Mouse::ScrollUp(cx, cy)
+ }
+ } else {
+ let drag = cb & 0b0100_0000 == 0b0100_0000;
+
+ match (cb & 0b0000_0011, drag) {
+ (0b0000_0000, false) => Mouse::Down(MouseButton::Left, cx, cy),
+ (0b0000_0010, false) => Mouse::Down(MouseButton::Right, cx, cy),
+ (0b0000_0001, false) => Mouse::Down(MouseButton::Middle, cx, cy),
+
+ (0b0000_0000, true) => Mouse::Drag(MouseButton::Left, cx, cy),
+ (0b0000_0010, true) => Mouse::Drag(MouseButton::Right, cx, cy),
+ (0b0000_0001, true) => Mouse::Drag(MouseButton::Middle, cx, cy),
+
+ (0b0000_0011, false) => Mouse::Up(MouseButton::Any, cx, cy),
+
+ _ => return None,
+ }
+ };
+
+ Some(Sequence::Mouse(mouse, modifiers))
+}
diff --git a/vendor/anes/src/parser/types.rs b/vendor/anes/src/parser/types.rs
new file mode 100644
index 000000000..66b6561fd
--- /dev/null
+++ b/vendor/anes/src/parser/types.rs
@@ -0,0 +1,79 @@
+use bitflags::bitflags;
+
+/// A parsed ANSI escape sequence.
+///
+/// Check the [`Parser`](struct.Parser.html) structure documentation for examples
+/// how to retrieve these values.
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub enum Sequence {
+ /// A keyboard event sequence.
+ Key(KeyCode, KeyModifiers),
+ /// A mouse event sequence.
+ Mouse(Mouse, KeyModifiers),
+ /// A cursor position (`x`, `y`).
+ ///
+ /// Top/left cell is represented as `Sequence::CursorPosition(1, 1)`.
+ CursorPosition(u16, u16),
+}
+
+bitflags! {
+ /// A key modifiers.
+ pub struct KeyModifiers: u8 {
+ const SHIFT = 0b0000_0001;
+ const CONTROL = 0b0000_0010;
+ const ALT = 0b0000_0100;
+ const META = 0b0000_1000;
+ }
+}
+
+/// A key code.
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub enum KeyCode {
+ Backspace,
+ Enter,
+ Left,
+ Right,
+ Up,
+ Down,
+ Home,
+ End,
+ PageUp,
+ PageDown,
+ Tab,
+ BackTab,
+ Delete,
+ Insert,
+ F(u8),
+ Char(char),
+ Null,
+ Esc,
+}
+
+/// A mouse event.
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub enum Mouse {
+ /// A mouse button press.
+ Down(MouseButton, u16, u16),
+ /// A mouse button release.
+ Up(MouseButton, u16, u16),
+ /// A mouse movement with pressed button.
+ Drag(MouseButton, u16, u16),
+ /// A mouse wheel scrolled up.
+ ScrollUp(u16, u16),
+ /// A mouse wheel scrolled down.
+ ScrollDown(u16, u16),
+}
+
+/// A mouse button.
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub enum MouseButton {
+ Left,
+ Right,
+ Middle,
+ /// This variant is provided only if [`Parser`](struct.Parser.html) doesn't know which
+ /// mouse button was pressed/released.
+ ///
+ /// An example is [rxvt](https://en.wikipedia.org/wiki/Rxvt) - it provides which mouse
+ /// button was pressed, but doesn't provide which mouse button was released.
+ Any,
+}
diff --git a/vendor/anes/src/sequences.rs b/vendor/anes/src/sequences.rs
new file mode 100644
index 000000000..c66080045
--- /dev/null
+++ b/vendor/anes/src/sequences.rs
@@ -0,0 +1,5 @@
+pub(crate) mod attribute;
+pub(crate) mod buffer;
+pub(crate) mod color;
+pub(crate) mod cursor;
+pub(crate) mod terminal;
diff --git a/vendor/anes/src/sequences/attribute.rs b/vendor/anes/src/sequences/attribute.rs
new file mode 100644
index 000000000..30961ff4b
--- /dev/null
+++ b/vendor/anes/src/sequences/attribute.rs
@@ -0,0 +1,133 @@
+use std::fmt;
+
+sequence!(
+ /// Resets all attributes.
+ ///
+ /// This sequence resets all attributes previously set by the:
+ ///
+ /// * [`SetAttribute`](struct.SetAttribute.html)
+ /// * [`SetForegroundColor`](struct.SetBackgroundColor.html)
+ /// * [`SetBackgroundColor`](struct.SetForegroundColor.html)
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::ResetAttributes;
+ ///
+ /// let mut stdout = stdout();
+ /// write!(stdout, "{}", ResetAttributes);
+ /// ```
+ struct ResetAttributes => sgr!("0")
+);
+
+/// A display attribute.
+///
+/// This is **NOT** a full ANSI sequence. `Attribute` must be used along with
+/// the [`SetAttribute`](struct.SetAttribute.html).
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::io::{stdout, Write};
+/// use anes::{Attribute, SetAttribute};
+///
+/// let mut stdout = stdout();
+/// write!(stdout, "{}Bold text", SetAttribute(Attribute::Bold));
+/// ```
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
+pub enum Attribute {
+ /// Bold (increased) intensity.
+ Bold = 1,
+ /// Faint (decreased) intensity.
+ Faint = 2,
+ /// Normal intensity (turns off `Bold` and/or `Faint`).
+ Normal = 22,
+
+ /// Italic.
+ Italic = 3,
+ /// Turns off `Italic`.
+ ItalicOff = 23,
+
+ /// Underlined text.
+ Underline = 4,
+ /// Turns off `Underline`.
+ UnderlineOff = 24,
+
+ /// Blinking text.
+ Blink = 5,
+ /// Turns off blinking text (`Blink`).
+ BlinkOff = 25,
+
+ /// Reverse foreground & background colors.
+ Reverse = 7,
+ /// Turns off `Reverse`.
+ ReverseOff = 27,
+
+ /// Concealed (hidden).
+ Conceal = 8,
+ /// Turns off `Conceal`.
+ ConcealOff = 28,
+
+ /// Crossed.
+ Crossed = 9,
+ /// Turns off `Crossed`.
+ CrossedOff = 29,
+}
+
+impl fmt::Display for Attribute {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}", *self as i32)
+ }
+}
+
+sequence!(
+ /// Sets the display attribute.
+ ///
+ /// See the [`Attribute`](enum.Attribute.html) enum for a list of attributes you can (un)set.
+ ///
+ /// The [`ResetAttributes`](struct.ResetAttributes.html) sequence can be used to turn off all
+ /// attributes.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::{Attribute, SetAttribute};
+ ///
+ /// let mut stdout = stdout();
+ /// write!(stdout, "{}Blinking text", SetAttribute(Attribute::Blink));
+ /// ```
+ struct SetAttribute(Attribute) =>
+ |this, f| write!(f, sgr!("{}"), this.0)
+);
+
+#[cfg(test)]
+test_sequences!(
+ set_attribute(
+ SetAttribute(Attribute::Bold) => "\x1B[1m",
+ SetAttribute(Attribute::Faint) => "\x1B[2m",
+ SetAttribute(Attribute::Normal) => "\x1B[22m",
+
+ SetAttribute(Attribute::Italic) => "\x1B[3m",
+ SetAttribute(Attribute::ItalicOff) => "\x1B[23m",
+
+ SetAttribute(Attribute::Underline) => "\x1B[4m",
+ SetAttribute(Attribute::UnderlineOff) => "\x1B[24m",
+
+ SetAttribute(Attribute::Blink) => "\x1B[5m",
+ SetAttribute(Attribute::BlinkOff) => "\x1B[25m",
+
+ SetAttribute(Attribute::Reverse) => "\x1B[7m",
+ SetAttribute(Attribute::ReverseOff) => "\x1B[27m",
+
+ SetAttribute(Attribute::Conceal) => "\x1B[8m",
+ SetAttribute(Attribute::ConcealOff) => "\x1B[28m",
+
+ SetAttribute(Attribute::Crossed) => "\x1B[9m",
+ SetAttribute(Attribute::CrossedOff) => "\x1B[29m",
+ ),
+ reset_attributes(
+ ResetAttributes => "\x1B[0m",
+ )
+);
diff --git a/vendor/anes/src/sequences/buffer.rs b/vendor/anes/src/sequences/buffer.rs
new file mode 100644
index 000000000..053195af6
--- /dev/null
+++ b/vendor/anes/src/sequences/buffer.rs
@@ -0,0 +1,145 @@
+sequence!(
+ /// Switches to the alternate buffer.
+ ///
+ /// Use the [`SwitchBufferToNormal`](struct.SwitchBufferToNormal.html) sequence to switch
+ /// back to the normal buffer.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::{SwitchBufferToAlternate, SwitchBufferToNormal};
+ ///
+ /// let mut stdout = stdout();
+ /// write!(stdout, "{}", SwitchBufferToAlternate);
+ /// // Your app on alternate screen
+ /// write!(stdout, "{}", SwitchBufferToNormal);
+ /// ```
+ struct SwitchBufferToAlternate => csi!("?1049h")
+);
+
+sequence!(
+ /// Switches to the normal buffer.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::{SwitchBufferToAlternate, SwitchBufferToNormal};
+ ///
+ /// let mut stdout = stdout();
+ /// write!(stdout, "{}", SwitchBufferToAlternate);
+ /// // Your app on alternate screen
+ /// write!(stdout, "{}", SwitchBufferToNormal);
+ /// ```
+ struct SwitchBufferToNormal => csi!("?1049l")
+);
+
+sequence!(
+ /// Scrolls up by the given number of rows.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::ScrollBufferUp;
+ ///
+ /// let mut stdout = stdout();
+ /// // Scroll up by 5 lines
+ /// write!(stdout, "{}", ScrollBufferUp(5));
+ /// ```
+ struct ScrollBufferUp(u16) =>
+ |this, f| write!(f, csi!("{}S"), this.0)
+);
+
+sequence!(
+ /// Scrolls down by the given number of rows.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::ScrollBufferDown;
+ ///
+ /// let mut stdout = stdout();
+ /// // Scroll down by 10 lines
+ /// write!(stdout, "{}", ScrollBufferDown(10));
+ /// ```
+ struct ScrollBufferDown(u16) =>
+ |this, f| write!(f, csi!("{}T"), this.0)
+);
+
+sequence!(
+ /// Clears part of the line.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::ClearLine;
+ ///
+ /// let mut stdout = stdout();
+ /// // Clear the whole line
+ /// write!(stdout, "{}", ClearLine::All);
+ /// ```
+ enum ClearLine {
+ /// Clears from the cursor position to end of the line.
+ Right => csi!("K"),
+ /// Clears from the cursor position to beginning of the line.
+ Left => csi!("1K"),
+ /// Clears the whole line.
+ All => csi!("2K"),
+ }
+);
+
+sequence!(
+ /// Clears part of the buffer.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::ClearBuffer;
+ ///
+ /// let mut stdout = stdout();
+ /// // Clear the entire buffer
+ /// write!(stdout, "{}", ClearBuffer::All);
+ /// ```
+ enum ClearBuffer {
+ /// Clears from the cursor position to end of the screen.
+ Below => csi!("J"),
+ /// Clears from the cursor position to beginning of the screen.
+ Above => csi!("1J"),
+ /// Clears the entire buffer.
+ All => csi!("2J"),
+ /// Clears the entire buffer and all saved lines in the scrollback buffer.
+ SavedLines => csi!("3J"),
+ }
+);
+
+#[cfg(test)]
+test_sequences!(
+ switch_buffer_to_alternate(
+ SwitchBufferToAlternate => "\x1B[?1049h",
+ ),
+ switch_buffer_to_main(
+ SwitchBufferToNormal => "\x1B[?1049l",
+ ),
+ scroll_buffer_up(
+ ScrollBufferUp(10) => "\x1B[10S",
+ ),
+ scroll_buffer_down(
+ ScrollBufferDown(10) => "\x1B[10T",
+ ),
+ clear_line(
+ ClearLine::Right => "\x1B[K",
+ ClearLine::Left => "\x1B[1K",
+ ClearLine::All => "\x1B[2K",
+ ),
+ clear_buffer(
+ ClearBuffer::Below => "\x1B[J",
+ ClearBuffer::Above => "\x1B[1J",
+ ClearBuffer::All => "\x1B[2J",
+ ClearBuffer::SavedLines => "\x1B[3J",
+ ),
+);
diff --git a/vendor/anes/src/sequences/color.rs b/vendor/anes/src/sequences/color.rs
new file mode 100644
index 000000000..b019f0fdd
--- /dev/null
+++ b/vendor/anes/src/sequences/color.rs
@@ -0,0 +1,189 @@
+use std::fmt;
+
+/// A color.
+///
+/// This is **NOT** a full ANSI sequence. `Color` must be used along with
+/// the:
+///
+/// * [`SetBackgroundColor`](struct.SetBackgroundColor.html)
+/// * [`SetForegroundColor`](struct.SetForegroundColor.html)
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::io::{stdout, Write};
+/// use anes::{Color, SetForegroundColor};
+///
+/// let mut stdout = stdout();
+/// // Set the foreground color to red
+/// write!(stdout, "{}", SetForegroundColor(Color::Red));
+/// ```
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
+pub enum Color {
+ /// Default color.
+ Default,
+ /// Black color.
+ Black,
+ /// Dark red color.
+ DarkRed,
+ /// Dark green color.
+ DarkGreen,
+ /// Dark yellow color.
+ DarkYellow,
+ /// Dark blue color.
+ DarkBlue,
+ /// Dark magenta color.
+ DarkMagenta,
+ /// Dark cyan color.
+ DarkCyan,
+ /// Dark gray color.
+ ///
+ /// Also knows as light (bright) black.
+ DarkGray,
+ /// Light (bright) gray color.
+ ///
+ /// Also known as dark white.
+ Gray,
+ /// Light (bright) red color.
+ Red,
+ /// Light (bright) green color.
+ Green,
+ /// Light (bright) yellow color.
+ Yellow,
+ /// Light (bright) blue color.
+ Blue,
+ /// Light (bright) magenta color.
+ Magenta,
+ /// Light (bright) cyan color.
+ Cyan,
+ /// White color.
+ White,
+ /// A color from the predefined set of ANSI colors.
+ ///
+ /// ```text
+ /// 0 - 7: standard colors (as in ESC [ 30–37 m)
+ /// 8- 15: high intensity colors (as in ESC [ 90–97 m)
+ /// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+ /// 232-255: grayscale from black to white in 24 steps
+ /// ```
+ ///
+ /// See [8-bit](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) for more information.
+ Ansi(u8),
+ /// An RGB color.
+ ///
+ /// See [24-bit](https://en.wikipedia.org/wiki/ANSI_escape_code#24-bit) for more information.
+ Rgb(u8, u8, u8),
+}
+
+impl fmt::Display for Color {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ // Color::Default is handled in the SetBackgroundColor & SetForegroundColor
+ Color::Default => Ok(()),
+ Color::Black => write!(f, "5;0"),
+ Color::DarkRed => write!(f, "5;1"),
+ Color::DarkGreen => write!(f, "5;2"),
+ Color::DarkYellow => write!(f, "5;3"),
+ Color::DarkBlue => write!(f, "5;4"),
+ Color::DarkMagenta => write!(f, "5;5"),
+ Color::DarkCyan => write!(f, "5;6"),
+ Color::Gray => write!(f, "5;7"),
+ Color::DarkGray => write!(f, "5;8"),
+ Color::Red => write!(f, "5;9"),
+ Color::Green => write!(f, "5;10"),
+ Color::Yellow => write!(f, "5;11"),
+ Color::Blue => write!(f, "5;12"),
+ Color::Magenta => write!(f, "5;13"),
+ Color::Cyan => write!(f, "5;14"),
+ Color::White => write!(f, "5;15"),
+ Color::Ansi(value) => write!(f, "5;{}", value),
+ Color::Rgb(r, g, b) => write!(f, "2;{};{};{}", r, g, b),
+ }
+ }
+}
+
+sequence! {
+ /// Sets the foreground color.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::{Color, SetForegroundColor};
+ ///
+ /// let mut stdout = stdout();
+ /// // Set the foreground color to blue
+ /// write!(stdout, "{}", SetForegroundColor(Color::Blue));
+ /// ```
+ struct SetForegroundColor(Color) =>
+ |this, f| match this.0 {
+ Color::Default => write!(f, sgr!("39")),
+ _ => write!(f, sgr!("38;{}"), this.0),
+ }
+}
+
+sequence! {
+ /// Sets the background color.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::{Color, SetBackgroundColor};
+ ///
+ /// let mut stdout = stdout();
+ /// // Set the background color to yellow
+ /// write!(stdout, "{}", SetBackgroundColor(Color::Yellow));
+ /// ```
+ struct SetBackgroundColor(Color) =>
+ |this, f| match this.0 {
+ Color::Default => write!(f, sgr!("49")),
+ _ => write!(f, sgr!("48;{}"), this.0),
+ }
+}
+
+#[cfg(test)]
+test_sequences!(
+ set_foreground_color(
+ SetForegroundColor(Color::Default) => "\x1B[39m",
+ SetForegroundColor(Color::Black) => "\x1B[38;5;0m",
+ SetForegroundColor(Color::DarkRed) => "\x1B[38;5;1m",
+ SetForegroundColor(Color::DarkGreen) => "\x1B[38;5;2m",
+ SetForegroundColor(Color::DarkYellow) => "\x1B[38;5;3m",
+ SetForegroundColor(Color::DarkBlue) => "\x1B[38;5;4m",
+ SetForegroundColor(Color::DarkMagenta) => "\x1B[38;5;5m",
+ SetForegroundColor(Color::DarkCyan) => "\x1B[38;5;6m",
+ SetForegroundColor(Color::DarkGray) => "\x1B[38;5;8m",
+ SetForegroundColor(Color::Gray) => "\x1B[38;5;7m",
+ SetForegroundColor(Color::Red) => "\x1B[38;5;9m",
+ SetForegroundColor(Color::Green) => "\x1B[38;5;10m",
+ SetForegroundColor(Color::Yellow) => "\x1B[38;5;11m",
+ SetForegroundColor(Color::Blue) => "\x1B[38;5;12m",
+ SetForegroundColor(Color::Magenta) => "\x1B[38;5;13m",
+ SetForegroundColor(Color::Cyan) => "\x1B[38;5;14m",
+ SetForegroundColor(Color::White) => "\x1B[38;5;15m",
+ SetForegroundColor(Color::Ansi(200)) => "\x1B[38;5;200m",
+ SetForegroundColor(Color::Rgb(1, 2, 3)) => "\x1B[38;2;1;2;3m",
+ ),
+ set_background_color(
+ SetBackgroundColor(Color::Default) => "\x1B[49m",
+ SetBackgroundColor(Color::Black) => "\x1B[48;5;0m",
+ SetBackgroundColor(Color::DarkRed) => "\x1B[48;5;1m",
+ SetBackgroundColor(Color::DarkGreen) => "\x1B[48;5;2m",
+ SetBackgroundColor(Color::DarkYellow) => "\x1B[48;5;3m",
+ SetBackgroundColor(Color::DarkBlue) => "\x1B[48;5;4m",
+ SetBackgroundColor(Color::DarkMagenta) => "\x1B[48;5;5m",
+ SetBackgroundColor(Color::DarkCyan) => "\x1B[48;5;6m",
+ SetBackgroundColor(Color::DarkGray) => "\x1B[48;5;8m",
+ SetBackgroundColor(Color::Gray) => "\x1B[48;5;7m",
+ SetBackgroundColor(Color::Red) => "\x1B[48;5;9m",
+ SetBackgroundColor(Color::Green) => "\x1B[48;5;10m",
+ SetBackgroundColor(Color::Yellow) => "\x1B[48;5;11m",
+ SetBackgroundColor(Color::Blue) => "\x1B[48;5;12m",
+ SetBackgroundColor(Color::Magenta) => "\x1B[48;5;13m",
+ SetBackgroundColor(Color::Cyan) => "\x1B[48;5;14m",
+ SetBackgroundColor(Color::White) => "\x1B[48;5;15m",
+ SetBackgroundColor(Color::Ansi(200)) => "\x1B[48;5;200m",
+ SetBackgroundColor(Color::Rgb(1, 2, 3)) => "\x1B[48;2;1;2;3m",
+ )
+);
diff --git a/vendor/anes/src/sequences/cursor.rs b/vendor/anes/src/sequences/cursor.rs
new file mode 100644
index 000000000..37abc3b19
--- /dev/null
+++ b/vendor/anes/src/sequences/cursor.rs
@@ -0,0 +1,352 @@
+//! A terminal cursor related ANSI escape sequences.
+
+sequence!(
+ /// Saves the cursor position.
+ ///
+ /// Use the [`RestoreCursorPosition`](struct.RestoreCursorPosition.html) sequence to
+ /// restore the cursor position.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::{SaveCursorPosition, RestoreCursorPosition};
+ ///
+ /// let mut stdout = stdout();
+ /// // Save cursor position
+ /// write!(stdout, "{}", SaveCursorPosition);
+ ///
+ /// // Your app
+ ///
+ /// // Restore cursor position
+ /// write!(stdout, "{}", RestoreCursorPosition);
+ /// ```
+ struct SaveCursorPosition => esc!("7")
+);
+
+sequence!(
+ /// Restores the cursor position.
+ ///
+ /// Use the [`SaveCursorPosition`](struct.SaveCursorPosition.html) sequence to
+ /// save the cursor position.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::{SaveCursorPosition, RestoreCursorPosition};
+ ///
+ /// let mut stdout = stdout();
+ /// // Save cursor position
+ /// write!(stdout, "{}", SaveCursorPosition);
+ ///
+ /// // Your app
+ ///
+ /// // Restore cursor position
+ /// write!(stdout, "{}", RestoreCursorPosition);
+ /// ```
+ struct RestoreCursorPosition => esc!("8")
+);
+
+sequence!(
+ /// Hides the cursor.
+ ///
+ /// Use the [`ShowCursor`](struct.ShowCursor.html) sequence to show the cursor.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::HideCursor;
+ ///
+ /// let mut stdout = stdout();
+ /// // Hide cursor
+ /// write!(stdout, "{}", HideCursor);
+ /// ```
+ struct HideCursor => csi!("?25l")
+);
+
+sequence!(
+ /// Shows the cursor.
+ ///
+ /// Use the [`HideCursor`](struct.HideCursor.html) sequence to hide the cursor.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::ShowCursor;
+ ///
+ /// let mut stdout = stdout();
+ /// // Show cursor
+ /// write!(stdout, "{}", ShowCursor);
+ /// ```
+ struct ShowCursor => csi!("?25h")
+);
+
+sequence!(
+ /// Enables the cursor blinking.
+ ///
+ /// Use the [`DisableCursorBlinking`](struct.DisableCursorBlinking.html) sequence to disable
+ /// cursor blinking.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::EnableCursorBlinking;
+ ///
+ /// let mut stdout = stdout();
+ /// // Enable cursor blinking
+ /// write!(stdout, "{}", EnableCursorBlinking);
+ /// ```
+ struct EnableCursorBlinking => csi!("?12h")
+);
+
+sequence!(
+ /// Disables the cursor blinking.
+ ///
+ /// Use the [`EnableCursorBlinking`](struct.EnableCursorBlinking.html) sequence to enable
+ /// cursor blinking.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::DisableCursorBlinking;
+ ///
+ /// let mut stdout = stdout();
+ /// // Disable cursor blinking
+ /// write!(stdout, "{}", DisableCursorBlinking);
+ /// ```
+ struct DisableCursorBlinking => csi!("?12l")
+);
+
+sequence!(
+ /// Moves the cursor to the given location (column, row).
+ ///
+ /// # Notes
+ ///
+ /// Top/left cell is represented as `1, 1` (`column, row`).
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::MoveCursorTo;
+ ///
+ /// let mut stdout = stdout();
+ /// // Move cursor to top left cell
+ /// write!(stdout, "{}", MoveCursorTo(1, 1));
+ /// ```
+ struct MoveCursorTo(u16, u16) =>
+ |this, f| write!(f, csi!("{};{}H"), this.1, this.0)
+);
+
+sequence!(
+ /// Moves the cursor up by the given number of rows.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::MoveCursorUp;
+ ///
+ /// let mut stdout = stdout();
+ /// // Move cursor up by 5 rows
+ /// write!(stdout, "{}", MoveCursorUp(5));
+ /// ```
+ struct MoveCursorUp(u16) =>
+ |this, f| write!(f, csi!("{}A"), this.0)
+);
+
+sequence!(
+ /// Moves the cursor down by the given number of rows.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::MoveCursorDown;
+ ///
+ /// let mut stdout = stdout();
+ /// // Move cursor down by 5 rows
+ /// write!(stdout, "{}", MoveCursorDown(5));
+ /// ```
+ struct MoveCursorDown(u16) =>
+ |this, f| write!(f, csi!("{}B"), this.0)
+);
+
+sequence!(
+ /// Moves the cursor right by the given number of columns.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::MoveCursorRight;
+ ///
+ /// let mut stdout = stdout();
+ /// // Move cursor right by 5 columns
+ /// write!(stdout, "{}", MoveCursorRight(5));
+ /// ```
+ struct MoveCursorRight(u16) =>
+ |this, f| write!(f, csi!("{}C"), this.0)
+);
+
+sequence!(
+ /// Moves the cursor left by the given number of columns.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::MoveCursorLeft;
+ ///
+ /// let mut stdout = stdout();
+ /// // Move cursor left by 5 columns
+ /// write!(stdout, "{}", MoveCursorLeft(5));
+ /// ```
+ struct MoveCursorLeft(u16) =>
+ |this, f| write!(f, csi!("{}D"), this.0)
+);
+
+sequence!(
+ /// Moves the cursor to beginning of line the given number of lines down.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::MoveCursorToNextLine;
+ ///
+ /// let mut stdout = stdout();
+ /// // Move cursor down by 2 rows and the move it to the first column
+ /// write!(stdout, "{}", MoveCursorToNextLine(2));
+ /// ```
+ ///
+ /// The previous example does the same thing as the following one:
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::{MoveCursorDown, MoveCursorToColumn};
+ ///
+ /// let mut stdout = stdout();
+ /// write!(stdout, "{}{}", MoveCursorDown(2), MoveCursorToColumn(1));
+ /// ```
+ struct MoveCursorToNextLine(u16) =>
+ |this, f| write!(f, csi!("{}E"), this.0)
+);
+
+sequence!(
+ /// Moves the cursor to beginning of line the given number of lines up.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::MoveCursorToPreviousLine;
+ ///
+ /// let mut stdout = stdout();
+ /// // Move cursor up by 2 rows and the move it to the first column
+ /// write!(stdout, "{}", MoveCursorToPreviousLine(2));
+ /// ```
+ ///
+ /// The previous example does the same thing as the following one:
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::{MoveCursorUp, MoveCursorToColumn};
+ ///
+ /// let mut stdout = stdout();
+ /// write!(stdout, "{}{}", MoveCursorUp(2), MoveCursorToColumn(1));
+ /// ```
+ struct MoveCursorToPreviousLine(u16) =>
+ |this, f| write!(f, csi!("{}F"), this.0)
+);
+
+sequence!(
+ /// Moves the cursor to the given column.
+ ///
+ /// # Notes
+ ///
+ /// Beginning of the line (left cell) is represented as `1`.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::MoveCursorToColumn;
+ ///
+ /// let mut stdout = stdout();
+ /// // Move cursor to the 10th column (same row)
+ /// write!(stdout, "{}", MoveCursorToColumn(10));
+ /// ```
+ struct MoveCursorToColumn(u16) =>
+ |this, f| write!(f, csi!("{}G"), this.0)
+);
+
+// TODO Enhance example with Parser to show how to retrieve it
+sequence!(
+ /// Asks for the current cursor position.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::ReportCursorPosition;
+ ///
+ /// let mut stdout = stdout();
+ /// write!(stdout, "{}", ReportCursorPosition);
+ /// ```
+ struct ReportCursorPosition => csi!("6n")
+);
+
+#[cfg(test)]
+test_sequences!(
+ save_cursor_position(
+ SaveCursorPosition => "\x1B7",
+ ),
+ restore_cursor_position(
+ RestoreCursorPosition => "\x1B8",
+ ),
+ hide_cursor(
+ HideCursor => "\x1B[?25l",
+ ),
+ show_cursor(
+ ShowCursor => "\x1B[?25h",
+ ),
+ disable_cursor_blinking(
+ DisableCursorBlinking => "\x1B[?12l",
+ ),
+ enable_cursor_blinking(
+ EnableCursorBlinking => "\x1B[?12h",
+ ),
+ move_cursor_up(
+ MoveCursorUp(10) => "\x1B[10A",
+ ),
+ move_cursor_down(
+ MoveCursorDown(10) => "\x1B[10B",
+ ),
+ move_cursor_right(
+ MoveCursorRight(10) => "\x1B[10C",
+ ),
+ move_cursor_left(
+ MoveCursorLeft(10) => "\x1B[10D",
+ ),
+ move_cursor_to(
+ MoveCursorTo(5, 10) => "\x1B[10;5H",
+ ),
+ move_cursor_to_next_line(
+ MoveCursorToNextLine(5) => "\x1B[5E",
+ ),
+ move_cursor_to_previous_line(
+ MoveCursorToPreviousLine(5) => "\x1B[5F",
+ ),
+ move_cursor_to_column(
+ MoveCursorToColumn(1) => "\x1B[1G",
+ ),
+ report_cursor_position(
+ ReportCursorPosition => "\x1B[6n",
+ )
+);
diff --git a/vendor/anes/src/sequences/terminal.rs b/vendor/anes/src/sequences/terminal.rs
new file mode 100644
index 000000000..74eada65b
--- /dev/null
+++ b/vendor/anes/src/sequences/terminal.rs
@@ -0,0 +1,54 @@
+//! A terminal related ANSI escape sequences.
+
+sequence!(
+ /// Resizes the text area to the given width and height in characters.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::{stdout, Write};
+ /// use anes::ResizeTextArea;
+ ///
+ /// let mut stdout = stdout();
+ /// // Resize the terminal to 80x25
+ /// write!(stdout, "{}", ResizeTextArea(80, 25));
+ /// ```
+ struct ResizeTextArea(u16, u16) =>
+ |this, f| write!(f, csi!("8;{};{}t"), this.1, this.0)
+);
+
+sequence!(
+ /// Tells the terminal to start reporting mouse events.
+ ///
+ /// Mouse events are not reported by default.
+ struct EnableMouseEvents => concat!(
+ csi!("?1000h"),
+ csi!("?1002h"),
+ csi!("?1015h"),
+ csi!("?1006h")
+ )
+);
+
+sequence!(
+ /// Tells the terminal to stop reporting mouse events.
+ struct DisableMouseEvents => concat!(
+ csi!("?1006l"),
+ csi!("?1015l"),
+ csi!("?1002l"),
+ csi!("?1000l")
+ )
+);
+
+#[cfg(test)]
+test_sequences!(
+ resize_text_area(
+ ResizeTextArea(80, 25) => "\x1B[8;25;80t",
+ ResizeTextArea(1, 1) => "\x1B[8;1;1t",
+ ),
+ enable_mouse_events(
+ EnableMouseEvents => "\x1B[?1000h\x1B[?1002h\x1B[?1015h\x1B[?1006h",
+ ),
+ disable_mouse_events(
+ DisableMouseEvents => "\x1B[?1006l\x1B[?1015l\x1B[?1002l\x1B[?1000l",
+ )
+);