Denis Drakhnia
1 year ago
7 changed files with 163 additions and 8 deletions
@ -0,0 +1,107 @@
@@ -0,0 +1,107 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
// SPDX-FileCopyrightText: 2023 Denis Drakhnia <numas13@gmail.com>
|
||||
|
||||
use std::borrow::Cow; |
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)] |
||||
pub enum Color { |
||||
Black, |
||||
Red, |
||||
Green, |
||||
Yellow, |
||||
Blue, |
||||
Cyan, |
||||
Magenta, |
||||
White, |
||||
} |
||||
|
||||
impl TryFrom<&str> for Color { |
||||
type Error = (); |
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> { |
||||
Ok(match value { |
||||
"^0" => Self::Black, |
||||
"^1" => Self::Red, |
||||
"^2" => Self::Green, |
||||
"^3" => Self::Yellow, |
||||
"^4" => Self::Blue, |
||||
"^5" => Self::Cyan, |
||||
"^6" => Self::Magenta, |
||||
"^7" => Self::White, |
||||
_ => return Err(()), |
||||
}) |
||||
} |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn is_color_code(s: &str) -> bool { |
||||
matches!(s.as_bytes(), [b'^', c, ..] if c.is_ascii_digit()) |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn trim_start_color(s: &str) -> (&str, &str) { |
||||
let n = if is_color_code(s) { 2 } else { 0 }; |
||||
s.split_at(n) |
||||
} |
||||
|
||||
pub struct ColorIter<'a> { |
||||
inner: &'a str, |
||||
} |
||||
|
||||
impl<'a> ColorIter<'a> { |
||||
pub fn new(inner: &'a str) -> Self { |
||||
Self { inner } |
||||
} |
||||
} |
||||
|
||||
impl<'a> Iterator for ColorIter<'a> { |
||||
type Item = (&'a str, &'a str); |
||||
|
||||
fn next(&mut self) -> Option<Self::Item> { |
||||
if !self.inner.is_empty() { |
||||
let i = self.inner[1..].find('^').map(|i| i + 1).unwrap_or(self.inner.len()); |
||||
let (head, tail) = self.inner.split_at(i); |
||||
let (color, text) = trim_start_color(head); |
||||
self.inner = tail; |
||||
Some((color, text)) |
||||
} else { |
||||
None |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn trim_color(s: &str) -> Cow<'_, str> { |
||||
let (_, s) = trim_start_color(s); |
||||
if !s.chars().any(|c| c == '^') { |
||||
return Cow::Borrowed(s); |
||||
} |
||||
|
||||
let mut out = String::with_capacity(s.len()); |
||||
for (_, s) in ColorIter::new(s) { |
||||
out.push_str(s); |
||||
} |
||||
|
||||
Cow::Owned(out) |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod tests { |
||||
use super::*; |
||||
|
||||
#[test] |
||||
fn trim_start_colors() { |
||||
assert_eq!(trim_start_color("foo^2bar"), ("", "foo^2bar")); |
||||
assert_eq!(trim_start_color("^foo^2bar"), ("", "^foo^2bar")); |
||||
assert_eq!(trim_start_color("^1foo^2bar"), ("^1", "foo^2bar")); |
||||
} |
||||
|
||||
#[test] |
||||
fn trim_colors() { |
||||
assert_eq!(trim_color("foo^2bar"), "foobar"); |
||||
assert_eq!(trim_color("^1foo^2bar^3"), "foobar"); |
||||
assert_eq!(trim_color("^1foo^2bar^3"), "foobar"); |
||||
assert_eq!(trim_color("^1foo^bar^3"), "foo^bar"); |
||||
assert_eq!(trim_color("^1foo^2bar^"), "foobar^"); |
||||
assert_eq!(trim_color("^foo^bar^"), "^foo^bar^"); |
||||
} |
||||
} |
Loading…
Reference in new issue