mirror of
https://github.com/sharkdp/bat.git
synced 2025-02-05 12:29:21 +01:00
Strip OSC sequences before printing
This commit strips OSC (Operating System Command) sequences before printing lines. Eventually when time permits, I want to add back support for printing OSC sequences (and improve it to treat hyperlinks like an attribute). Until then, this should help prevent garbled output :)
This commit is contained in:
parent
414403b062
commit
054421268f
@ -33,7 +33,7 @@ use crate::line_range::RangeCheckResult;
|
|||||||
use crate::preprocessor::{expand_tabs, replace_nonprintable};
|
use crate::preprocessor::{expand_tabs, replace_nonprintable};
|
||||||
use crate::style::StyleComponent;
|
use crate::style::StyleComponent;
|
||||||
use crate::terminal::{as_terminal_escaped, to_ansi_color};
|
use crate::terminal::{as_terminal_escaped, to_ansi_color};
|
||||||
use crate::vscreen::AnsiStyle;
|
use crate::vscreen::{strip_problematic_sequences, AnsiStyle};
|
||||||
use crate::wrapping::WrappingMode;
|
use crate::wrapping::WrappingMode;
|
||||||
|
|
||||||
pub enum OutputHandle<'a> {
|
pub enum OutputHandle<'a> {
|
||||||
@ -581,7 +581,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
let italics = self.config.use_italic_text;
|
let italics = self.config.use_italic_text;
|
||||||
|
|
||||||
for &(style, region) in ®ions {
|
for &(style, region) in ®ions {
|
||||||
let ansi_iterator = AnsiCodeIterator::new(region);
|
let text = strip_problematic_sequences(region);
|
||||||
|
let ansi_iterator = AnsiCodeIterator::new(&text);
|
||||||
for chunk in ansi_iterator {
|
for chunk in ansi_iterator {
|
||||||
match chunk {
|
match chunk {
|
||||||
// ANSI escape passthrough.
|
// ANSI escape passthrough.
|
||||||
@ -634,7 +635,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for &(style, region) in ®ions {
|
for &(style, region) in ®ions {
|
||||||
let ansi_iterator = AnsiCodeIterator::new(region);
|
let text = strip_problematic_sequences(region);
|
||||||
|
let ansi_iterator = AnsiCodeIterator::new(&text);
|
||||||
for chunk in ansi_iterator {
|
for chunk in ansi_iterator {
|
||||||
match chunk {
|
match chunk {
|
||||||
// ANSI escape passthrough.
|
// ANSI escape passthrough.
|
||||||
|
@ -458,9 +458,54 @@ impl<'a> Iterator for EscapeSequenceOffsetsIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Strips problematic ANSI escape sequences from a string.
|
||||||
|
///
|
||||||
|
/// Ideally, this will be replaced with something that uses [[Attributes]] to create a table of char offsets
|
||||||
|
/// -> absolute styles and style deltas. Something like that would let us simplify the printer (and support
|
||||||
|
/// re-printing OSC hyperlink commands).
|
||||||
|
pub fn strip_problematic_sequences(text: &str) -> String {
|
||||||
|
use EscapeSequenceOffsets::*;
|
||||||
|
|
||||||
|
let mut buffer = String::with_capacity(text.len());
|
||||||
|
for seq in EscapeSequenceOffsetsIterator::new(text) {
|
||||||
|
match seq {
|
||||||
|
Text { start, end } => buffer.push_str(&text[start..end]),
|
||||||
|
Unknown { start, end } => buffer.push_str(&text[start..end]),
|
||||||
|
|
||||||
|
NF {
|
||||||
|
start_sequence: start,
|
||||||
|
start: _,
|
||||||
|
end,
|
||||||
|
} => buffer.push_str(&text[start..end]),
|
||||||
|
|
||||||
|
CSI {
|
||||||
|
start_sequence: start,
|
||||||
|
start_parameters: _,
|
||||||
|
start_intermediates: _,
|
||||||
|
start_final_byte: _,
|
||||||
|
end,
|
||||||
|
} => buffer.push_str(&text[start..end]),
|
||||||
|
|
||||||
|
OSC {
|
||||||
|
start_sequence: _,
|
||||||
|
start_command: _,
|
||||||
|
start_terminator: _,
|
||||||
|
end: _,
|
||||||
|
} => {
|
||||||
|
// TODO(eth-p): Support re-printing hyperlinks.
|
||||||
|
// In the meantime, strip these.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::vscreen::{EscapeSequenceOffsets, EscapeSequenceOffsetsIterator};
|
use crate::vscreen::{
|
||||||
|
strip_problematic_sequences, EscapeSequenceOffsets, EscapeSequenceOffsetsIterator,
|
||||||
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_escape_sequence_offsets_iterator_parses_text() {
|
fn test_escape_sequence_offsets_iterator_parses_text() {
|
||||||
@ -683,4 +728,12 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(iter.next(), None);
|
assert_eq!(iter.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strip_problematic_sequences() {
|
||||||
|
assert_eq!(
|
||||||
|
strip_problematic_sequences("text\x1B[33m\x1B]OSC\x1B\\\x1B(0"),
|
||||||
|
"text\x1B[33m\x1B(0"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user