Skip to content

Commit

Permalink
link: support soft reset
Browse files Browse the repository at this point in the history
  • Loading branch information
ahaoboy committed Oct 18, 2024
1 parent 210f64b commit 758e4c6
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 46 deletions.
22 changes: 11 additions & 11 deletions ansi2/src/lex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,32 +153,32 @@ pub enum Token {

fn parse_cursor_up(input: &str) -> IResult<&str, Token> {
let (rem, (_, b, _)) = tuple((tag("\x1b["), digit0, tag_no_case("a")))(input)?;
Ok((rem, Token::CursorUp(str::parse(b).unwrap())))
Ok((rem, Token::CursorUp(str::parse(b).unwrap_or(1))))
}

fn parse_cursor_down(input: &str) -> IResult<&str, Token> {
let (rem, (_, b, _)) = tuple((tag("\x1b["), digit0, tag_no_case("b")))(input)?;
Ok((rem, Token::CursorDown(str::parse(b).unwrap())))
Ok((rem, Token::CursorDown(str::parse(b).unwrap_or(1))))
}

fn parse_cursor_forward(input: &str) -> IResult<&str, Token> {
let (rem, (_, b, _)) = tuple((tag("\x1b["), digit0, tag_no_case("c")))(input)?;
Ok((rem, Token::CursorForward(str::parse(b).unwrap())))
Ok((rem, Token::CursorForward(str::parse(b).unwrap_or(1))))
}

fn parse_cursor_back(input: &str) -> IResult<&str, Token> {
let (rem, (_, b, _)) = tuple((tag("\x1b["), digit0, tag_no_case("d")))(input)?;
Ok((rem, Token::CursorBack(str::parse(b).unwrap())))
Ok((rem, Token::CursorBack(str::parse(b).unwrap_or(1))))
}

fn parse_cursor_next_line(input: &str) -> IResult<&str, Token> {
let (rem, (_, b, _)) = tuple((tag("\x1b["), digit0, tag_no_case("e")))(input)?;
Ok((rem, Token::CursorNextLine(str::parse(b).unwrap())))
Ok((rem, Token::CursorNextLine(str::parse(b).unwrap_or(1))))
}

fn parse_cursor_previous_line(input: &str) -> IResult<&str, Token> {
let (rem, (_, b, _)) = tuple((tag("\x1b["), digit0, tag_no_case("f")))(input)?;
Ok((rem, Token::CursorPreviousLine(str::parse(b).unwrap())))
Ok((rem, Token::CursorPreviousLine(str::parse(b).unwrap_or(1))))
}

fn parse_cursor_horizontal(input: &str) -> IResult<&str, Token> {
Expand Down Expand Up @@ -291,7 +291,7 @@ fn parse_color_underline(input: &str) -> IResult<&str, Token> {
let (rem, (_, b, _)) = tuple((tag("\x1b[58;5;"), digit0, tag_no_case("m")))(input)?;
Ok((
rem,
Token::ColorUnderLine(AnsiColor::Color8(str::parse(b).unwrap())),
Token::ColorUnderLine(AnsiColor::Color8(str::parse(b).unwrap_or(1))),
))
}

Expand Down Expand Up @@ -574,8 +574,8 @@ fn parse_link_no_title(input: &str) -> IResult<&str, Token> {
let (rem, (_, _, url, _)) = tuple((
tag("\x1b]8;"),
opt(tag(";")),
take_until("\x1b]8;;\x1b\\"),
tag("\x1b]8;;\x1b\\"),
alt((take_until("\x1b]8;;\x1b\\"), take_until("\x1b[!p"))),
alt((tag("\x1b]8;;\x1b\\"), tag("\x1b[!p"))),
))(input)?;
Ok((rem, Token::Link(url.to_string(), url.to_string())))
}
Expand All @@ -586,8 +586,8 @@ fn parse_link_with_title(input: &str) -> IResult<&str, Token> {
opt(tag(";")),
take_until("\x1b\\"),
tag("\x1b\\"),
take_until("\x1b]8;;\x1b\\"),
tag("\x1b]8;;\x1b\\"),
alt((take_until("\x1b]8;;\x1b\\"), take_until("\x1b[!p"))),
alt((tag("\x1b]8;;\x1b\\"), tag("\x1b[!p"))),
))(input)?;
Ok((rem, Token::Link(url.to_string(), title.to_string())))
}
Expand Down
112 changes: 77 additions & 35 deletions ansi2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pub mod lex;
pub mod svg;
pub mod text;
pub mod theme;
use std::collections::VecDeque;

