|
1 | 1 | #[cfg(feature = "alloc")] |
2 | 2 | use alloc::{borrow::Cow, string::String}; |
3 | 3 | use core::{ |
| 4 | + fmt::Display, |
4 | 5 | iter::{FusedIterator, Peekable}, |
5 | 6 | str::CharIndices, |
6 | 7 | }; |
@@ -201,6 +202,27 @@ pub fn strip_ansi_codes(s: &str) -> Cow<str> { |
201 | 202 | } |
202 | 203 | } |
203 | 204 |
|
| 205 | +/// A wrapper struct that implements [`core::fmt::Display`], only displaying non-ansi parts. |
| 206 | +pub struct WithoutAnsi<'a> { |
| 207 | + str: &'a str, |
| 208 | +} |
| 209 | +impl<'a> WithoutAnsi<'a> { |
| 210 | + pub fn new(str: &'a str) -> Self { |
| 211 | + Self { str } |
| 212 | + } |
| 213 | +} |
| 214 | +impl Display for WithoutAnsi<'_> { |
| 215 | + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| 216 | + for str in |
| 217 | + AnsiCodeIterator::new(self.str) |
| 218 | + .filter_map(|(str, is_ansi)| if is_ansi { None } else { Some(str) }) |
| 219 | + { |
| 220 | + f.write_str(str)?; |
| 221 | + } |
| 222 | + Ok(()) |
| 223 | + } |
| 224 | +} |
| 225 | + |
204 | 226 | /// An iterator over ansi codes in a string. |
205 | 227 | /// |
206 | 228 | /// This type can be used to scan over ansi codes in a string. |
@@ -273,6 +295,7 @@ impl FusedIterator for AnsiCodeIterator<'_> {} |
273 | 295 | mod tests { |
274 | 296 | use super::*; |
275 | 297 |
|
| 298 | + use core::fmt::Write; |
276 | 299 | use once_cell::sync::Lazy; |
277 | 300 | use proptest::prelude::*; |
278 | 301 | use regex::Regex; |
@@ -385,6 +408,17 @@ mod tests { |
385 | 408 | assert_eq!(&[s], matches.as_slice()); |
386 | 409 | } |
387 | 410 |
|
| 411 | + #[test] |
| 412 | + fn test_without_ansi() { |
| 413 | + let str_with_ansi = "\x1b[1;97;41mError\x1b[0m"; |
| 414 | + let without_ansi = WithoutAnsi::new(str_with_ansi); |
| 415 | + for _ in 0..2 { |
| 416 | + let mut output = String::default(); |
| 417 | + write!(output, "{without_ansi}").unwrap(); |
| 418 | + assert_eq!(output, "Error"); |
| 419 | + } |
| 420 | + } |
| 421 | + |
388 | 422 | #[test] |
389 | 423 | fn test_ansi_iter_re_vt100() { |
390 | 424 | let s = "\x1b(0lpq\x1b)Benglish"; |
|
0 commit comments