diff options
author | Dan Davison <dandavison7@gmail.com> | 2020-07-30 21:25:47 -0400 |
---|---|---|
committer | Dan Davison <dandavison7@gmail.com> | 2020-08-01 11:38:19 -0400 |
commit | c6f66ab8fde78209d395d3502c63da66fae294e0 (patch) | |
tree | 2eb55b3819ea22ef36a96e4e2bb95de8eb7f4560 /src/ansi/mod.rs | |
parent | e03a12df8c4be03a08b07ae236ffcd6b67ba77df (diff) |
Parse ANSI escape sequences as ansi_term Style
Diffstat (limited to 'src/ansi/mod.rs')
-rw-r--r-- | src/ansi/mod.rs | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/ansi/mod.rs b/src/ansi/mod.rs new file mode 100644 index 00000000..158b562c --- /dev/null +++ b/src/ansi/mod.rs @@ -0,0 +1,73 @@ +pub mod parse; + +use std::cmp::min; + +use console; +use itertools::Itertools; + +pub const ANSI_CSI_CLEAR_TO_EOL: &str = "\x1b[0K"; +pub const ANSI_CSI_CLEAR_TO_BOL: &str = "\x1b[1K"; +pub const ANSI_SGR_RESET: &str = "\x1b[0m"; + +pub fn string_starts_with_ansi_escape_sequence(s: &str) -> bool { + console::AnsiCodeIterator::new(s) + .nth(0) + .map(|(_, is_ansi)| is_ansi) + .unwrap_or(false) +} + +/// Return string formed from a byte slice starting at byte position `start`, where the index +/// counts bytes in non-ANSI-escape-sequence content only. All ANSI escape sequences in the +/// original string are preserved. +pub fn ansi_preserving_slice(s: &str, start: usize) -> String { + console::AnsiCodeIterator::new(s) + .scan(0, |i, (substring, is_ansi)| { + // i is the index in non-ANSI-escape-sequence content. + let substring_slice = if is_ansi || *i > start { + substring + } else { + &substring[min(substring.len(), start - *i)..] + }; + if !is_ansi { + *i += substring.len(); + } + Some(substring_slice) + }) + .join("") +} + +#[cfg(test)] +mod tests { + + use crate::ansi::ansi_preserving_slice; + use crate::ansi::string_starts_with_ansi_escape_sequence; + + #[test] + fn test_string_starts_with_ansi_escape_sequence() { + assert!(!string_starts_with_ansi_escape_sequence("")); + assert!(!string_starts_with_ansi_escape_sequence("-")); + assert!(string_starts_with_ansi_escape_sequence( + "\x1b[31m-XXX\x1b[m\n" + )); + assert!(string_starts_with_ansi_escape_sequence("\x1b[32m+XXX")); + } + + #[test] + fn test_ansi_preserving_slice() { + assert_eq!(ansi_preserving_slice("", 0), ""); + assert_eq!(ansi_preserving_slice("a", 0), "a"); + assert_eq!(ansi_preserving_slice("a", 1), ""); + assert_eq!( + ansi_preserving_slice("\x1b[1;35m-2222.2222.2222.2222\x1b[0m", 1), + "\x1b[1;35m2222.2222.2222.2222\x1b[0m" + ); + assert_eq!( + ansi_preserving_slice("\x1b[1;35m-2222.2222.2222.2222\x1b[0m", 15), + "\x1b[1;35m.2222\x1b[0m" + ); + assert_eq!( + ansi_preserving_slice("\x1b[1;36m-\x1b[m\x1b[1;36m2222·2222·2222·2222\x1b[m\n", 1), + "\x1b[1;36m\x1b[m\x1b[1;36m2222·2222·2222·2222\x1b[m\n" + ) + } +} |