use lex::{parse_ansi, AnsiColor, Token};

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -70,7 +72,9 @@ impl Canvas {
let mut hide = false;
let max_width = max_width.unwrap_or(usize::MAX);

for i in lex {
let mut q = VecDeque::from(lex);

while let Some(i) = q.pop_front() {
let mut reset_all = || {
bold = false;
dim = false;
Expand Down Expand Up @@ -99,7 +103,7 @@ impl Canvas {
dim,
italic,
underline,
hide
hide,
};
if cur_x >= max_width {
cur_x = 0;
Expand Down Expand Up @@ -193,25 +197,41 @@ impl Canvas {
cur_c = AnsiColor::Color8(front);
cur_bg_c = AnsiColor::Color8(background);
}
Token::Sgr4(reset, ctrl, front, background) => {
Token::Sgr4(reset, ctrl, a, b) => {
if reset == 0 {
reset_all();
}
match ctrl {
0 => reset_all(),
1 => {
bold = true;
cur_c = AnsiColor::Color8(front);
cur_bg_c = AnsiColor::Color8(background);
cur_c = AnsiColor::Color8(a);
cur_bg_c = AnsiColor::Color8(b);
}
5 => {
blink = true;
cur_bg_c = AnsiColor::Color8(front);
blink_c = background;
cur_bg_c = AnsiColor::Color256(a);
blink_c = b;
}
48 => match a {
5 => {
cur_bg_c = AnsiColor::Color256(b);
}
_ => {
cur_bg_c = AnsiColor::Color8(b);
}
},
38 => match a {
5 => {
cur_c = AnsiColor::Color256(b);
}
_ => {
cur_c = AnsiColor::Color8(b);
}
},
_ => {
cur_c = AnsiColor::Color8(front);
cur_bg_c = AnsiColor::Color8(background);
cur_c = AnsiColor::Color8(a);
cur_bg_c = AnsiColor::Color8(b);
}
}
}
Expand All @@ -232,33 +252,46 @@ impl Canvas {
cur_bg_c = AnsiColor::Color8(0);
}

Token::Link(_, title ) => {
for i in title.chars() {
if i == '\n' {
cur_x = 0;
cur_y += 1;
continue;
Token::Link(_, title) => match parse_ansi(&title) {
Ok((_, tokens)) => {
// FIXME: Avoid the influence of styles in link on subsequent characters
q.push_front(Token::ColorReset);
for i in tokens.into_iter().rev() {
underline = true;
q.push_front(i);
}

let node = Node {
char: i,
bg_color: cur_bg_c,
color: cur_c,
bold,
blink,
dim,
italic,
underline: true,
hide
};

if cur_x >= max_width {
cur_x = 0;
cur_y += 1;
}
Err(_) => {
for i in title.chars() {
if i == '\n' {
cur_x = 0;
cur_y += 1;
continue;
}

let node = Node {
char: i,
bg_color: cur_bg_c,
color: cur_c,
bold,
blink,
dim,
italic,
underline: true,
hide,
};

if cur_x >= max_width {
cur_x = 0;
cur_y += 1;
}
set_node(&mut pixels, node, cur_x, cur_y);
cur_x += 1;
}
set_node(&mut pixels, node, cur_x, cur_y);
cur_x += 1;
}
},
Token::CursorHide => {
hide = true;
}
_ => {}
}
Expand Down Expand Up @@ -336,7 +369,8 @@ mod test {

#[test]
fn test_link() {
let s = "\x1b]8;;file:///Users/xxx/src/new-nu-parser/Cargo.toml\x1b\\Cargo.toml\x1b]8;;\x1b";
let s =
"\x1b]8;;file:///Users/xxx/src/new-nu-parser/Cargo.toml\x1b\\Cargo.toml\x1b]8;;\x1b";
let r = parse_ansi(s).unwrap();
println!("{:?}", r);
}
Expand All @@ -361,6 +395,13 @@ mod test {
println!("{:?}", r);
}

#[test]
fn test_link_soft_reset() {
let s = "\x1b]8;;http://example.com/softreset\\\x1b[3;31mfoo[!pbar";
let r = parse_ansi(s).unwrap();
println!("{:?}", r);
}

#[test]
fn test_link_no_close() {
let s = "\x1b]8;;http://example.com/foo\x1b\\foo\x1b]8;;http://example.com/foo\x1b\\foo\x1b]8;;\x1b\\ \x1b]8;;http://example.com/foo\x1b\\foo\x1b]8;;http://example.com/bar\x1b\\bar\x1b]8;;\x1b\\";
Expand All @@ -377,7 +418,8 @@ mod test {

#[test]
fn test_style() {
let s = "aaa\x1b[1mbold\x1b[0m \x1b[2mdim\x1b[0m \x1b[3mitalic\x1b[3m \x1b[4munderline\x1b[4m";
let s =
"aaa\x1b[1mbold\x1b[0m \x1b[2mdim\x1b[0m \x1b[3mitalic\x1b[3m \x1b[4munderline\x1b[4m";
let r = parse_ansi(s).unwrap();
println!("{:?}", r);
}
Expand Down

0 comments on commit 758e4c6

Please sign in to comment.