diff options
author | Ethan P <eth-p+git@hidden.email> | 2023-04-16 20:18:40 -0700 |
---|---|---|
committer | Ethan P. <eth-p+git@hidden.email> | 2024-02-09 22:09:39 -0800 |
commit | 054421268fff33003b892eb7bcef1a831c6c308d (patch) | |
tree | aa4a4f09b57b7a1831f3b53fef7da205f08e1f35 /src | |
parent | 414403b062ac644ee2b569870f66de49999f9dd3 (diff) |
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 :)
Diffstat (limited to 'src')
-rw-r--r-- | src/printer.rs | 8 | ||||
-rw-r--r-- | src/vscreen.rs | 55 |
2 files changed, 59 insertions, 4 deletions
diff --git a/src/printer.rs b/src/printer.rs index 257cc766..45fd5336 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -33,7 +33,7 @@ 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::vscreen::{strip_problematic_sequences, AnsiStyle}; use crate::wrapping::WrappingMode; pub enum OutputHandle<'a> { @@ -581,7 +581,8 @@ impl<'a> Printer for InteractivePrinter<'a> { let italics = self.config.use_italic_text; 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 { match chunk { // ANSI escape passthrough. @@ -634,7 +635,8 @@ impl<'a> Printer for InteractivePrinter<'a> { } } else { 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 { match chunk { // ANSI escape passthrough. diff --git a/src/vscreen.rs b/src/vscreen.rs index ecf2bd3c..ccd0bfe8 100644 --- a/src/vscreen.rs +++ b/src/vscreen.rs @@ -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)] mod tests { - use crate::vscreen::{EscapeSequenceOffsets, EscapeSequenceOffsetsIterator}; + use crate::vscreen::{ + strip_problematic_sequences, EscapeSequenceOffsets, EscapeSequenceOffsetsIterator, + }; #[test] fn test_escape_sequence_offsets_iterator_parses_text() { @@ -683,4 +728,12 @@ mod tests { ); 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" + ); + } } |