diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2020-05-31 22:37:06 +0300 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2020-05-31 22:37:06 +0300 |
commit | 049175e743d4066a87b957f168d710992102558c (patch) | |
tree | f64939d01355d3ae80b7c994bda771b0e681b4cc /src/terminal | |
parent | bee1baedb257d9f7a983b2ade1c6cad608454cd5 (diff) |
pager: fix filter invocation and ansi parsing
Diffstat (limited to 'src/terminal')
-rw-r--r-- | src/terminal/cells.rs | 137 |
1 files changed, 117 insertions, 20 deletions
diff --git a/src/terminal/cells.rs b/src/terminal/cells.rs index 81f8b295..ccdbca4f 100644 --- a/src/terminal/cells.rs +++ b/src/terminal/cells.rs @@ -1842,7 +1842,8 @@ pub mod ansi { use super::{Attr, Cell, CellBuffer, Color}; /// Create a `CellBuffer` from a string slice containing ANSI escape codes. pub fn ansi_to_cellbuffer(s: &str) -> Option<CellBuffer> { - let mut buf: Vec<Cell> = Vec::with_capacity(2048); + let mut bufs: Vec<Vec<Cell>> = Vec::with_capacity(2048); + let mut row: Vec<Cell> = Vec::with_capacity(2048); enum State { Start, @@ -1853,7 +1854,7 @@ pub mod ansi { use State::*; let mut rows = 0; - let mut cols = 0; + let mut max_cols = 0; let mut current_fg = Color::Default; let mut current_bg = Color::Default; let mut current_attrs = Attr::DEFAULT; @@ -1863,7 +1864,11 @@ pub mod ansi { cur_cell = Cell::default(); state = State::Start; let mut chars = l.chars().peekable(); - cols = 0; + if rows > 0 { + max_cols = std::cmp::max(row.len(), max_cols); + bufs.push(row); + row = Vec::with_capacity(2048); + } rows += 1; 'line_loop: loop { let c = chars.next(); @@ -1882,10 +1887,8 @@ pub mod ansi { cur_cell.set_fg(current_fg); cur_cell.set_bg(current_bg); cur_cell.set_attrs(current_attrs); - buf.push(cur_cell); + row.push(cur_cell); cur_cell = Cell::default(); - - cols += 1; } (Csi, 'm') => { /* Reset styles */ @@ -1894,39 +1897,53 @@ pub mod ansi { current_attrs = Attr::DEFAULT; state = Start; } - (Csi, '0'..='8') if chars.peek() == Some(&'m') => { - match chars.next() { - Some('0') => { + (Csi, '0') if chars.peek() == Some(&'0') => { + current_attrs = Attr::DEFAULT; + chars.next(); + let next = chars.next(); + if next == Some('m') { + state = Start; + } else if next != Some(';') { + return None; + } + } + (Csi, c @ '0'..='8') if chars.peek() == Some(&'m') => { + chars.next(); + state = Start; + match c { + '0' => { //Reset all attributes current_fg = Color::Default; current_bg = Color::Default; current_attrs = Attr::DEFAULT; - state = Start; } - Some('1') => { + '1' => { current_attrs.set(Attr::BOLD, true); } - Some('2') => { + '2' => { current_attrs.set(Attr::DIM, true); } - Some('3') => { + '3' => { current_attrs.set(Attr::ITALICS, true); } - Some('4') => { + '4' => { current_attrs.set(Attr::UNDERLINE, true); } - Some('5') => { + '5' => { current_attrs.set(Attr::BLINK, true); } - Some('7') => { + '7' => { current_attrs.set(Attr::REVERSE, true); } - Some('8') => { + '8' => { current_attrs.set(Attr::HIDDEN, true); } _ => return None, } } + (Csi, '0') => { + continue; + } (Csi, '2') => { match (chars.next(), chars.next()) { (Some('2'), Some('m')) => { @@ -1961,8 +1978,20 @@ pub mod ansi { /* Next arguments are 5;n or 2;r;g;b */ continue; } + chars.next(); return None; } + Some('9') => { + current_fg = Color::Default; + /* default foreground color */ + let next = chars.next(); + if next == Some('m') { + state = Start; + } else if next != Some(';') { + return None; + } + continue; + } Some(c) if c >= '0' && c < '8' => { current_fg = Color::from_byte(c as u8 - 0x30); if chars.next() != Some('m') { @@ -1984,6 +2013,17 @@ pub mod ansi { } return None; } + Some('9') => { + /* default background color */ + current_bg = Color::Default; + let next = chars.next(); + if next == Some('m') { + state = Start; + } else if next != Some(';') { + return None; + } + continue; + } Some(c) if c >= '0' && c < '8' => { current_bg = Color::from_byte(c as u8 - 0x30); if chars.next() != Some('m') { @@ -1994,6 +2034,44 @@ pub mod ansi { _ => return None, } } + (Csi, '9') => { + match chars.next() { + Some('0') => current_fg = Color::Black, + Some('1') => current_fg = Color::Red, + Some('2') => current_fg = Color::Green, + Some('3') => current_fg = Color::Yellow, + Some('4') => current_fg = Color::Blue, + Some('5') => current_fg = Color::Magenta, + Some('6') => current_fg = Color::Cyan, + Some('7') => current_fg = Color::White, + _ => {}, + } + let next = chars.next(); + if next != Some('m') { + //debug!(next); + } + state = Start; + } + (Csi, '1') if chars.peek() == Some(&'0') => { + chars.next(); + match chars.next() { + Some('0') => current_bg = Color::Black, + Some('1') => current_bg = Color::Red, + Some('2') => current_bg = Color::Green, + Some('3') => current_bg = Color::Yellow, + Some('4') => current_bg = Color::Blue, + Some('5') => current_bg = Color::Magenta, + Some('6') => current_bg = Color::Cyan, + Some('7') => current_bg = Color::White, + _ => {}, + } + let next = chars.next(); + if next != Some('m') { + //debug!(next); + } + + state = Start; + } (SetFg, '5') => { if chars.next() != Some(';') { return None; @@ -2098,13 +2176,32 @@ pub mod ansi { } } } - if buf.len() != rows * cols { - debug!("rows: {} cols: {}, buf.len() = {}", rows, cols, buf.len()); + max_cols = std::cmp::max(row.len(), max_cols); + bufs.push(row); + let mut buf: Vec<Cell> = Vec::with_capacity(max_cols * bufs.len()); + for l in bufs { + let row_len = l.len(); + buf.extend(l.into_iter()); + if row_len < max_cols { + for _ in row_len..max_cols { + buf.push(Cell::default()); + } + } + } + + if buf.len() != rows * max_cols { + debug!( + "BUG: rows: {} cols: {} = {}, but buf.len() = {}", + rows, + max_cols, + rows * max_cols, + buf.len() + ); } Some(CellBuffer { buf, rows, - cols, + cols: max_cols, growable: false, ascii_drawing: false, }) |