You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
344 lines
15 KiB
344 lines
15 KiB
--- git-delta-0.4.4/src/ansi/iterator.rs 2020-08-14 17:36:58.000000000 +0200
|
|
+++ iterator.rs 2020-12-05 22:41:42.578320503 +0100
|
|
@@ -1,7 +1,7 @@
|
|
use core::str::Bytes;
|
|
-
|
|
-use ansi_term;
|
|
-use vte;
|
|
+use std::convert::TryFrom;
|
|
+use std::iter;
|
|
+use vte::{Params, ParamsIter};
|
|
|
|
pub struct AnsiElementIterator<'a> {
|
|
// The input bytes
|
|
@@ -54,11 +54,6 @@
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
- pub fn to_vec(self) -> Vec<Element> {
|
|
- self.collect()
|
|
- }
|
|
-
|
|
- #[allow(dead_code)]
|
|
pub fn dbg(s: &str) {
|
|
for el in AnsiElementIterator::new(s) {
|
|
match el {
|
|
@@ -124,26 +119,23 @@
|
|
}
|
|
}
|
|
|
|
-// Based on https://github.com/alacritty/vte/blob/0310be12d3007e32be614c5df94653d29fcc1a8b/examples/parselog.rs
|
|
+// Based on https://github.com/alacritty/vte/blob/v0.9.0/examples/parselog.rs
|
|
impl vte::Perform for Performer {
|
|
- fn csi_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, c: char) {
|
|
+ fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) {
|
|
if ignore || intermediates.len() > 1 {
|
|
return;
|
|
}
|
|
|
|
- match (c, intermediates.get(0)) {
|
|
- ('m', None) => {
|
|
- if params.is_empty() {
|
|
- // Attr::Reset;
|
|
- } else {
|
|
- self.element = Some(Element::CSI(
|
|
- ansi_term_style_from_sgr_parameters(params),
|
|
- 0,
|
|
- 0,
|
|
- ));
|
|
- }
|
|
+ if let ('m', None) = (c, intermediates.get(0)) {
|
|
+ if params.is_empty() {
|
|
+ // Attr::Reset; TODO: does this need to be handled?
|
|
+ } else {
|
|
+ self.element = Some(Element::CSI(
|
|
+ ansi_term_style_from_sgr_parameters(&mut params.iter()),
|
|
+ 0,
|
|
+ 0,
|
|
+ ));
|
|
}
|
|
- _ => {}
|
|
}
|
|
}
|
|
|
|
@@ -158,7 +150,7 @@
|
|
}
|
|
}
|
|
|
|
- fn hook(&mut self, _params: &[i64], _intermediates: &[u8], _ignore: bool, _c: char) {}
|
|
+ fn hook(&mut self, _params: &Params, _intermediates: &[u8], _ignore: bool, _c: char) {}
|
|
|
|
fn put(&mut self, _byte: u8) {}
|
|
|
|
@@ -173,139 +165,111 @@
|
|
}
|
|
}
|
|
|
|
-// Based on https://github.com/alacritty/alacritty/blob/57c4ac9145a20fb1ae9a21102503458d3da06c7b/alacritty_terminal/src/ansi.rs#L1168
|
|
-fn ansi_term_style_from_sgr_parameters(parameters: &[i64]) -> ansi_term::Style {
|
|
- let mut i = 0;
|
|
+// Based on https://github.com/alacritty/alacritty/blob/9e71002e40d5487c6fa2571a3a3c4f5c8f679334/alacritty_terminal/src/ansi.rs#L1175
|
|
+fn ansi_term_style_from_sgr_parameters(params: &mut ParamsIter<'_>) -> ansi_term::Style {
|
|
let mut style = ansi_term::Style::new();
|
|
- loop {
|
|
- if i >= parameters.len() {
|
|
- break;
|
|
- }
|
|
+ while let Some(param) = params.next() {
|
|
+ match param {
|
|
+ // [0] => Some(Attr::Reset),
|
|
+ [1] => style.is_bold = true,
|
|
+ [2] => style.is_dimmed = true,
|
|
+ [3] => style.is_italic = true,
|
|
+ [4, ..] => style.is_underline = true,
|
|
+ [5] => style.is_blink = true, // blink slow
|
|
+ [6] => style.is_blink = true, // blink fast
|
|
+ [7] => style.is_reverse = true,
|
|
+ [8] => style.is_hidden = true,
|
|
+ [9] => style.is_strikethrough = true,
|
|
+ // [21] => Some(Attr::CancelBold),
|
|
+ // [22] => Some(Attr::CancelBoldDim),
|
|
+ // [23] => Some(Attr::CancelItalic),
|
|
+ // [24] => Some(Attr::CancelUnderline),
|
|
+ // [25] => Some(Attr::CancelBlink),
|
|
+ // [27] => Some(Attr::CancelReverse),
|
|
+ // [28] => Some(Attr::CancelHidden),
|
|
+ // [29] => Some(Attr::CancelStrike),
|
|
+ [30] => style.foreground = Some(ansi_term::Color::Black),
|
|
+ [31] => style.foreground = Some(ansi_term::Color::Red),
|
|
+ [32] => style.foreground = Some(ansi_term::Color::Green),
|
|
+ [33] => style.foreground = Some(ansi_term::Color::Yellow),
|
|
+ [34] => style.foreground = Some(ansi_term::Color::Blue),
|
|
+ [35] => style.foreground = Some(ansi_term::Color::Purple),
|
|
+ [36] => style.foreground = Some(ansi_term::Color::Cyan),
|
|
+ [37] => style.foreground = Some(ansi_term::Color::White),
|
|
+ [38] => {
|
|
+ let mut iter = params.map(|param| param[0]);
|
|
+ if let Some(color) = parse_sgr_color(&mut iter) {
|
|
+ style.foreground = Some(color);
|
|
+ }
|
|
+ }
|
|
+ [38, params @ ..] => {
|
|
+ let rgb_start = if params.len() > 4 { 2 } else { 1 };
|
|
+ let rgb_iter = params[rgb_start..].iter().copied();
|
|
+ let mut iter = iter::once(params[0]).chain(rgb_iter);
|
|
|
|
- match parameters[i] {
|
|
- // 0 => Some(Attr::Reset),
|
|
- 1 => style.is_bold = true,
|
|
- 2 => style.is_dimmed = true,
|
|
- 3 => style.is_italic = true,
|
|
- 4 => style.is_underline = true,
|
|
- 5 => style.is_blink = true, // blink slow
|
|
- 6 => style.is_blink = true, // blink fast
|
|
- 7 => style.is_reverse = true,
|
|
- 8 => style.is_hidden = true,
|
|
- 9 => style.is_strikethrough = true,
|
|
- // 21 => Some(Attr::CancelBold),
|
|
- // 22 => Some(Attr::CancelBoldDim),
|
|
- // 23 => Some(Attr::CancelItalic),
|
|
- // 24 => Some(Attr::CancelUnderline),
|
|
- // 25 => Some(Attr::CancelBlink),
|
|
- // 27 => Some(Attr::CancelReverse),
|
|
- // 28 => Some(Attr::CancelHidden),
|
|
- // 29 => Some(Attr::CancelStrike),
|
|
- 30 => style.foreground = Some(ansi_term::Color::Black),
|
|
- 31 => style.foreground = Some(ansi_term::Color::Red),
|
|
- 32 => style.foreground = Some(ansi_term::Color::Green),
|
|
- 33 => style.foreground = Some(ansi_term::Color::Yellow),
|
|
- 34 => style.foreground = Some(ansi_term::Color::Blue),
|
|
- 35 => style.foreground = Some(ansi_term::Color::Purple),
|
|
- 36 => style.foreground = Some(ansi_term::Color::Cyan),
|
|
- 37 => style.foreground = Some(ansi_term::Color::White),
|
|
- 38 => {
|
|
- let mut start = 0;
|
|
- if let Some(color) = parse_sgr_color(¶meters[i..], &mut start) {
|
|
- i += start;
|
|
+ if let Some(color) = parse_sgr_color(&mut iter) {
|
|
style.foreground = Some(color);
|
|
}
|
|
}
|
|
- // 39 => Some(Attr::Foreground(Color::Named(NamedColor::Foreground))),
|
|
- 40 => style.background = Some(ansi_term::Color::Black),
|
|
- 41 => style.background = Some(ansi_term::Color::Red),
|
|
- 42 => style.background = Some(ansi_term::Color::Green),
|
|
- 43 => style.background = Some(ansi_term::Color::Yellow),
|
|
- 44 => style.background = Some(ansi_term::Color::Blue),
|
|
- 45 => style.background = Some(ansi_term::Color::Purple),
|
|
- 46 => style.background = Some(ansi_term::Color::Cyan),
|
|
- 47 => style.background = Some(ansi_term::Color::White),
|
|
- 48 => {
|
|
- let mut start = 0;
|
|
- if let Some(color) = parse_sgr_color(¶meters[i..], &mut start) {
|
|
- i += start;
|
|
+ // [39] => Some(Attr::Foreground(Color::Named(NamedColor::Foreground))),
|
|
+ [40] => style.background = Some(ansi_term::Color::Black),
|
|
+ [41] => style.background = Some(ansi_term::Color::Red),
|
|
+ [42] => style.background = Some(ansi_term::Color::Green),
|
|
+ [43] => style.background = Some(ansi_term::Color::Yellow),
|
|
+ [44] => style.background = Some(ansi_term::Color::Blue),
|
|
+ [45] => style.background = Some(ansi_term::Color::Purple),
|
|
+ [46] => style.background = Some(ansi_term::Color::Cyan),
|
|
+ [47] => style.background = Some(ansi_term::Color::White),
|
|
+ [48] => {
|
|
+ let mut iter = params.map(|param| param[0]);
|
|
+ if let Some(color) = parse_sgr_color(&mut iter) {
|
|
+ style.background = Some(color);
|
|
+ }
|
|
+ }
|
|
+ [48, params @ ..] => {
|
|
+ let rgb_start = if params.len() > 4 { 2 } else { 1 };
|
|
+ let rgb_iter = params[rgb_start..].iter().copied();
|
|
+ let mut iter = iter::once(params[0]).chain(rgb_iter);
|
|
+ if let Some(color) = parse_sgr_color(&mut iter) {
|
|
style.background = Some(color);
|
|
}
|
|
}
|
|
- // 49 => Some(Attr::Background(Color::Named(NamedColor::Background))),
|
|
+ // [49] => Some(Attr::Background(Color::Named(NamedColor::Background))),
|
|
// "bright" colors. ansi_term doesn't offer a way to emit them as, e.g., 90m; instead
|
|
// that would be 38;5;8.
|
|
- 90 => style.foreground = Some(ansi_term::Color::Fixed(8)),
|
|
- 91 => style.foreground = Some(ansi_term::Color::Fixed(9)),
|
|
- 92 => style.foreground = Some(ansi_term::Color::Fixed(10)),
|
|
- 93 => style.foreground = Some(ansi_term::Color::Fixed(11)),
|
|
- 94 => style.foreground = Some(ansi_term::Color::Fixed(12)),
|
|
- 95 => style.foreground = Some(ansi_term::Color::Fixed(13)),
|
|
- 96 => style.foreground = Some(ansi_term::Color::Fixed(14)),
|
|
- 97 => style.foreground = Some(ansi_term::Color::Fixed(15)),
|
|
- 100 => style.background = Some(ansi_term::Color::Fixed(8)),
|
|
- 101 => style.background = Some(ansi_term::Color::Fixed(9)),
|
|
- 102 => style.background = Some(ansi_term::Color::Fixed(10)),
|
|
- 103 => style.background = Some(ansi_term::Color::Fixed(11)),
|
|
- 104 => style.background = Some(ansi_term::Color::Fixed(12)),
|
|
- 105 => style.background = Some(ansi_term::Color::Fixed(13)),
|
|
- 106 => style.background = Some(ansi_term::Color::Fixed(14)),
|
|
- 107 => style.background = Some(ansi_term::Color::Fixed(15)),
|
|
+ [90] => style.foreground = Some(ansi_term::Color::Fixed(8)),
|
|
+ [91] => style.foreground = Some(ansi_term::Color::Fixed(9)),
|
|
+ [92] => style.foreground = Some(ansi_term::Color::Fixed(10)),
|
|
+ [93] => style.foreground = Some(ansi_term::Color::Fixed(11)),
|
|
+ [94] => style.foreground = Some(ansi_term::Color::Fixed(12)),
|
|
+ [95] => style.foreground = Some(ansi_term::Color::Fixed(13)),
|
|
+ [96] => style.foreground = Some(ansi_term::Color::Fixed(14)),
|
|
+ [97] => style.foreground = Some(ansi_term::Color::Fixed(15)),
|
|
+ [100] => style.background = Some(ansi_term::Color::Fixed(8)),
|
|
+ [101] => style.background = Some(ansi_term::Color::Fixed(9)),
|
|
+ [102] => style.background = Some(ansi_term::Color::Fixed(10)),
|
|
+ [103] => style.background = Some(ansi_term::Color::Fixed(11)),
|
|
+ [104] => style.background = Some(ansi_term::Color::Fixed(12)),
|
|
+ [105] => style.background = Some(ansi_term::Color::Fixed(13)),
|
|
+ [106] => style.background = Some(ansi_term::Color::Fixed(14)),
|
|
+ [107] => style.background = Some(ansi_term::Color::Fixed(15)),
|
|
_ => {}
|
|
};
|
|
- i += 1;
|
|
}
|
|
style
|
|
}
|
|
|
|
// Based on https://github.com/alacritty/alacritty/blob/57c4ac9145a20fb1ae9a21102503458d3da06c7b/alacritty_terminal/src/ansi.rs#L1258
|
|
-fn parse_sgr_color(attrs: &[i64], i: &mut usize) -> Option<ansi_term::Color> {
|
|
- if attrs.len() < 2 {
|
|
- return None;
|
|
- }
|
|
-
|
|
- match attrs[*i + 1] {
|
|
- 2 => {
|
|
- // RGB color spec.
|
|
- if attrs.len() < 5 {
|
|
- // debug!("Expected RGB color spec; got {:?}", attrs);
|
|
- return None;
|
|
- }
|
|
-
|
|
- let r = attrs[*i + 2];
|
|
- let g = attrs[*i + 3];
|
|
- let b = attrs[*i + 4];
|
|
-
|
|
- *i += 4;
|
|
-
|
|
- let range = 0..256;
|
|
- if !range.contains(&r) || !range.contains(&g) || !range.contains(&b) {
|
|
- // debug!("Invalid RGB color spec: ({}, {}, {})", r, g, b);
|
|
- return None;
|
|
- }
|
|
-
|
|
- Some(ansi_term::Color::RGB(r as u8, g as u8, b as u8))
|
|
- }
|
|
- 5 => {
|
|
- if attrs.len() < 3 {
|
|
- // debug!("Expected color index; got {:?}", attrs);
|
|
- None
|
|
- } else {
|
|
- *i += 2;
|
|
- let idx = attrs[*i];
|
|
- match idx {
|
|
- 0..=255 => Some(ansi_term::Color::Fixed(idx as u8)),
|
|
- _ => {
|
|
- // debug!("Invalid color index: {}", idx);
|
|
- None
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- _ => {
|
|
- // debug!("Unexpected color attr: {}", attrs[*i + 1]);
|
|
- None
|
|
+fn parse_sgr_color(params: &mut dyn Iterator<Item = i64>) -> Option<ansi_term::Color> {
|
|
+ match params.next() {
|
|
+ Some(2) => {
|
|
+ let r = u8::try_from(params.next()?).ok()?;
|
|
+ let g = u8::try_from(params.next()?).ok()?;
|
|
+ let b = u8::try_from(params.next()?).ok()?;
|
|
+ Some(ansi_term::Color::RGB(r, g, b))
|
|
}
|
|
+ Some(5) => Some(ansi_term::Color::Fixed(u8::try_from(params.next()?).ok()?)),
|
|
+ _ => None,
|
|
}
|
|
}
|
|
|
|
@@ -385,8 +349,9 @@
|
|
#[test]
|
|
fn test_iterator_1() {
|
|
let minus_line = "\x1b[31m0123\x1b[m\n";
|
|
+ let actual_elements: Vec<Element> = AnsiElementIterator::new(minus_line).collect();
|
|
assert_eq!(
|
|
- AnsiElementIterator::new(minus_line).to_vec(),
|
|
+ actual_elements,
|
|
vec![
|
|
Element::CSI(
|
|
ansi_term::Style {
|
|
@@ -408,8 +373,9 @@
|
|
#[test]
|
|
fn test_iterator_2() {
|
|
let minus_line = "\x1b[31m0123\x1b[m456\n";
|
|
+ let actual_elements: Vec<Element> = AnsiElementIterator::new(minus_line).collect();
|
|
assert_eq!(
|
|
- AnsiElementIterator::new(minus_line).to_vec(),
|
|
+ actual_elements,
|
|
vec![
|
|
Element::CSI(
|
|
ansi_term::Style {
|
|
@@ -431,8 +397,9 @@
|
|
#[test]
|
|
fn test_iterator_styled_non_ascii() {
|
|
let s = "\x1b[31mバー\x1b[0m";
|
|
+ let actual_elements: Vec<Element> = AnsiElementIterator::new(s).collect();
|
|
assert_eq!(
|
|
- AnsiElementIterator::new(s).to_vec(),
|
|
+ actual_elements,
|
|
vec![
|
|
Element::CSI(
|
|
ansi_term::Style {
|
|
@@ -463,8 +430,9 @@
|
|
assert_eq!(&s[86..87], "\\");
|
|
assert_eq!(&s[87..91], "\x1b[0m");
|
|
assert_eq!(&s[91..92], "\n");
|
|
+ let actual_elements: Vec<Element> = AnsiElementIterator::new(s).collect();
|
|
assert_eq!(
|
|
- AnsiElementIterator::new(s).to_vec(),
|
|
+ actual_elements,
|
|
vec![
|
|
Element::CSI(
|
|
ansi_term::Style {
|