summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEthan P <eth-p+git@hidden.email>2023-04-16 20:18:40 -0700
committerEthan P. <eth-p+git@hidden.email>2024-02-09 22:09:39 -0800
commit054421268fff33003b892eb7bcef1a831c6c308d (patch)
treeaa4a4f09b57b7a1831f3b53fef7da205f08e1f35 /src
parent414403b062ac644ee2b569870f66de49999f9dd3 (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.rs8
-rw-r--r--src/vscreen.rs55
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 &regions {
- 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 &regions {
- 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"
+ );
+ }
}