From cd95910ce212517ff508d3bfa70ddabf43e75012 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Sun, 17 Mar 2024 13:26:22 -0400 Subject: Reimplement line_has_style_other_than --- src/ansi/mod.rs | 14 ++++++++++++++ src/style.rs | 20 +++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/ansi/mod.rs b/src/ansi/mod.rs index a0f7f973..d525c71d 100644 --- a/src/ansi/mod.rs +++ b/src/ansi/mod.rs @@ -67,6 +67,18 @@ pub fn truncate_str<'a>(s: &'a str, display_width: usize, tail: &str) -> Cow<'a, Cow::from(format!("{result}{result_tail}")) } +pub fn ansi_styles_iterator<'a>(s: &'a str) -> impl Iterator + 'a { + let mut curr_style = Style::default(); + AnsiElementIterator::new(s).filter_map(move |el| match el { + Element::Text(_, _) => Some(curr_style), + Element::Sgr(style, _, _) => { + curr_style = style; + None + } + _ => None, + }) +} + pub fn parse_style_sections(s: &str) -> Vec<(ansi_term::Style, &str)> { let mut sections = Vec::new(); let mut curr_style = Style::default(); @@ -81,6 +93,7 @@ pub fn parse_style_sections(s: &str) -> Vec<(ansi_term::Style, &str)> { } // Return the first CSI element, if any, as an `ansi_term::Style`. +#[cfg(test)] pub fn parse_first_style(s: &str) -> Option { AnsiElementIterator::new(s).find_map(|el| match el { Element::Sgr(style, _, _) => Some(style), @@ -88,6 +101,7 @@ pub fn parse_first_style(s: &str) -> Option { }) } +#[cfg(test)] pub fn string_starts_with_ansi_style_sequence(s: &str) -> bool { AnsiElementIterator::new(s) .next() diff --git a/src/style.rs b/src/style.rs index c52400c8..1fba6d65 100644 --- a/src/style.rs +++ b/src/style.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::collections::HashSet; use std::fmt; use std::hash::{Hash, Hasher}; @@ -118,6 +119,7 @@ impl Style { } } + #[cfg(test)] pub fn is_applied_to(&self, s: &str) -> bool { match ansi::parse_first_style(s) { Some(parsed_style) => ansi_term_style_equality(parsed_style, self.ansi_term_style), @@ -203,6 +205,7 @@ impl fmt::Display for Style { } } +#[cfg(test)] pub fn ansi_term_style_equality(a: ansi_term::Style, b: ansi_term::Style) -> bool { let a_attrs = ansi_term::Style { foreground: None, @@ -306,6 +309,7 @@ impl fmt::Debug for AnsiTermStyleEqualityKey { } } +#[cfg(test)] fn ansi_term_color_equality(a: Option, b: Option) -> bool { match (a, b) { (None, None) => true, @@ -321,6 +325,7 @@ fn ansi_term_color_equality(a: Option, b: Option bool { matches!( (a, b), @@ -367,15 +372,16 @@ lazy_static! { } pub fn line_has_style_other_than(line: &str, styles: &[Style]) -> bool { - if !ansi::string_starts_with_ansi_style_sequence(line) { - return false; - } - for style in styles { - if style.is_applied_to(line) { - return false; + let style_keys: HashSet = styles + .iter() + .map(|s| ansi_term_style_equality_key(s.ansi_term_style)) + .collect(); + for line_style in ansi::ansi_styles_iterator(line) { + if !style_keys.contains(&ansi_term_style_equality_key(line_style)) { + return true; } } - true + false } #[cfg(test)] -- cgit v1.2.3