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);
}
} }
} }
@ -177,10 +190,15 @@ 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 => {
self.style = TerminalStyle::default();
self.invert = false;
}
1 => self.style = self.style.add(TerminalStyle::bold(true)), 1 => self.style = self.style.add(TerminalStyle::bold(true)),
3 => self.style = self.style.add(TerminalStyle::italic(true)), 3 => self.style = self.style.add(TerminalStyle::italic(true)),
4 => self.style = self.style.add(TerminalStyle::underline(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)),
@ -215,7 +233,6 @@ impl Perform for PerfAtom {
_ => {} _ => {}
} }
}, },
48 => { 48 => {
let x = piter.next().unwrap(); let x = piter.next().unwrap();
match x[0] { match x[0] {
@ -235,40 +252,55 @@ impl Perform for PerfAtom {
_ => {} _ => {}
} }
}, }
'@' => {
'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; }
'E' => {
self.cursor.x = 0; self.cursor.x = 0;
self.cursor.y += piter.next().unwrap()[0] as i16; }
}
'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' => {
if self.cursor.x >= self.term_width {
self.cursor.y += 1;
}
self.cursor.x = 0;
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;
}
}
_ => {} _ => {}
} }
@ -359,13 +400,6 @@ impl Perform for PerfAtom {
intermediates, ignore, byte intermediates, ignore, byte
); );
*/ */
match byte {
_ => {}
}
} }
} }