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}