summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Davison <dandavison7@gmail.com>2024-03-17 13:26:22 -0400
committerDan Davison <dandavison7@gmail.com>2024-03-17 13:26:44 -0400
commitcd95910ce212517ff508d3bfa70ddabf43e75012 (patch)
treeacd6021faac1c53a61e1aca67c2114f27d82cccd
parent4b80dfb04c4a6e2dc841408345a2f72d441cf161 (diff)
Reimplement line_has_style_other_than
-rw-r--r--src/ansi/mod.rs14
-rw-r--r--src/style.rs20
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<Item = ansi_term::Style> + '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<ansi_term::Style> {
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<ansi_term::Style> {
})
}
+#[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<ansi_term::Color>, b: Option<ansi_term::Color>) -> bool {
match (a, b) {
(None, None) => true,
@@ -321,6 +325,7 @@ fn ansi_term_color_equality(a: Option<ansi_term::Color>, b: Option<ansi_term::Co
}
}
+#[cfg(test)]
fn ansi_term_16_color_equality(a: ansi_term::Color, b: ansi_term::Color) -> 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<AnsiTermStyleEqualityKey> = 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)]