Compare commits
11 Commits
6ed05bfb18
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
555b28e25a | ||
![]() |
e1082e47cb | ||
![]() |
6b973008e0 | ||
![]() |
7a31a7346b | ||
![]() |
a431fb31f8 | ||
![]() |
bfcd268967 | ||
![]() |
af1951d169 | ||
![]() |
80b28ea6c4 | ||
![]() |
27beb4bc1f | ||
![]() |
28001c3197 | ||
![]() |
e512d4f0f1 |
12
Cargo.toml
12
Cargo.toml
@@ -1,21 +1,21 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ansi-parser"
|
authors = ["David Bittner <bittneradave@gmail.com>"]
|
||||||
description = "A library using nom for parsing ANSI Escape Codes"
|
description = "A library using nom for parsing ANSI Escape Codes"
|
||||||
homepage = "https://gitlab.com/DavidBittner/ansi-parser"
|
homepage = "https://gitlab.com/DavidBittner/ansi-parser"
|
||||||
authors = ["David Bittner <bittneradave@gmail.com>"]
|
name = "ansi-parser"
|
||||||
|
|
||||||
version = "0.8.0"
|
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
|
version = "0.9.1"
|
||||||
|
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
heapless = "0.5.6"
|
heapless = "0.8.0"
|
||||||
|
|
||||||
[dependencies.nom]
|
[dependencies.nom]
|
||||||
version = "4.2.3"
|
|
||||||
default-features = false
|
default-features = false
|
||||||
|
version = "8.0.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = ["nom/std"]
|
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
|
std = ["nom/std"]
|
||||||
|
53
src/enums.rs
53
src/enums.rs
@@ -1,24 +1,36 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use heapless::{consts::U5, Vec};
|
use heapless::Vec;
|
||||||
|
|
||||||
///The following are the implemented ANSI escape sequences. More to be added.
|
///The following are the implemented ANSI escape sequences. More to be added.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum AnsiSequence {
|
pub enum AnsiSequence {
|
||||||
Escape,
|
Escape,
|
||||||
CursorPos(u32, u32),
|
CursorHome, // ^[[H
|
||||||
CursorUp(u32),
|
CursorPos(u32, u32), // ^[[#;#H or [#;#f
|
||||||
CursorDown(u32),
|
CursorUp(u32), // ^[[#A
|
||||||
CursorForward(u32),
|
CursorDown(u32), // ^[[#B
|
||||||
CursorBackward(u32),
|
CursorRight(u32), // ^[[#C
|
||||||
CursorSave,
|
CursorLeft(u32), // ^[[#D
|
||||||
CursorRestore,
|
// TODO ^[[#E
|
||||||
EraseDisplay,
|
// TODO ^[[#F
|
||||||
EraseLine,
|
// TODO ^[[#G
|
||||||
SetGraphicsMode(Vec<u8, U5>),
|
RequestCursorPos, // ^[[6n TODO rename GetCursorPos to RequestCursorPos
|
||||||
SetMode(u8),
|
CursorUpScroll, // ^[ M
|
||||||
ResetMode(u8),
|
CursorSave, // ^[ 7
|
||||||
|
CursorRestore, // ^[ 8
|
||||||
|
EraseScreenToEnd, // ^[[0J or ^[[J
|
||||||
|
EraseScreenFromStart, // ^[[1J
|
||||||
|
EraseScreen, // ^[[2J
|
||||||
|
// TODO ^[[3J
|
||||||
|
EraseLineToEnd, // ^[[0K or ^[[K
|
||||||
|
EraseLineFromStart, // ^[[1K
|
||||||
|
EraseLine, // ^[[2K
|
||||||
|
SetGraphicsMode(Vec<u8, 5>), // TODO figure out graphics mode
|
||||||
|
SetMode(u8), // ^[[=#h
|
||||||
|
ResetMode(u8), // ^[[=#l
|
||||||
|
|
||||||
HideCursor,
|
HideCursor,
|
||||||
ShowCursor,
|
ShowCursor,
|
||||||
CursorToApp,
|
CursorToApp,
|
||||||
@@ -65,15 +77,22 @@ impl Display for AnsiSequence {
|
|||||||
use AnsiSequence::*;
|
use AnsiSequence::*;
|
||||||
match self {
|
match self {
|
||||||
Escape => write!(formatter, "\u{1b}"),
|
Escape => write!(formatter, "\u{1b}"),
|
||||||
|
RequestCursorPos => write!(formatter, "[6n"),
|
||||||
|
CursorHome => write!(formatter, "[H"),
|
||||||
CursorPos(line, col) => write!(formatter, "[{};{}H", line, col),
|
CursorPos(line, col) => write!(formatter, "[{};{}H", line, col),
|
||||||
CursorUp(amt) => write!(formatter, "[{}A", amt),
|
CursorUp(amt) => write!(formatter, "[{}A", amt),
|
||||||
CursorDown(amt) => write!(formatter, "[{}B", amt),
|
CursorDown(amt) => write!(formatter, "[{}B", amt),
|
||||||
CursorForward(amt) => write!(formatter, "[{}C", amt),
|
CursorRight(amt) => write!(formatter, "[{}C", amt),
|
||||||
CursorBackward(amt) => write!(formatter, "[{}D", amt),
|
CursorLeft(amt) => write!(formatter, "[{}D", amt),
|
||||||
|
CursorUpScroll => write!(formatter, "[ M"),
|
||||||
CursorSave => write!(formatter, "[s"),
|
CursorSave => write!(formatter, "[s"),
|
||||||
CursorRestore => write!(formatter, "[u"),
|
CursorRestore => write!(formatter, "[u"),
|
||||||
EraseDisplay => write!(formatter, "[2J"),
|
EraseScreenToEnd => write!(formatter, "[0J"),
|
||||||
EraseLine => write!(formatter, "[K"),
|
EraseScreenFromStart => write!(formatter, "[1J"),
|
||||||
|
EraseScreen => write!(formatter, "[2J"),
|
||||||
|
EraseLineToEnd => write!(formatter, "[0K"),
|
||||||
|
EraseLineFromStart => write!(formatter, "[1K"),
|
||||||
|
EraseLine => write!(formatter, "[2K"),
|
||||||
SetGraphicsMode(vec) => match vec.len() {
|
SetGraphicsMode(vec) => match vec.len() {
|
||||||
0 => write!(formatter, "[m"),
|
0 => write!(formatter, "[m"),
|
||||||
1 => write!(formatter, "[{}m", vec[0]),
|
1 => write!(formatter, "[{}m", vec[0]),
|
||||||
|
525
src/parsers.rs
525
src/parsers.rs
@@ -3,242 +3,216 @@ mod tests;
|
|||||||
|
|
||||||
use crate::AnsiSequence;
|
use crate::AnsiSequence;
|
||||||
|
|
||||||
use core::convert::TryInto;
|
|
||||||
use heapless::Vec;
|
use heapless::Vec;
|
||||||
use nom::*;
|
use nom::branch::alt;
|
||||||
|
use nom::bytes::complete::tag;
|
||||||
|
use nom::character::complete::{digit0, digit1};
|
||||||
|
use nom::combinator::{map, map_res, opt, value};
|
||||||
|
use nom::sequence::{delimited, preceded};
|
||||||
|
use nom::IResult;
|
||||||
|
use nom::Parser;
|
||||||
|
|
||||||
macro_rules! tag_parser {
|
macro_rules! tag_parser {
|
||||||
($sig:ident, $tag:expr, $ret:expr) => {
|
($sig:ident, $tag:expr, $ret:expr) => {
|
||||||
named!(
|
fn $sig(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
$sig<&str, AnsiSequence>,
|
value($ret, tag($tag)).parse(input)
|
||||||
do_parse!(
|
|
||||||
tag!($tag) >>
|
|
||||||
($ret)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(
|
fn parse_u32(input: &str) -> IResult<&str, u32> {
|
||||||
parse_int<&str, u32>,
|
map_res(digit1, |s: &str| s.parse::<u32>()).parse(input)
|
||||||
map_res!(
|
}
|
||||||
nom::digit,
|
|
||||||
|s: &str| s.parse::<u32>()
|
fn parse_u8(input: &str) -> IResult<&str, u8> {
|
||||||
)
|
map_res(digit1, |s: &str| s.parse::<u8>()).parse(input)
|
||||||
);
|
}
|
||||||
|
|
||||||
// TODO kind of ugly, would prefer to pass in the default so we could use it for
|
// TODO kind of ugly, would prefer to pass in the default so we could use it for
|
||||||
// all escapes with defaults (not just those that default to 1).
|
// all escapes with defaults (not just those that default to 1).
|
||||||
named!(
|
fn parse_def_cursor_int(input: &str) -> IResult<&str, u32> {
|
||||||
parse_def_cursor_int<&str, u32>,
|
map(digit0, |s: &str| s.parse::<u32>().unwrap_or(1)).parse(input)
|
||||||
map!(
|
}
|
||||||
nom::digit0,
|
|
||||||
|s: &str| s.parse::<u32>().unwrap_or(1)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
named!(
|
fn cursor_pos(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
cursor_pos<&str, AnsiSequence>,
|
map(
|
||||||
do_parse!(
|
(
|
||||||
tag!("[") >>
|
tag("["),
|
||||||
x: parse_def_cursor_int >>
|
parse_def_cursor_int,
|
||||||
opt!(tag!(";")) >>
|
opt(tag(";")),
|
||||||
y: parse_def_cursor_int >>
|
parse_def_cursor_int,
|
||||||
alt!(
|
alt((tag("H"), tag("f"))),
|
||||||
tag!("H") |
|
),
|
||||||
tag!("f")
|
|(_, x, _, y, _)| AnsiSequence::CursorPos(x, y),
|
||||||
) >>
|
|
||||||
(AnsiSequence::CursorPos(x, y))
|
|
||||||
)
|
)
|
||||||
);
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
named!(
|
fn escape(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
escape<&str, AnsiSequence>,
|
value(AnsiSequence::Escape, tag("\u{1b}")).parse(input)
|
||||||
do_parse!(
|
}
|
||||||
tag!("\u{1b}") >>
|
|
||||||
(AnsiSequence::Escape)
|
fn cursor_up(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
|
map(delimited(tag("["), parse_def_cursor_int, tag("A")), |am| {
|
||||||
|
AnsiSequence::CursorUp(am)
|
||||||
|
})
|
||||||
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cursor_down(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
|
map(delimited(tag("["), parse_def_cursor_int, tag("B")), |am| {
|
||||||
|
AnsiSequence::CursorDown(am)
|
||||||
|
})
|
||||||
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cursor_right(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
|
map(delimited(tag("["), parse_def_cursor_int, tag("C")), |am| {
|
||||||
|
AnsiSequence::CursorRight(am)
|
||||||
|
})
|
||||||
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cursor_left(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
|
map(delimited(tag("["), parse_def_cursor_int, tag("D")), |am| {
|
||||||
|
AnsiSequence::CursorLeft(am)
|
||||||
|
})
|
||||||
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn graphics_mode1(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
|
map(delimited(tag("["), parse_u8, tag("m")), |val| {
|
||||||
|
let mode =
|
||||||
|
Vec::from_slice(&[val]).expect("Vec::from_slice should allocate sufficient size");
|
||||||
|
AnsiSequence::SetGraphicsMode(mode)
|
||||||
|
})
|
||||||
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn graphics_mode2(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
|
map(
|
||||||
|
(tag("["), parse_u8, tag(";"), parse_u8, tag("m")),
|
||||||
|
|(_, val1, _, val2, _)| {
|
||||||
|
let mode = Vec::from_slice(&[val1, val2])
|
||||||
|
.expect("Vec::from_slice should allocate sufficient size");
|
||||||
|
AnsiSequence::SetGraphicsMode(mode)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
);
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
named!(
|
fn graphics_mode3(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
cursor_up<&str, AnsiSequence>,
|
map(
|
||||||
do_parse!(
|
(
|
||||||
tag!("[") >>
|
tag("["),
|
||||||
am: parse_def_cursor_int >>
|
parse_u8,
|
||||||
tag!("A") >>
|
tag(";"),
|
||||||
(AnsiSequence::CursorUp(am))
|
parse_u8,
|
||||||
|
tag(";"),
|
||||||
|
parse_u8,
|
||||||
|
tag("m"),
|
||||||
|
),
|
||||||
|
|(_, val1, _, val2, _, val3, _)| {
|
||||||
|
let mode = Vec::from_slice(&[val1, val2, val3])
|
||||||
|
.expect("Vec::from_slice should allocate sufficient size");
|
||||||
|
AnsiSequence::SetGraphicsMode(mode)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
);
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
named!(
|
fn graphics_mode4(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
cursor_down<&str, AnsiSequence>,
|
value(AnsiSequence::SetGraphicsMode(Vec::new()), tag("[m")).parse(input)
|
||||||
do_parse!(
|
}
|
||||||
tag!("[") >>
|
|
||||||
am: parse_def_cursor_int >>
|
fn graphics_mode5(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
tag!("B") >>
|
map(
|
||||||
(AnsiSequence::CursorDown(am))
|
(
|
||||||
|
tag("["),
|
||||||
|
parse_u8,
|
||||||
|
tag(";"),
|
||||||
|
parse_u8,
|
||||||
|
tag(";"),
|
||||||
|
parse_u8,
|
||||||
|
tag(";"),
|
||||||
|
parse_u8,
|
||||||
|
tag(";"),
|
||||||
|
parse_u8,
|
||||||
|
tag("m"),
|
||||||
|
),
|
||||||
|
|(_, val1, _, val2, _, val3, _, val4, _, val5, _)| {
|
||||||
|
let mode = Vec::from_slice(&[val1, val2, val3, val4, val5])
|
||||||
|
.expect("Vec::from_slice should allocate sufficient size");
|
||||||
|
AnsiSequence::SetGraphicsMode(mode)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
);
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
named!(
|
fn graphics_mode(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
cursor_forward<&str, AnsiSequence>,
|
alt((
|
||||||
do_parse!(
|
graphics_mode1,
|
||||||
tag!("[") >>
|
graphics_mode2,
|
||||||
am: parse_def_cursor_int >>
|
graphics_mode3,
|
||||||
tag!("C") >>
|
graphics_mode4,
|
||||||
(AnsiSequence::CursorForward(am))
|
graphics_mode5,
|
||||||
|
))
|
||||||
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_mode(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
|
map(delimited(tag("[="), parse_u8, tag("h")), |val| {
|
||||||
|
AnsiSequence::SetMode(val)
|
||||||
|
})
|
||||||
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_mode(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
|
map(delimited(tag("[="), parse_u8, tag("l")), |val| {
|
||||||
|
AnsiSequence::ResetMode(val)
|
||||||
|
})
|
||||||
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_top_and_bottom(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
|
map(
|
||||||
|
(tag("["), parse_u32, tag(";"), parse_u32, tag("r")),
|
||||||
|
|(_, x, _, y, _)| AnsiSequence::SetTopAndBottom(x, y),
|
||||||
)
|
)
|
||||||
);
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
named!(
|
fn erase_line_to_end(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
cursor_backward<&str, AnsiSequence>,
|
map(alt((tag("[K"), tag("[0K"))), |_| {
|
||||||
do_parse!(
|
AnsiSequence::EraseLineToEnd
|
||||||
tag!("[") >>
|
})
|
||||||
am: parse_def_cursor_int >>
|
.parse(input)
|
||||||
tag!("D") >>
|
}
|
||||||
(AnsiSequence::CursorBackward(am))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
named!(
|
fn erase_screen_to_end(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
graphics_mode1<&str, AnsiSequence>,
|
map(alt((tag("[J"), tag("[0J"))), |_| {
|
||||||
do_parse!(
|
AnsiSequence::EraseScreenToEnd
|
||||||
tag!("[") >>
|
})
|
||||||
val: parse_int >>
|
.parse(input)
|
||||||
tag!("m") >>
|
}
|
||||||
val: expr_res!(val.try_into()) >>
|
|
||||||
conv: expr_res!(Vec::from_slice(&[val])) >>
|
|
||||||
(AnsiSequence::SetGraphicsMode(conv))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
named!(
|
tag_parser!(
|
||||||
graphics_mode2<&str, AnsiSequence>,
|
erase_screen_from_start,
|
||||||
do_parse!(
|
"[1J",
|
||||||
tag!("[") >>
|
AnsiSequence::EraseScreenFromStart
|
||||||
val1: parse_int >>
|
|
||||||
tag!(";") >>
|
|
||||||
val2: parse_int >>
|
|
||||||
tag!("m") >>
|
|
||||||
val1: expr_res!(val1.try_into()) >>
|
|
||||||
val2: expr_res!(val2.try_into()) >>
|
|
||||||
conv: expr_res!(Vec::from_slice(&[
|
|
||||||
val1,
|
|
||||||
val2,
|
|
||||||
])) >>
|
|
||||||
(AnsiSequence::SetGraphicsMode(conv))
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
tag_parser!(
|
||||||
named!(
|
erase_line_from_start,
|
||||||
graphics_mode3<&str, AnsiSequence>,
|
"[1K",
|
||||||
do_parse!(
|
AnsiSequence::EraseLineFromStart
|
||||||
tag!("[") >>
|
|
||||||
val1: parse_int >>
|
|
||||||
tag!(";") >>
|
|
||||||
val2: parse_int >>
|
|
||||||
tag!(";") >>
|
|
||||||
val3: parse_int >>
|
|
||||||
tag!("m") >>
|
|
||||||
val1: expr_res!(val1.try_into()) >>
|
|
||||||
val2: expr_res!(val2.try_into()) >>
|
|
||||||
val3: expr_res!(val3.try_into()) >>
|
|
||||||
conv: expr_res!(Vec::from_slice(&[
|
|
||||||
val1,
|
|
||||||
val2,
|
|
||||||
val3,
|
|
||||||
])) >>
|
|
||||||
(AnsiSequence::SetGraphicsMode(conv))
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
tag_parser!(cursor_up_scroll, "[ M", AnsiSequence::CursorUpScroll);
|
||||||
named!(
|
tag_parser!(erase_line, "[2K", AnsiSequence::EraseLine);
|
||||||
graphics_mode4<&str, AnsiSequence>,
|
tag_parser!(cursor_home, "[H", AnsiSequence::CursorHome);
|
||||||
do_parse!(
|
tag_parser!(request_cursor_pos, "[6n", AnsiSequence::RequestCursorPos);
|
||||||
tag!("[m") >>
|
|
||||||
(AnsiSequence::SetGraphicsMode(Vec::new()))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
named!(
|
|
||||||
graphics_mode5<&str, AnsiSequence>,
|
|
||||||
do_parse!(
|
|
||||||
tag!("[") >>
|
|
||||||
val1: parse_int >>
|
|
||||||
tag!(";") >>
|
|
||||||
val2: parse_int >>
|
|
||||||
tag!(";") >>
|
|
||||||
val3: parse_int >>
|
|
||||||
tag!(";") >>
|
|
||||||
val4: parse_int >>
|
|
||||||
tag!(";") >>
|
|
||||||
val5: parse_int >>
|
|
||||||
tag!("m") >>
|
|
||||||
val1: expr_res!(val1.try_into()) >>
|
|
||||||
val2: expr_res!(val2.try_into()) >>
|
|
||||||
val3: expr_res!(val3.try_into()) >>
|
|
||||||
val4: expr_res!(val4.try_into()) >>
|
|
||||||
val5: expr_res!(val5.try_into()) >>
|
|
||||||
conv: expr_res!(Vec::from_slice(&[
|
|
||||||
val1,
|
|
||||||
val2,
|
|
||||||
val3,
|
|
||||||
val4,
|
|
||||||
val5,
|
|
||||||
])) >>
|
|
||||||
(AnsiSequence::SetGraphicsMode(conv))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
named!(
|
|
||||||
graphics_mode<&str, AnsiSequence>,
|
|
||||||
alt!(
|
|
||||||
graphics_mode1
|
|
||||||
| graphics_mode2
|
|
||||||
| graphics_mode3
|
|
||||||
| graphics_mode4
|
|
||||||
| graphics_mode5
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
named!(
|
|
||||||
set_mode<&str, AnsiSequence>,
|
|
||||||
do_parse!(
|
|
||||||
tag!("[=") >>
|
|
||||||
mode: parse_int >>
|
|
||||||
conv: expr_res!(mode.try_into()) >>
|
|
||||||
tag!("h") >>
|
|
||||||
(AnsiSequence::SetMode(conv))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
named!(
|
|
||||||
reset_mode<&str, AnsiSequence>,
|
|
||||||
do_parse!(
|
|
||||||
tag!("[=") >>
|
|
||||||
mode: parse_int >>
|
|
||||||
conv: expr_res!(mode.try_into()) >>
|
|
||||||
tag!("l") >>
|
|
||||||
(AnsiSequence::ResetMode(conv))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
named!(
|
|
||||||
set_top_and_bottom<&str, AnsiSequence>,
|
|
||||||
do_parse!(
|
|
||||||
tag!("[") >>
|
|
||||||
x: parse_int >>
|
|
||||||
tag!(";") >>
|
|
||||||
y: parse_int >>
|
|
||||||
tag!("r") >>
|
|
||||||
(AnsiSequence::SetTopAndBottom(x, y))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
tag_parser!(cursor_save, "[s", AnsiSequence::CursorSave);
|
tag_parser!(cursor_save, "[s", AnsiSequence::CursorSave);
|
||||||
tag_parser!(cursor_restore, "[u", AnsiSequence::CursorRestore);
|
tag_parser!(cursor_restore, "[u", AnsiSequence::CursorRestore);
|
||||||
tag_parser!(erase_display, "[2J", AnsiSequence::EraseDisplay);
|
tag_parser!(erase_screen, "[2J", AnsiSequence::EraseScreen);
|
||||||
tag_parser!(erase_line, "[K", AnsiSequence::EraseLine);
|
|
||||||
tag_parser!(hide_cursor, "[?25l", AnsiSequence::HideCursor);
|
tag_parser!(hide_cursor, "[?25l", AnsiSequence::HideCursor);
|
||||||
tag_parser!(show_cursor, "[?25h", AnsiSequence::ShowCursor);
|
tag_parser!(show_cursor, "[?25h", AnsiSequence::ShowCursor);
|
||||||
tag_parser!(cursor_to_app, "[?1h", AnsiSequence::CursorToApp);
|
tag_parser!(cursor_to_app, "[?1h", AnsiSequence::CursorToApp);
|
||||||
@@ -276,66 +250,75 @@ tag_parser!(set_g1_graph, ")2", AnsiSequence::SetG1AltAndSpecialGraph);
|
|||||||
tag_parser!(set_single_shift2, "N", AnsiSequence::SetSingleShift2);
|
tag_parser!(set_single_shift2, "N", AnsiSequence::SetSingleShift2);
|
||||||
tag_parser!(set_single_shift3, "O", AnsiSequence::SetSingleShift3);
|
tag_parser!(set_single_shift3, "O", AnsiSequence::SetSingleShift3);
|
||||||
|
|
||||||
named!(
|
fn combined(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
combined<&str, AnsiSequence>,
|
// `alt` only supports up to 21 parsers, and nom doesn't seem to
|
||||||
alt!(
|
// have an alternative with higher variability.
|
||||||
escape
|
// So we simply nest them.
|
||||||
| cursor_pos
|
alt((
|
||||||
| cursor_up
|
alt((
|
||||||
| cursor_down
|
escape,
|
||||||
| cursor_forward
|
cursor_pos,
|
||||||
| cursor_backward
|
cursor_up,
|
||||||
| cursor_save
|
cursor_down,
|
||||||
| cursor_restore
|
cursor_right,
|
||||||
| erase_display
|
cursor_left,
|
||||||
| erase_line
|
cursor_save,
|
||||||
| graphics_mode
|
cursor_restore,
|
||||||
| set_mode
|
erase_screen,
|
||||||
| reset_mode
|
erase_line,
|
||||||
| hide_cursor
|
graphics_mode,
|
||||||
| show_cursor
|
set_mode,
|
||||||
| cursor_to_app
|
reset_mode,
|
||||||
| set_new_line_mode
|
hide_cursor,
|
||||||
| set_col_132
|
show_cursor,
|
||||||
| set_smooth_scroll
|
cursor_to_app,
|
||||||
| set_reverse_video
|
set_new_line_mode,
|
||||||
| set_origin_rel
|
set_col_132,
|
||||||
| set_auto_wrap
|
set_smooth_scroll,
|
||||||
| set_auto_repeat
|
set_reverse_video,
|
||||||
| set_interlacing
|
set_origin_rel,
|
||||||
| set_linefeed
|
)),
|
||||||
| set_cursorkey
|
alt((
|
||||||
| set_vt52
|
set_auto_wrap,
|
||||||
| set_col80
|
set_auto_repeat,
|
||||||
| set_jump_scroll
|
set_interlacing,
|
||||||
| set_normal_video
|
set_linefeed,
|
||||||
| set_origin_abs
|
set_cursorkey,
|
||||||
| reset_auto_wrap
|
set_vt52,
|
||||||
| reset_auto_repeat
|
set_col80,
|
||||||
| reset_interlacing
|
set_jump_scroll,
|
||||||
| set_top_and_bottom
|
set_normal_video,
|
||||||
| set_alternate_keypad
|
set_origin_abs,
|
||||||
| set_numeric_keypad
|
reset_auto_wrap,
|
||||||
| set_uk_g0
|
reset_auto_repeat,
|
||||||
| set_uk_g1
|
reset_interlacing,
|
||||||
| set_us_g0
|
set_top_and_bottom,
|
||||||
| set_us_g1
|
set_alternate_keypad,
|
||||||
| set_g0_special
|
set_numeric_keypad,
|
||||||
| set_g1_special
|
set_uk_g0,
|
||||||
| set_g0_alternate
|
set_uk_g1,
|
||||||
| set_g1_alternate
|
set_us_g0,
|
||||||
| set_g0_graph
|
set_us_g1,
|
||||||
| set_g1_graph
|
set_g0_special,
|
||||||
| set_single_shift2
|
)),
|
||||||
| set_single_shift3
|
set_g1_special,
|
||||||
)
|
set_g0_alternate,
|
||||||
);
|
set_g1_alternate,
|
||||||
|
set_g0_graph,
|
||||||
|
set_g1_graph,
|
||||||
|
set_single_shift2,
|
||||||
|
set_single_shift3,
|
||||||
|
request_cursor_pos,
|
||||||
|
cursor_home,
|
||||||
|
erase_line_from_start,
|
||||||
|
erase_screen_from_start,
|
||||||
|
erase_screen_to_end,
|
||||||
|
erase_line_to_end,
|
||||||
|
cursor_up_scroll,
|
||||||
|
))
|
||||||
|
.parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
named!(
|
pub fn parse_escape(input: &str) -> IResult<&str, AnsiSequence> {
|
||||||
pub parse_escape<&str, AnsiSequence>,
|
preceded(tag("\u{1b}"), combined).parse(input)
|
||||||
do_parse!(
|
}
|
||||||
tag!("\u{1b}") >>
|
|
||||||
seq: combined >>
|
|
||||||
(seq)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
@@ -44,6 +44,7 @@ macro_rules! test_def_val_parser {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_parser!(get_cursor_pos, "\u{1b}[6n");
|
||||||
test_def_val_parser!(cursor_pos_default, "\u{1b}[H");
|
test_def_val_parser!(cursor_pos_default, "\u{1b}[H");
|
||||||
test_def_val_parser!(cursor_pos, "\u{1b}[10;5H");
|
test_def_val_parser!(cursor_pos, "\u{1b}[10;5H");
|
||||||
test_def_val_parser!(cursor_up_default, "\u{1b}[A");
|
test_def_val_parser!(cursor_up_default, "\u{1b}[A");
|
||||||
|
Reference in New Issue
Block a user