From 4ad83166367b4b1746068d6e63b5d55e8de408f3 Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Sun, 7 Nov 2021 17:42:36 +0100 Subject: [PATCH] improve ansi parsing --- nested/src/terminal/ansi_parser.rs | 246 ++++++++++++++++------------- 1 file changed, 140 insertions(+), 106 deletions(-) diff --git a/nested/src/terminal/ansi_parser.rs b/nested/src/terminal/ansi_parser.rs index 679aae4..4ec4503 100644 --- a/nested/src/terminal/ansi_parser.rs +++ b/nested/src/terminal/ansi_parser.rs @@ -26,7 +26,8 @@ pub fn read_ansi_from(ansi_reader: &mut R, port: InnerViewPort< let mut performer = PerfAtom { cursor: Point2::new(0, 0), style: TerminalStyle::default(), - term_width: 180, + invert: false, + term_width: 80, cursor_stack: Vec::new(), @@ -62,7 +63,6 @@ pub fn read_ansi_from(ansi_reader: &mut R, port: InnerViewPort< } } - struct ColorPalett { black: (u8, u8, u8), red: (u8, u8, u8), @@ -80,7 +80,7 @@ struct PerfAtom { cursor: Point2, style: TerminalStyle, - + invert: bool, cursor_stack: Vec>, buf: IndexBuffer, TerminalAtom>, @@ -88,31 +88,41 @@ struct PerfAtom { impl PerfAtom { fn write_atom(&mut self, pos: Point2, atom: Option) { - if let Some(a) = atom { + if let Some(mut a) = atom { self.buf.insert(pos, a); } else { 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 { fn print(&mut self, c: char) { - //eprintln!("[print] {:?}", c); - self.write_atom( - self.cursor, - Some(TerminalAtom::new(c, self.style)) - ); + self.write_atom(self.cursor, Some(TerminalAtom::new(c, self.get_style()))); self.cursor.x += 1; - if self.cursor.x > self.term_width { + if self.cursor.x >= self.term_width { self.cursor.x = 0; self.cursor.y += 1; } } fn execute(&mut self, byte: u8) { - //eprintln!("[execute] {:02x}", byte); match byte { // linefeed b'\n' => { @@ -138,7 +148,10 @@ impl Perform for PerfAtom { 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={:?}", params, intermediates, ignore, c ); - */ + */ } fn put(&mut self, byte: u8) { @@ -177,98 +190,117 @@ impl Perform for PerfAtom { // Set SGR 'm' => while let Some(n) = piter.next() { match n[0] { - 0 => self.style = TerminalStyle::default(), - 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)), + 0 => { + self.style = TerminalStyle::default(); + self.invert = false; + } + 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)), - 40 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.black)), - 31 => self.style = self.style.add(TerminalStyle::fg_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)), - 42 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.green)), - 33 => self.style = self.style.add(TerminalStyle::fg_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)), - 44 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.blue)), - 35 => self.style = self.style.add(TerminalStyle::fg_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)), - 46 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.cyan)), - 37 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.white)), - 47 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.white)), + 30 => self.style = self.style.add(TerminalStyle::fg_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)), + 41 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.red)), + 32 => self.style = self.style.add(TerminalStyle::fg_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)), + 43 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.yellow)), + 34 => self.style = self.style.add(TerminalStyle::fg_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)), + 45 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.magenta)), + 36 => self.style = self.style.add(TerminalStyle::fg_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)), + 47 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.white)), - 38 => { - let x = piter.next().unwrap(); - match x[0] { - 2 => { - let r = piter.next().unwrap(); - let g = 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))) - }, - 5 => { - let v = piter.next().unwrap(); - self.style = self.style.add(TerminalStyle::fg_color(ansi_colours::rgb_from_ansi256(v[0] as u8))) - }, - _ => {} - } - }, - - 48 => { - let x = piter.next().unwrap(); - match x[0] { - 2 => { - let r = piter.next().unwrap(); - let g = 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))) - }, - 5 => { - let v = piter.next().unwrap(); - self.style = self.style.add(TerminalStyle::bg_color(ansi_colours::rgb_from_ansi256(v[0] as u8))) - }, - _ => {} - } - }, + 38 => { + let x = piter.next().unwrap(); + match x[0] { + 2 => { + let r = piter.next().unwrap(); + let g = 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))) + }, + 5 => { + let v = piter.next().unwrap(); + self.style = self.style.add(TerminalStyle::fg_color(ansi_colours::rgb_from_ansi256(v[0] as u8))) + }, + _ => {} + } + }, + 48 => { + let x = piter.next().unwrap(); + match x[0] { + 2 => { + let r = piter.next().unwrap(); + let g = 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))) + }, + 5 => { + let v = piter.next().unwrap(); + self.style = self.style.add(TerminalStyle::bg_color(ansi_colours::rgb_from_ansi256(v[0] as u8))) + }, + _ => {} + } + }, _ => {} } - }, - - 'H' => { - if let Some(y) = piter.next() { self.cursor.y = y[0] as i16 - 1 }; - 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()[0] as i16; } - 'B' => { self.cursor.y += piter.next().unwrap()[0] as i16; } - 'C' => { self.cursor.x += piter.next().unwrap()[0] as i16; } - 'D' => { self.cursor.x -= piter.next().unwrap()[0] as i16; } + } + '@' => { + for x in self.cursor.x .. self.term_width { + self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.style))); + } + } + 'A' => { + self.cursor.y -= piter.next().unwrap_or(&[1])[0] as i16; + } + 'B' => { + self.cursor.y += piter.next().unwrap_or(&[1])[0] as i16; + if self.cursor.x >= self.term_width { + 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' => { + if self.cursor.x >= self.term_width { + self.cursor.y += 1; + } 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' => { 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' => { self.cursor.x = piter.next().unwrap()[0] as i16 - 1; } - - 's' => { - self.cursor_stack.push(self.cursor); + 'H' => { + if let Some(y) = piter.next() { self.cursor.y = y[0] as i16 - 1 }; + 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' => { let x = piter.next().unwrap_or(&[0 as u16; 1]); match x[0] { @@ -311,35 +343,36 @@ impl Perform for PerfAtom { self.write_atom(Point2::new(x, y), None); } } + + self.cursor = Point2::new(0, 0); } // invalid _ => {} } - } - + } 'K' => { - let x = piter.next().unwrap(); + let x = piter.next().unwrap_or(&[0]); match x[0] { - // clear cursor until end + // clear from cursor until end of line 0 => { 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 => { 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 2 => { 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}", intermediates, ignore, byte ); - */ - - match byte { - - - - _ => {} - } +*/ } }