papergrid/ansi/
ansi_buf.rs

1use std::fmt::{self, Write};
2
3use 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)]
7pub struct ANSIBuf {
8    prefix: String,
9    suffix: String,
10}
11
12impl 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
51impl 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")]
62impl 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")]
71impl 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")]
80fn 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
91impl From<ANSIStr<'_>> for ANSIBuf {
92    fn from(value: ANSIStr<'_>) -> Self {
93        Self::new(value.get_prefix(), value.get_suffix())
94    }
95}