improve ansi parsing

This commit is contained in:
Michael Sippel 2021-11-07 17:42:36 +01:00
parent 05a189a2bb
commit 4ad8316636
Signed by: senvas
GPG key ID: F96CF119C34B64A6

View file

@ -26,7 +26,8 @@ pub fn read_ansi_from<R: Read + Unpin>(ansi_reader: &mut R, port: InnerViewPort<
let mut performer = PerfAtom { let mut performer = PerfAtom {
cursor: Point2::new(0, 0), cursor: Point2::new(0, 0),
style: TerminalStyle::default(), style: TerminalStyle::default(),
term_width: 180, invert: false,
term_width: 80,
cursor_stack: Vec::new(), cursor_stack: Vec::new(),
@ -62,7 +63,6 @@ pub fn read_ansi_from<R: Read + Unpin>(ansi_reader: &mut R, port: InnerViewPort<
} }
} }
struct ColorPalett { struct ColorPalett {
black: (u8, u8, u8), black: (u8, u8, u8),
red: (u8, u8, u8), red: (u8, u8, u8),
@ -80,7 +80,7 @@ struct PerfAtom {
cursor: Point2<i16>, cursor: Point2<i16>,
style: TerminalStyle, style: TerminalStyle,
invert: bool,
cursor_stack: Vec<Point2<i16>>, cursor_stack: Vec<Point2<i16>>,
buf: IndexBuffer<Point2<i16>, TerminalAtom>, buf: IndexBuffer<Point2<i16>, TerminalAtom>,
@ -88,31 +88,41 @@ struct PerfAtom {
impl PerfAtom { impl PerfAtom {
fn write_atom(&mut self, pos: Point2<i16>, atom: Option<TerminalAtom>) { fn write_atom(&mut self, pos: Point2<i16>, atom: Option<TerminalAtom>) {
if let Some(a) = atom { if let Some(mut a) = atom {
self.buf.insert(pos, a); self.buf.insert(pos, a);
} else { } else {
self.buf.remove(pos); self.buf.remove(pos);
} }
} }
fn get_style(&self) -> TerminalStyle {
let mut style = self.style;
if self.invert {
style.fg_color = Some(self.style.bg_color.unwrap_or(self.colors.black));
style.bg_color = Some(self.style.fg_color.unwrap_or(self.colors.white));
}
style
}
fn cursor_up(&mut self, n: usize) {
}
fn cursor_down(&mut self, n: usize) {
}
} }
impl Perform for PerfAtom { impl Perform for PerfAtom {
fn print(&mut self, c: char) { fn print(&mut self, c: char) {
//eprintln!("[print] {:?}", c); self.write_atom(self.cursor, Some(TerminalAtom::new(c, self.get_style())));
self.write_atom(
self.cursor,
Some(TerminalAtom::new(c, self.style))
);
self.cursor.x += 1; self.cursor.x += 1;
if self.cursor.x > self.term_width { if self.cursor.x >= self.term_width {
self.cursor.x = 0; self.cursor.x = 0;
self.cursor.y += 1; self.cursor.y += 1;
} }
} }
fn execute(&mut self, byte: u8) { fn execute(&mut self, byte: u8) {
//eprintln!("[execute] {:02x}", byte);
match byte { match byte {
// linefeed // linefeed
b'\n' => { b'\n' => {
@ -138,7 +148,10 @@ impl Perform for PerfAtom {
self.cursor.x = self.term_width - 1; self.cursor.x = self.term_width - 1;
} }
} }
_ => {}
_ => {
eprintln!("unhandled execute byte {:02x}", byte);
}
} }
} }
@ -148,7 +161,7 @@ impl Perform for PerfAtom {
"[hook] params={:?}, intermediates={:?}, ignore={:?}, char={:?}", "[hook] params={:?}, intermediates={:?}, ignore={:?}, char={:?}",
params, intermediates, ignore, c params, intermediates, ignore, c
); );
*/ */
} }
fn put(&mut self, byte: u8) { fn put(&mut self, byte: u8) {
@ -177,98 +190,117 @@ impl Perform for PerfAtom {
// Set SGR // Set SGR
'm' => while let Some(n) = piter.next() { 'm' => while let Some(n) = piter.next() {
match n[0] { match n[0] {
0 => self.style = TerminalStyle::default(), 0 => {
1 => self.style = self.style.add(TerminalStyle::bold(true)), self.style = TerminalStyle::default();
3 => self.style = self.style.add(TerminalStyle::italic(true)), self.invert = false;
4 => self.style = self.style.add(TerminalStyle::underline(true)), }
1 => self.style = self.style.add(TerminalStyle::bold(true)),
3 => self.style = self.style.add(TerminalStyle::italic(true)),
4 => self.style = self.style.add(TerminalStyle::underline(true)),
7 => self.invert = true,
27 => self.invert = false,
30 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.black)), 30 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.black)),
40 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.black)), 40 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.black)),
31 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.red)), 31 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.red)),
41 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.red)), 41 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.red)),
32 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.green)), 32 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.green)),
42 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.green)), 42 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.green)),
33 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.yellow)), 33 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.yellow)),
43 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.yellow)), 43 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.yellow)),
34 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.blue)), 34 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.blue)),
44 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.blue)), 44 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.blue)),
35 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.magenta)), 35 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.magenta)),
45 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.magenta)), 45 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.magenta)),
36 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.cyan)), 36 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.cyan)),
46 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.cyan)), 46 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.cyan)),
37 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.white)), 37 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.white)),
47 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.white)), 47 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.white)),
38 => { 38 => {
let x = piter.next().unwrap(); let x = piter.next().unwrap();
match x[0] { match x[0] {
2 => { 2 => {
let r = piter.next().unwrap(); let r = piter.next().unwrap();
let g = piter.next().unwrap(); let g = piter.next().unwrap();
let b = piter.next().unwrap(); let b = piter.next().unwrap();
self.style = self.style.add(TerminalStyle::fg_color((r[0] as u8, g[0] as u8, b[30] as u8))) self.style = self.style.add(TerminalStyle::fg_color((r[0] as u8, g[0] as u8, b[30] as u8)))
}, },
5 => { 5 => {
let v = piter.next().unwrap(); let v = piter.next().unwrap();
self.style = self.style.add(TerminalStyle::fg_color(ansi_colours::rgb_from_ansi256(v[0] as u8))) self.style = self.style.add(TerminalStyle::fg_color(ansi_colours::rgb_from_ansi256(v[0] as u8)))
}, },
_ => {} _ => {}
} }
}, },
48 => {
48 => { let x = piter.next().unwrap();
let x = piter.next().unwrap(); match x[0] {
match x[0] { 2 => {
2 => { let r = piter.next().unwrap();
let r = piter.next().unwrap(); let g = piter.next().unwrap();
let g = piter.next().unwrap(); let b = piter.next().unwrap();
let b = piter.next().unwrap(); self.style = self.style.add(TerminalStyle::bg_color((r[0] as u8, g[0] as u8, b[30] as u8)))
self.style = self.style.add(TerminalStyle::bg_color((r[0] as u8, g[0] as u8, b[30] as u8))) },
}, 5 => {
5 => { let v = piter.next().unwrap();
let v = piter.next().unwrap(); self.style = self.style.add(TerminalStyle::bg_color(ansi_colours::rgb_from_ansi256(v[0] as u8)))
self.style = self.style.add(TerminalStyle::bg_color(ansi_colours::rgb_from_ansi256(v[0] as u8))) },
}, _ => {}
_ => {} }
} },
},
_ => {} _ => {}
} }
}, }
'@' => {
'H' => { for x in self.cursor.x .. self.term_width {
if let Some(y) = piter.next() { self.cursor.y = y[0] as i16 - 1 }; self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.style)));
if let Some(x) = piter.next() { self.cursor.x = x[0] as i16 - 1 }; }
}
//eprintln!("cursor at {:?}", self.cursor); 'A' => {
}, self.cursor.y -= piter.next().unwrap_or(&[1])[0] as i16;
}
'A' => { self.cursor.y -= piter.next().unwrap()[0] as i16; } 'B' => {
'B' => { self.cursor.y += piter.next().unwrap()[0] as i16; } self.cursor.y += piter.next().unwrap_or(&[1])[0] as i16;
'C' => { self.cursor.x += piter.next().unwrap()[0] as i16; } if self.cursor.x >= self.term_width {
'D' => { self.cursor.x -= piter.next().unwrap()[0] as i16; } self.cursor.x = 0;
}
}
'C' => {
self.cursor.x += piter.next().unwrap_or(&[1])[0] as i16;
if self.cursor.x >= self.term_width {
self.cursor.x = 0;
}
}
'D' => {
self.cursor.x -= piter.next().unwrap_or(&[1])[0] as i16;
if self.cursor.x < 0 {
self.cursor.x = self.term_width - 1;
self.cursor.y -= 1;
}
}
'd' => {
self.cursor.y = piter.next().unwrap_or(&[1])[0] as i16 - 1;
}
'E' => { 'E' => {
if self.cursor.x >= self.term_width {
self.cursor.y += 1;
}
self.cursor.x = 0; self.cursor.x = 0;
self.cursor.y += piter.next().unwrap()[0] as i16; self.cursor.y += piter.next().unwrap_or(&[1])[0] as i16;
} }
'F' => { 'F' => {
self.cursor.x = 0; self.cursor.x = 0;
self.cursor.y -= piter.next().unwrap()[0] as i16; self.cursor.y -= piter.next().unwrap_or(&[1])[0] as i16;
} }
'G' => { 'G' => {
self.cursor.x = piter.next().unwrap()[0] as i16 - 1; self.cursor.x = piter.next().unwrap()[0] as i16 - 1;
} }
'H' => {
's' => { if let Some(y) = piter.next() { self.cursor.y = y[0] as i16 - 1 };
self.cursor_stack.push(self.cursor); if let Some(x) = piter.next() { self.cursor.x = x[0] as i16 - 1 };
} }
'u' => {
if let Some(c) = self.cursor_stack.pop() {
self.cursor = c;
}
}
'J' => { 'J' => {
let x = piter.next().unwrap_or(&[0 as u16; 1]); let x = piter.next().unwrap_or(&[0 as u16; 1]);
match x[0] { match x[0] {
@ -311,35 +343,36 @@ impl Perform for PerfAtom {
self.write_atom(Point2::new(x, y), None); self.write_atom(Point2::new(x, y), None);
} }
} }
self.cursor = Point2::new(0, 0);
} }
// invalid // invalid
_ => {} _ => {}
} }
} }
'K' => { 'K' => {
let x = piter.next().unwrap(); let x = piter.next().unwrap_or(&[0]);
match x[0] { match x[0] {
// clear cursor until end // clear from cursor until end of line
0 => { 0 => {
for x in self.cursor.x .. self.term_width { for x in self.cursor.x .. self.term_width {
self.write_atom(Point2::new(x, self.cursor.y), None); self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.get_style())));
} }
}, },
// clear start until cursor // clear from start of line until cursor
1 => { 1 => {
for x in 0 .. self.cursor.x { for x in 0 .. self.cursor.x {
self.write_atom(Point2::new(x, self.cursor.y), None); self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.get_style())));
} }
}, },
// clear entire line // clear entire line
2 => { 2 => {
for x in 0 .. self.term_width { for x in 0 .. self.term_width {
self.write_atom(Point2::new(x, self.cursor.y), None); self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.get_style())));
} }
}, },
@ -347,6 +380,14 @@ impl Perform for PerfAtom {
_ => {} _ => {}
} }
} }
's' => {
self.cursor_stack.push(self.cursor);
}
'u' => {
if let Some(c) = self.cursor_stack.pop() {
self.cursor = c;
}
}
_ => {} _ => {}
} }
@ -358,14 +399,7 @@ impl Perform for PerfAtom {
"[esc_dispatch] intermediates={:?}, ignore={:?}, byte={:02x}", "[esc_dispatch] intermediates={:?}, ignore={:?}, byte={:02x}",
intermediates, ignore, byte intermediates, ignore, byte
); );
*/ */
match byte {
_ => {}
}
} }
} }