improve ansi parsing
This commit is contained in:
parent
05a189a2bb
commit
4ad8316636
1 changed files with 140 additions and 106 deletions
|
@ -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 {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue