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