1use std::collections::HashSet;
2use std::str::FromStr;
3
4use crate::error::*;
5
6#[non_exhaustive]
7#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
8pub enum StyleComponent {
9 Auto,
10 #[cfg(feature = "git")]
11 Changes,
12 Grid,
13 Rule,
14 Header,
15 HeaderFilename,
16 HeaderFilesize,
17 LineNumbers,
18 Snip,
19 Full,
20 Default,
21 Plain,
22}
23
24impl StyleComponent {
25 pub fn components(self, interactive_terminal: bool) -> &'static [StyleComponent] {
26 match self {
27 StyleComponent::Auto => {
28 if interactive_terminal {
29 StyleComponent::Default.components(interactive_terminal)
30 } else {
31 StyleComponent::Plain.components(interactive_terminal)
32 }
33 }
34 #[cfg(feature = "git")]
35 StyleComponent::Changes => &[StyleComponent::Changes],
36 StyleComponent::Grid => &[StyleComponent::Grid],
37 StyleComponent::Rule => &[StyleComponent::Rule],
38 StyleComponent::Header => &[StyleComponent::HeaderFilename],
39 StyleComponent::HeaderFilename => &[StyleComponent::HeaderFilename],
40 StyleComponent::HeaderFilesize => &[StyleComponent::HeaderFilesize],
41 StyleComponent::LineNumbers => &[StyleComponent::LineNumbers],
42 StyleComponent::Snip => &[StyleComponent::Snip],
43 StyleComponent::Full => &[
44 #[cfg(feature = "git")]
45 StyleComponent::Changes,
46 StyleComponent::Grid,
47 StyleComponent::HeaderFilename,
48 StyleComponent::HeaderFilesize,
49 StyleComponent::LineNumbers,
50 StyleComponent::Snip,
51 ],
52 StyleComponent::Default => &[
53 #[cfg(feature = "git")]
54 StyleComponent::Changes,
55 StyleComponent::Grid,
56 StyleComponent::HeaderFilename,
57 StyleComponent::LineNumbers,
58 StyleComponent::Snip,
59 ],
60 StyleComponent::Plain => &[],
61 }
62 }
63}
64
65impl FromStr for StyleComponent {
66 type Err = Error;
67
68 fn from_str(s: &str) -> Result<Self> {
69 match s {
70 "auto" => Ok(StyleComponent::Auto),
71 #[cfg(feature = "git")]
72 "changes" => Ok(StyleComponent::Changes),
73 "grid" => Ok(StyleComponent::Grid),
74 "rule" => Ok(StyleComponent::Rule),
75 "header" => Ok(StyleComponent::Header),
76 "header-filename" => Ok(StyleComponent::HeaderFilename),
77 "header-filesize" => Ok(StyleComponent::HeaderFilesize),
78 "numbers" => Ok(StyleComponent::LineNumbers),
79 "snip" => Ok(StyleComponent::Snip),
80 "full" => Ok(StyleComponent::Full),
81 "default" => Ok(StyleComponent::Default),
82 "plain" => Ok(StyleComponent::Plain),
83 _ => Err(format!("Unknown style '{}'", s).into()),
84 }
85 }
86}
87
88#[derive(Debug, Clone, Default)]
89pub struct StyleComponents(pub HashSet<StyleComponent>);
90
91impl StyleComponents {
92 pub fn new(components: &[StyleComponent]) -> StyleComponents {
93 StyleComponents(components.iter().cloned().collect())
94 }
95
96 #[cfg(feature = "git")]
97 pub fn changes(&self) -> bool {
98 self.0.contains(&StyleComponent::Changes)
99 }
100
101 pub fn grid(&self) -> bool {
102 self.0.contains(&StyleComponent::Grid)
103 }
104
105 pub fn rule(&self) -> bool {
106 self.0.contains(&StyleComponent::Rule)
107 }
108
109 pub fn header(&self) -> bool {
110 self.header_filename() || self.header_filesize()
111 }
112
113 pub fn header_filename(&self) -> bool {
114 self.0.contains(&StyleComponent::HeaderFilename)
115 }
116
117 pub fn header_filesize(&self) -> bool {
118 self.0.contains(&StyleComponent::HeaderFilesize)
119 }
120
121 pub fn numbers(&self) -> bool {
122 self.0.contains(&StyleComponent::LineNumbers)
123 }
124
125 pub fn snip(&self) -> bool {
126 self.0.contains(&StyleComponent::Snip)
127 }
128
129 pub fn plain(&self) -> bool {
130 self.0.iter().all(|c| c == &StyleComponent::Plain)
131 }
132}