Skip to content

Commit

Permalink
Remove code that tries to handle ANSI escape inputs (#2189)
Browse files Browse the repository at this point in the history
Syntax highlighting is broken when input contains ANSI escape characters
anyway, so there is not much point in trying to handle ANSI escapes in
input.
  • Loading branch information
Enselic authored Aug 29, 2022
1 parent a6297b2 commit 899fdbb
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 397 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

- Relaxed glibc requirements on amd64, see #2106 and #2194 (@sharkdp)
- Improved fish completions. See #2275 (@zgracem)
- Stop pre-processing ANSI escape characters. Syntax highlighting on ANSI escaped input is not supported. See #2185 and #2189 (@Enselic)

## Syntaxes

Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ pub(crate) mod printer;
pub mod style;
pub(crate) mod syntax_mapping;
mod terminal;
mod vscreen;
pub(crate) mod wrapping;

pub use pretty_printer::{Input, PrettyPrinter};
Expand Down
45 changes: 18 additions & 27 deletions src/preprocessor.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,26 @@
use console::AnsiCodeIterator;

/// Expand tabs like an ANSI-enabled expand(1).
pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
let mut buffer = String::with_capacity(line.len() * 2);

for chunk in AnsiCodeIterator::new(line) {
match chunk {
(text, true) => buffer.push_str(text),
(mut text, false) => {
while let Some(index) = text.find('\t') {
// Add previous text.
if index > 0 {
*cursor += index;
buffer.push_str(&text[0..index]);
}

// Add tab.
let spaces = width - (*cursor % width);
*cursor += spaces;
buffer.push_str(&*" ".repeat(spaces));
pub fn expand_tabs(mut text: &str, width: usize, cursor: &mut usize) -> String {
let mut buffer = String::with_capacity(text.len() * 2);

while let Some(index) = text.find('\t') {
// Add previous text.
if index > 0 {
*cursor += index;
buffer.push_str(&text[0..index]);
}

// Next.
text = &text[index + 1..text.len()];
}
// Add tab.
let spaces = width - (*cursor % width);
*cursor += spaces;
buffer.push_str(&*" ".repeat(spaces));

*cursor += text.len();
buffer.push_str(text);
}
}
// Next.
text = &text[index + 1..text.len()];
}

*cursor += text.len();
buffer.push_str(text);

buffer
}

Expand Down
240 changes: 102 additions & 138 deletions src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ use ansi_term::Style;

use bytesize::ByteSize;

use console::AnsiCodeIterator;

use syntect::easy::HighlightLines;
use syntect::highlighting::Color;
use syntect::highlighting::Theme;
Expand All @@ -33,7 +31,6 @@ use crate::line_range::RangeCheckResult;
use crate::preprocessor::{expand_tabs, replace_nonprintable};
use crate::style::StyleComponent;
use crate::terminal::{as_terminal_escaped, to_ansi_color};
use crate::vscreen::AnsiStyle;
use crate::wrapping::WrappingMode;

pub(crate) trait Printer {
Expand Down Expand Up @@ -122,7 +119,6 @@ pub(crate) struct InteractivePrinter<'a> {
config: &'a Config<'a>,
decorations: Vec<Box<dyn Decoration>>,
panel_width: usize,
ansi_style: AnsiStyle,
content_type: Option<ContentType>,
#[cfg(feature = "git")]
pub line_changes: &'a Option<LineChanges>,
Expand Down Expand Up @@ -206,7 +202,6 @@ impl<'a> InteractivePrinter<'a> {
config,
decorations,
content_type: input.reader.content_type,
ansi_style: AnsiStyle::new(),
#[cfg(feature = "git")]
line_changes,
highlighter_from_set,
Expand Down Expand Up @@ -476,7 +471,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
self.config.highlighted_lines.0.check(line_number) == RangeCheckResult::InRange;

if highlight_this_line && self.config.theme == "ansi" {
self.ansi_style.update("^[4m");
write!(handle, "\x1B[4m")?;
}

let background_color = self
Expand All @@ -503,51 +498,37 @@ impl<'a> Printer for InteractivePrinter<'a> {
let italics = self.config.use_italic_text;

for &(style, region) in &regions {
let ansi_iterator = AnsiCodeIterator::new(region);
for chunk in ansi_iterator {
match chunk {
// ANSI escape passthrough.
(ansi, true) => {
self.ansi_style.update(ansi);
write!(handle, "{}", ansi)?;
}
let text = &*self.preprocess(region, &mut cursor_total);
let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n');

// Regular text.
(text, false) => {
let text = &*self.preprocess(text, &mut cursor_total);
let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n');

write!(
handle,
"{}",
as_terminal_escaped(
style,
&format!("{}{}", self.ansi_style, text_trimmed),
true_color,
colored_output,
italics,
background_color
)
)?;

if text.len() != text_trimmed.len() {
if let Some(background_color) = background_color {
let ansi_style = Style {
background: to_ansi_color(background_color, true_color),
..Default::default()
};

let width = if cursor_total <= cursor_max {
cursor_max - cursor_total + 1
} else {
0
};
write!(handle, "{}", ansi_style.paint(" ".repeat(width)))?;
}
write!(handle, "{}", &text[text_trimmed.len()..])?;
}
}
write!(
handle,
"{}",
as_terminal_escaped(
style,
text_trimmed,
true_color,
colored_output,
italics,
background_color
)
)?;

if text.len() != text_trimmed.len() {
if let Some(background_color) = background_color {
let ansi_style = Style {
background: to_ansi_color(background_color, true_color),
..Default::default()
};

let width = if cursor_total <= cursor_max {
cursor_max - cursor_total + 1
} else {
0
};
write!(handle, "{}", ansi_style.paint(" ".repeat(width)))?;
}
write!(handle, "{}", &text[text_trimmed.len()..])?;
}
}

Expand All @@ -556,98 +537,82 @@ impl<'a> Printer for InteractivePrinter<'a> {
}
} else {
for &(style, region) in &regions {
let ansi_iterator = AnsiCodeIterator::new(region);
for chunk in ansi_iterator {
match chunk {
// ANSI escape passthrough.
(ansi, true) => {
self.ansi_style.update(ansi);
write!(handle, "{}", ansi)?;
}

// Regular text.
(text, false) => {
let text = self.preprocess(
text.trim_end_matches(|c| c == '\r' || c == '\n'),
&mut cursor_total,
);

let mut max_width = cursor_max - cursor;

// line buffer (avoid calling write! for every character)
let mut line_buf = String::with_capacity(max_width * 4);

// Displayed width of line_buf
let mut current_width = 0;

for c in text.chars() {
// calculate the displayed width for next character
let cw = c.width().unwrap_or(0);
current_width += cw;

// if next character cannot be printed on this line,
// flush the buffer.
if current_width > max_width {
// Generate wrap padding if not already generated.
if panel_wrap.is_none() {
panel_wrap = if self.panel_width > 0 {
Some(format!(
"{} ",
self.decorations
.iter()
.map(|d| d
.generate(line_number, true, self)
.text)
.collect::<Vec<String>>()
.join(" ")
))
} else {
Some("".to_string())
}
}

// It wraps.
write!(
handle,
"{}\n{}",
as_terminal_escaped(
style,
&*format!("{}{}", self.ansi_style, line_buf),
self.config.true_color,
self.config.colored_output,
self.config.use_italic_text,
background_color
),
panel_wrap.clone().unwrap()
)?;

cursor = 0;
max_width = cursor_max;

line_buf.clear();
current_width = cw;
}

line_buf.push(c);
let text = self.preprocess(
region.trim_end_matches(|c| c == '\r' || c == '\n'),
&mut cursor_total,
);

let mut max_width = cursor_max - cursor;

// line buffer (avoid calling write! for every character)
let mut line_buf = String::with_capacity(max_width * 4);

// Displayed width of line_buf
let mut current_width = 0;

for c in text.chars() {
// calculate the displayed width for next character
let cw = c.width().unwrap_or(0);
current_width += cw;

// if next character cannot be printed on this line,
// flush the buffer.
if current_width > max_width {
// Generate wrap padding if not already generated.
if panel_wrap.is_none() {
panel_wrap = if self.panel_width > 0 {
Some(format!(
"{} ",
self.decorations
.iter()
.map(|d| d.generate(line_number, true, self).text)
.collect::<Vec<String>>()
.join(" ")
))
} else {
Some("".to_string())
}

// flush the buffer
cursor += current_width;
write!(
handle,
"{}",
as_terminal_escaped(
style,
&*format!("{}{}", self.ansi_style, line_buf),
self.config.true_color,
self.config.colored_output,
self.config.use_italic_text,
background_color
)
)?;
}

// It wraps.
write!(
handle,
"{}\n{}",
as_terminal_escaped(
style,
&line_buf,
self.config.true_color,
self.config.colored_output,
self.config.use_italic_text,
background_color
),
panel_wrap.clone().unwrap()
)?;

cursor = 0;
max_width = cursor_max;

line_buf.clear();
current_width = cw;
}

line_buf.push(c);
}

// flush the buffer
cursor += current_width;
write!(
handle,
"{}",
as_terminal_escaped(
style,
&line_buf,
self.config.true_color,
self.config.colored_output,
self.config.use_italic_text,
background_color
)
)?;
}

if let Some(background_color) = background_color {
Expand All @@ -666,7 +631,6 @@ impl<'a> Printer for InteractivePrinter<'a> {
}

if highlight_this_line && self.config.theme == "ansi" {
self.ansi_style.update("^[24m");
write!(handle, "\x1B[24m")?;
}

Expand Down
Loading

0 comments on commit 899fdbb

Please sign in to comment.