63 lines
2.3 KiB
Rust
63 lines
2.3 KiB
Rust
use nom::{
|
|
branch::alt,
|
|
bytes::complete::{tag, take_till, take_till1},
|
|
combinator::eof,
|
|
error::Error,
|
|
multi::fold_many0,
|
|
sequence::{pair, tuple},
|
|
Err, Parser,
|
|
};
|
|
|
|
enum AnsiFrag<'l> {
|
|
Lit(&'l str),
|
|
Special(&'l str),
|
|
}
|
|
use AnsiFrag::Special;
|
|
|
|
pub fn parse_ansi_markup(i: &str) -> Result<String, Err<Error<&str>>> {
|
|
pair(
|
|
fold_many0(
|
|
alt((
|
|
take_till1(|c| c == '<').map(AnsiFrag::Lit),
|
|
tuple((tag("<"), take_till(|c| c == '>'), tag(">")))
|
|
.map(|t| AnsiFrag::Special(t.1)),
|
|
)),
|
|
|| "".to_owned(),
|
|
|a, r| {
|
|
a + match r {
|
|
AnsiFrag::Lit(s) => &s,
|
|
Special(s) if s == "reset" => "\x1b[0m",
|
|
Special(s) if s == "bold" => "\x1b[1m",
|
|
Special(s) if s == "under" => "\x1b[4m",
|
|
Special(s) if s == "strike" => "\x1b[9m",
|
|
Special(s) if s == "nounder" => "\x1b[24m",
|
|
Special(s) if s == "black" => "\x1b[30m",
|
|
Special(s) if s == "red" => "\x1b[31m",
|
|
Special(s) if s == "green" => "\x1b[32m",
|
|
Special(s) if s == "yellow" => "\x1b[33m",
|
|
Special(s) if s == "blue" => "\x1b[34m",
|
|
Special(s) if s == "magenta" => "\x1b[35m",
|
|
Special(s) if s == "cyan" => "\x1b[36m",
|
|
Special(s) if s == "white" => "\x1b[37m",
|
|
Special(s) if s == "bgblack" => "\x1b[40m",
|
|
Special(s) if s == "bgred" => "\x1b[41m",
|
|
Special(s) if s == "bggreen" => "\x1b[42m",
|
|
Special(s) if s == "bgyellow" => "\x1b[43m",
|
|
Special(s) if s == "bgblue" => "\x1b[44m",
|
|
Special(s) if s == "bgmagenta" => "\x1b[45m",
|
|
Special(s) if s == "bgcyan" => "\x1b[46m",
|
|
Special(s) if s == "bgwhite" => "\x1b[47m",
|
|
Special(s) if s == "lt" => "<",
|
|
Special(r) => panic!("Unknown ansi type {}", r),
|
|
}
|
|
},
|
|
),
|
|
eof,
|
|
)(i)
|
|
.map(|(_, (r, _))| r)
|
|
}
|
|
|
|
pub fn parse_ansi_markup_escape(i: &str) -> Result<String, Err<Error<&str>>> {
|
|
parse_ansi_markup(i).map(|o| o.replace('\x1b', "\\e"))
|
|
}
|