Remove hyperlink when wrapping lines

This commit is contained in:
Ethan P 2023-04-17 19:19:49 -07:00 committed by Ethan P.
parent 6549e26f5d
commit 1023399c5e
No known key found for this signature in database
GPG Key ID: 1BA2A0CC7C22B854
3 changed files with 46 additions and 7 deletions

View File

@ -598,12 +598,12 @@ impl<'a> Printer for InteractivePrinter<'a> {
match chunk {
// Regular text.
EscapeSequence::Text(text) => {
let text = &*self.preprocess(text, &mut cursor_total);
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),
@ -611,9 +611,11 @@ impl<'a> Printer for InteractivePrinter<'a> {
colored_output,
italics,
background_color
)
),
self.ansi_style.to_reset_sequence(),
)?;
// Pad the rest of the line.
if text.len() != text_trimmed.len() {
if let Some(background_color) = background_color {
let ansi_style = Style {
@ -693,7 +695,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
// It wraps.
write!(
handle,
"{}\n{}",
"{}{}\n{}",
as_terminal_escaped(
style,
&format!("{}{}", self.ansi_style, line_buf),
@ -702,6 +704,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
self.config.use_italic_text,
background_color
),
self.ansi_style.to_reset_sequence(),
panel_wrap.clone().unwrap()
)?;

View File

@ -23,6 +23,13 @@ impl AnsiStyle {
}
}
}
pub fn to_reset_sequence(&mut self) -> String {
match &mut self.attributes {
Some(a) => a.to_reset_sequence(),
None => String::new(),
}
}
}
impl Display for AnsiStyle {
@ -35,6 +42,8 @@ impl Display for AnsiStyle {
}
struct Attributes {
has_sgr_sequences: bool,
foreground: String,
background: String,
underlined: String,
@ -67,16 +76,18 @@ struct Attributes {
strike: String,
/// The hyperlink sequence.
/// FORMAT: \x1B]8;<ID>;<HREF>\e\\
/// FORMAT: \x1B]8;{ID};{URL}\e\\
///
/// `\e\\` may be replaced with BEL `\x07`.
/// Setting both <ID> and <HREF> to an empty string represents no hyperlink.
/// Setting both {ID} and {URL} to an empty string represents no hyperlink.
hyperlink: String,
}
impl Attributes {
pub fn new() -> Self {
Attributes {
has_sgr_sequences: false,
foreground: "".to_owned(),
background: "".to_owned(),
underlined: "".to_owned(),
@ -135,6 +146,8 @@ impl Attributes {
}
fn sgr_reset(&mut self) {
self.has_sgr_sequences = false;
self.foreground.clear();
self.background.clear();
self.underlined.clear();
@ -152,6 +165,7 @@ impl Attributes {
.map(|p| p.parse::<u16>())
.map(|p| p.unwrap_or(0)); // Treat errors as 0.
self.has_sgr_sequences = true;
while let Some(p) = iter.next() {
match p {
0 => self.sgr_reset(),
@ -214,6 +228,28 @@ impl Attributes {
_ => format!("\x1B[{}m", color),
}
}
/// Gets an ANSI escape sequence to reset all the known attributes.
pub fn to_reset_sequence(&self) -> String {
let mut buf = String::with_capacity(17);
// TODO: Enable me in a later pull request.
// if self.has_sgr_sequences {
// buf.push_str("\x1B[m");
// }
if !self.hyperlink.is_empty() {
buf.push_str("\x1B]8;;\x1B\\"); // Disable hyperlink.
}
// TODO: Enable me in a later pull request.
// if !self.charset.is_empty() {
// // https://espterm.github.io/docs/VT100%20escape%20codes.html
// buf.push_str("\x1B(B\x1B)B"); // setusg0 and setusg1
// }
buf
}
}
impl Display for Attributes {

View File

@ -1966,7 +1966,7 @@ fn ansi_hyperlink_emitted_when_wrapped() {
.write_stdin("\x1B]8;;http://example.com/\x1B\\Hyperlinks..........Wrap across lines.\n")
.assert()
.success()
.stdout("\x1B]8;;http://example.com/\x1B\\\x1B]8;;http://example.com/\x1B\\Hyperlinks..........\n\x1B]8;;http://example.com/\x1B\\Wrap across lines.\n")
.stdout("\x1B]8;;http://example.com/\x1B\\\x1B]8;;http://example.com/\x1B\\Hyperlinks..........\x1B]8;;\x1B\\\n\x1B]8;;http://example.com/\x1B\\Wrap across lines.\n")
// FIXME: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ should not be emitted twice.
.stderr("");
}