nu_utils/
deansi.rs

1use std::borrow::Cow;
2
3/// Removes ANSI escape codes and some ASCII control characters
4///
5/// Optimized for strings that rarely contain ANSI control chars.
6/// Uses fast search to avoid reallocations.
7///
8/// Keeps `\n` removes `\r`, `\t` etc.
9///
10/// If parsing fails silently returns the input string
11pub fn strip_ansi_unlikely(string: &str) -> Cow<'_, str> {
12    // Check if any ascii control character except LF(0x0A = 10) is present,
13    // which will be stripped. Includes the primary start of ANSI sequences ESC
14    // (0x1B = decimal 27)
15    if string.bytes().any(|x| matches!(x, 0..=9 | 11..=31))
16        && let Ok(stripped) = String::from_utf8(strip_ansi_escapes::strip(string))
17    {
18        return Cow::Owned(stripped);
19    }
20    // Else case includes failures to parse!
21    Cow::Borrowed(string)
22}
23
24/// Removes ANSI escape codes and some ASCII control characters
25///
26/// Optimized for strings that likely contain ANSI control chars.
27///
28/// Keeps `\n` removes `\r`, `\t` etc.
29///
30/// If parsing fails silently returns the input string
31pub fn strip_ansi_likely(string: &str) -> Cow<'_, str> {
32    // Check if any ascii control character except LF(0x0A = 10) is present,
33    // which will be stripped. Includes the primary start of ANSI sequences ESC
34    // (0x1B = decimal 27)
35    if let Ok(stripped) = String::from_utf8(strip_ansi_escapes::strip(string)) {
36        return Cow::Owned(stripped);
37    }
38    // Else case includes failures to parse!
39    Cow::Borrowed(string)
40}
41
42/// Removes ANSI escape codes and some ASCII control characters
43///
44/// Optimized for strings that rarely contain ANSI control chars.
45/// Uses fast search to avoid reallocations.
46///
47/// Keeps `\n` removes `\r`, `\t` etc.
48///
49/// If parsing fails silently returns the input string
50pub fn strip_ansi_string_unlikely(string: String) -> String {
51    // Check if any ascii control character except LF(0x0A = 10) is present,
52    // which will be stripped. Includes the primary start of ANSI sequences ESC
53    // (0x1B = decimal 27)
54    if string
55        .as_str()
56        .bytes()
57        .any(|x| matches!(x, 0..=8 | 11..=31))
58        && let Ok(stripped) = String::from_utf8(strip_ansi_escapes::strip(&string))
59    {
60        return stripped;
61    }
62    // Else case includes failures to parse!
63    string
64}
65
66/// Removes ANSI escape codes and some ASCII control characters
67///
68/// Optimized for strings that likely contain ANSI control chars.
69///
70/// Keeps `\n` removes `\r`, `\t` etc.
71///
72/// If parsing fails silently returns the input string
73pub fn strip_ansi_string_likely(string: String) -> String {
74    // Check if any ascii control character except LF(0x0A = 10) is present,
75    // which will be stripped. Includes the primary start of ANSI sequences ESC
76    // (0x1B = decimal 27)
77    if let Ok(stripped) = String::from_utf8(strip_ansi_escapes::strip(&string)) {
78        return stripped;
79    }
80    // Else case includes failures to parse!
81    string
82}