1//! Terminal [`Styles`] for help and error output
2
3pub 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
23pub 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
33impl Styles {
34 /// No terminal styling
35 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
48 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]
73 pub const fn header(mut self, style: anstyle::Style) -> Self {
74 self.header = style;
75 self
76 }
77
78 /// Error heading
79 #[inline]
80 pub const fn error(mut self, style: anstyle::Style) -> Self {
81 self.error = style;
82 self
83 }
84
85 /// Usage heading
86 #[inline]
87 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]
94 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]
101 pub const fn placeholder(mut self, style: anstyle::Style) -> Self {
102 self.placeholder = style;
103 self
104 }
105
106 /// Highlight suggested usage
107 #[inline]
108 pub const fn valid(mut self, style: anstyle::Style) -> Self {
109 self.valid = style;
110 self
111 }
112
113 /// Highlight invalid usage
114 #[inline]
115 pub const fn invalid(mut self, style: anstyle::Style) -> Self {
116 self.invalid = style;
117 self
118 }
119}
120
121/// Reflection
122impl Styles {
123 /// General Heading style, e.g. [`help_heading`][crate::Arg::help_heading]
124 #[inline(always)]
125 pub const fn get_header(&self) -> &anstyle::Style {
126 &self.header
127 }
128
129 /// Error heading
130 #[inline(always)]
131 pub const fn get_error(&self) -> &anstyle::Style {
132 &self.error
133 }
134
135 /// Usage heading
136 #[inline(always)]
137 pub const fn get_usage(&self) -> &anstyle::Style {
138 &self.usage
139 }
140
141 /// Literal command-line syntax, e.g. `--help`
142 #[inline(always)]
143 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)]
149 pub const fn get_placeholder(&self) -> &anstyle::Style {
150 &self.placeholder
151 }
152
153 /// Highlight suggested usage
154 #[inline(always)]
155 pub const fn get_valid(&self) -> &anstyle::Style {
156 &self.valid
157 }
158
159 /// Highlight invalid usage
160 #[inline(always)]
161 pub const fn get_invalid(&self) -> &anstyle::Style {
162 &self.invalid
163 }
164}
165
166impl super::AppTag for Styles {}
167
168impl Default for Styles {
169 fn default() -> Self {
170 Self::styled()
171 }
172}
173
174impl Default for &'_ Styles {
175 fn default() -> Self {
176 const STYLES: Styles = Styles::styled();
177 &STYLES
178 }
179}
180