1 //! Terminal [`Styles`] for help and error output
2 
3 pub use anstyle::*;
4 
5 /// Terminal styling definitions
6 ///
7 /// See also [`Command::styles`][crate::Command::styles].
8 ///
9 /// # Example
10 ///
11 /// clap v3 styling
12 /// ```rust
13 /// # use clap_builder as clap;
14 /// # use clap::builder::styling::*;
15 /// let styles = Styles::styled()
16 ///     .header(AnsiColor::Yellow.on_default())
17 ///     .usage(AnsiColor::Green.on_default())
18 ///     .literal(AnsiColor::Green.on_default())
19 ///     .placeholder(AnsiColor::Green.on_default());
20 /// ```
21 #[derive(Clone, Debug)]
22 #[allow(missing_copy_implementations)] // Large enough type that I want an explicit `clone()` for now
23 pub struct Styles {
24     header: anstyle::Style,
25     error: anstyle::Style,
26     usage: anstyle::Style,
27     literal: anstyle::Style,
28     placeholder: anstyle::Style,
29     valid: anstyle::Style,
30     invalid: anstyle::Style,
31 }
32 
33 impl Styles {
34     /// No terminal styling
plain() -> Self35     pub const fn plain() -> Self {
36         Self {
37             header: anstyle::Style::new(),
38             error: anstyle::Style::new(),
39             usage: anstyle::Style::new(),
40             literal: anstyle::Style::new(),
41             placeholder: anstyle::Style::new(),
42             valid: anstyle::Style::new(),
43             invalid: anstyle::Style::new(),
44         }
45     }
46 
47     /// Default terminal styling
styled() -> Self48     pub const fn styled() -> Self {
49         #[cfg(feature = "color")]
50         {
51             Self {
52                 header: anstyle::Style::new().bold().underline(),
53                 error: anstyle::Style::new()
54                     .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Red)))
55                     .bold(),
56                 usage: anstyle::Style::new().bold().underline(),
57                 literal: anstyle::Style::new().bold(),
58                 placeholder: anstyle::Style::new(),
59                 valid: anstyle::Style::new()
60                     .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Green))),
61                 invalid: anstyle::Style::new()
62                     .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Yellow))),
63             }
64         }
65         #[cfg(not(feature = "color"))]
66         {
67             Self::plain()
68         }
69     }
70 
71     /// General Heading style, e.g. [`help_heading`][crate::Arg::help_heading]
72     #[inline]
header(mut self, style: anstyle::Style) -> Self73     pub const fn header(mut self, style: anstyle::Style) -> Self {
74         self.header = style;
75         self
76     }
77 
78     /// Error heading
79     #[inline]
error(mut self, style: anstyle::Style) -> Self80     pub const fn error(mut self, style: anstyle::Style) -> Self {
81         self.error = style;
82         self
83     }
84 
85     /// Usage heading
86     #[inline]
usage(mut self, style: anstyle::Style) -> Self87     pub const fn usage(mut self, style: anstyle::Style) -> Self {
88         self.usage = style;
89         self
90     }
91 
92     /// Literal command-line syntax, e.g. `--help`
93     #[inline]
literal(mut self, style: anstyle::Style) -> Self94     pub const fn literal(mut self, style: anstyle::Style) -> Self {
95         self.literal = style;
96         self
97     }
98 
99     /// Descriptions within command-line syntax, e.g. [`value_name`][crate::Arg::value_name]
100     #[inline]
placeholder(mut self, style: anstyle::Style) -> Self101     pub const fn placeholder(mut self, style: anstyle::Style) -> Self {
102         self.placeholder = style;
103         self
104     }
105 
106     /// Highlight suggested usage
107     #[inline]
valid(mut self, style: anstyle::Style) -> Self108     pub const fn valid(mut self, style: anstyle::Style) -> Self {
109         self.valid = style;
110         self
111     }
112 
113     /// Highlight invalid usage
114     #[inline]
invalid(mut self, style: anstyle::Style) -> Self115     pub const fn invalid(mut self, style: anstyle::Style) -> Self {
116         self.invalid = style;
117         self
118     }
119 }
120 
121 /// Reflection
122 impl Styles {
123     /// General Heading style, e.g. [`help_heading`][crate::Arg::help_heading]
124     #[inline(always)]
get_header(&self) -> &anstyle::Style125     pub const fn get_header(&self) -> &anstyle::Style {
126         &self.header
127     }
128 
129     /// Error heading
130     #[inline(always)]
get_error(&self) -> &anstyle::Style131     pub const fn get_error(&self) -> &anstyle::Style {
132         &self.error
133     }
134 
135     /// Usage heading
136     #[inline(always)]
get_usage(&self) -> &anstyle::Style137     pub const fn get_usage(&self) -> &anstyle::Style {
138         &self.usage
139     }
140 
141     /// Literal command-line syntax, e.g. `--help`
142     #[inline(always)]
get_literal(&self) -> &anstyle::Style143     pub const fn get_literal(&self) -> &anstyle::Style {
144         &self.literal
145     }
146 
147     /// Descriptions within command-line syntax, e.g. [`value_name`][crate::Arg::value_name]
148     #[inline(always)]
get_placeholder(&self) -> &anstyle::Style149     pub const fn get_placeholder(&self) -> &anstyle::Style {
150         &self.placeholder
151     }
152 
153     /// Highlight suggested usage
154     #[inline(always)]
get_valid(&self) -> &anstyle::Style155     pub const fn get_valid(&self) -> &anstyle::Style {
156         &self.valid
157     }
158 
159     /// Highlight invalid usage
160     #[inline(always)]
get_invalid(&self) -> &anstyle::Style161     pub const fn get_invalid(&self) -> &anstyle::Style {
162         &self.invalid
163     }
164 }
165 
166 impl super::AppTag for Styles {}
167 
168 impl Default for Styles {
default() -> Self169     fn default() -> Self {
170         Self::styled()
171     }
172 }
173 
174 impl Default for &'_ Styles {
default() -> Self175     fn default() -> Self {
176         const STYLES: Styles = Styles::styled();
177         &STYLES
178     }
179 }
180