1 | use std::{ |
2 | borrow::Cow, |
3 | fmt::{self, Write}, |
4 | }; |
5 | |
6 | use super::{Color, StaticColor}; |
7 | |
8 | /// The structure represents a ANSI color by suffix and prefix. |
9 | #[derive (Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)] |
10 | pub struct AnsiColor<'a> { |
11 | prefix: Cow<'a, str>, |
12 | suffix: Cow<'a, str>, |
13 | } |
14 | |
15 | impl<'a> AnsiColor<'a> { |
16 | /// Constructs a new instance with suffix and prefix. |
17 | /// |
18 | /// They are not checked so you should make sure you provide correct ANSI. |
19 | /// Otherwise you may want to use [`TryFrom`]. |
20 | /// |
21 | /// [`TryFrom`]: std::convert::TryFrom |
22 | pub const fn new(prefix: Cow<'a, str>, suffix: Cow<'a, str>) -> Self { |
23 | Self { prefix, suffix } |
24 | } |
25 | } |
26 | |
27 | impl AnsiColor<'_> { |
28 | /// Gets a reference to a prefix. |
29 | pub fn get_prefix(&self) -> &str { |
30 | &self.prefix |
31 | } |
32 | |
33 | /// Gets a reference to a suffix. |
34 | pub fn get_suffix(&self) -> &str { |
35 | &self.suffix |
36 | } |
37 | } |
38 | |
39 | impl Color for AnsiColor<'_> { |
40 | fn fmt_prefix<W: Write>(&self, f: &mut W) -> fmt::Result { |
41 | f.write_str(&self.prefix) |
42 | } |
43 | |
44 | fn fmt_suffix<W: Write>(&self, f: &mut W) -> fmt::Result { |
45 | f.write_str(&self.suffix) |
46 | } |
47 | } |
48 | |
49 | #[cfg (feature = "color" )] |
50 | impl std::convert::TryFrom<&str> for AnsiColor<'static> { |
51 | type Error = (); |
52 | |
53 | fn try_from(value: &str) -> Result<Self, Self::Error> { |
54 | parse_ansi_color(value).ok_or(()) |
55 | } |
56 | } |
57 | |
58 | #[cfg (feature = "color" )] |
59 | impl std::convert::TryFrom<String> for AnsiColor<'static> { |
60 | type Error = (); |
61 | |
62 | fn try_from(value: String) -> Result<Self, Self::Error> { |
63 | Self::try_from(value.as_str()) |
64 | } |
65 | } |
66 | |
67 | #[cfg (feature = "color" )] |
68 | fn parse_ansi_color(s: &str) -> Option<AnsiColor<'static>> { |
69 | let mut blocks = ansi_str::get_blocks(s); |
70 | let block = blocks.next()?; |
71 | let style = block.style(); |
72 | |
73 | let start = style.start().to_string(); |
74 | let end = style.end().to_string(); |
75 | |
76 | Some(AnsiColor::new(start.into(), end.into())) |
77 | } |
78 | |
79 | impl From<StaticColor> for AnsiColor<'static> { |
80 | fn from(value: StaticColor) -> Self { |
81 | Self::new( |
82 | prefix:Cow::Borrowed(value.get_prefix()), |
83 | suffix:Cow::Borrowed(value.get_suffix()), |
84 | ) |
85 | } |
86 | } |
87 | |