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: Style, |
25 | error: Style, |
26 | usage: Style, |
27 | literal: Style, |
28 | placeholder: Style, |
29 | valid: Style, |
30 | invalid: Style, |
31 | } |
32 | |
33 | impl Styles { |
34 | /// No terminal styling |
35 | pub const fn plain() -> Self { |
36 | Self { |
37 | header: Style::new(), |
38 | error: Style::new(), |
39 | usage: Style::new(), |
40 | literal: Style::new(), |
41 | placeholder: Style::new(), |
42 | valid: Style::new(), |
43 | invalid: Style::new(), |
44 | } |
45 | } |
46 | |
47 | /// Default terminal styling |
48 | pub const fn styled() -> Self { |
49 | #[cfg (feature = "color" )] |
50 | { |
51 | Self { |
52 | header: Style::new().bold().underline(), |
53 | error: Style::new() |
54 | .fg_color(Some(Color::Ansi(AnsiColor::Red))) |
55 | .bold(), |
56 | usage: Style::new().bold().underline(), |
57 | literal: Style::new().bold(), |
58 | placeholder: Style::new(), |
59 | valid: Style::new().fg_color(Some(Color::Ansi(AnsiColor::Green))), |
60 | invalid: Style::new().fg_color(Some(Color::Ansi(AnsiColor::Yellow))), |
61 | } |
62 | } |
63 | #[cfg (not(feature = "color" ))] |
64 | { |
65 | Self::plain() |
66 | } |
67 | } |
68 | |
69 | /// General Heading style, e.g. [`help_heading`][crate::Arg::help_heading] |
70 | #[inline ] |
71 | pub const fn header(mut self, style: Style) -> Self { |
72 | self.header = style; |
73 | self |
74 | } |
75 | |
76 | /// Error heading |
77 | #[inline ] |
78 | pub const fn error(mut self, style: Style) -> Self { |
79 | self.error = style; |
80 | self |
81 | } |
82 | |
83 | /// Usage heading |
84 | #[inline ] |
85 | pub const fn usage(mut self, style: Style) -> Self { |
86 | self.usage = style; |
87 | self |
88 | } |
89 | |
90 | /// Literal command-line syntax, e.g. `--help` |
91 | #[inline ] |
92 | pub const fn literal(mut self, style: Style) -> Self { |
93 | self.literal = style; |
94 | self |
95 | } |
96 | |
97 | /// Descriptions within command-line syntax, e.g. [`value_name`][crate::Arg::value_name] |
98 | #[inline ] |
99 | pub const fn placeholder(mut self, style: Style) -> Self { |
100 | self.placeholder = style; |
101 | self |
102 | } |
103 | |
104 | /// Highlight suggested usage |
105 | #[inline ] |
106 | pub const fn valid(mut self, style: Style) -> Self { |
107 | self.valid = style; |
108 | self |
109 | } |
110 | |
111 | /// Highlight invalid usage |
112 | #[inline ] |
113 | pub const fn invalid(mut self, style: Style) -> Self { |
114 | self.invalid = style; |
115 | self |
116 | } |
117 | } |
118 | |
119 | /// Reflection |
120 | impl Styles { |
121 | /// General Heading style, e.g. [`help_heading`][crate::Arg::help_heading] |
122 | #[inline (always)] |
123 | pub const fn get_header(&self) -> &Style { |
124 | &self.header |
125 | } |
126 | |
127 | /// Error heading |
128 | #[inline (always)] |
129 | pub const fn get_error(&self) -> &Style { |
130 | &self.error |
131 | } |
132 | |
133 | /// Usage heading |
134 | #[inline (always)] |
135 | pub const fn get_usage(&self) -> &Style { |
136 | &self.usage |
137 | } |
138 | |
139 | /// Literal command-line syntax, e.g. `--help` |
140 | #[inline (always)] |
141 | pub const fn get_literal(&self) -> &Style { |
142 | &self.literal |
143 | } |
144 | |
145 | /// Descriptions within command-line syntax, e.g. [`value_name`][crate::Arg::value_name] |
146 | #[inline (always)] |
147 | pub const fn get_placeholder(&self) -> &Style { |
148 | &self.placeholder |
149 | } |
150 | |
151 | /// Highlight suggested usage |
152 | #[inline (always)] |
153 | pub const fn get_valid(&self) -> &Style { |
154 | &self.valid |
155 | } |
156 | |
157 | /// Highlight invalid usage |
158 | #[inline (always)] |
159 | pub const fn get_invalid(&self) -> &Style { |
160 | &self.invalid |
161 | } |
162 | } |
163 | |
164 | impl super::AppExt for Styles {} |
165 | |
166 | impl Default for Styles { |
167 | fn default() -> Self { |
168 | Self::styled() |
169 | } |
170 | } |
171 | |
172 | impl Default for &'_ Styles { |
173 | fn default() -> Self { |
174 | const STYLES: Styles = Styles::styled(); |
175 | &STYLES |
176 | } |
177 | } |
178 | |