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 |
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 |
122 | impl 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 | |
166 | impl super::AppTag for Styles {} |
167 | |
168 | impl Default for Styles { |
169 | fn default() -> Self { |
170 | Self::styled() |
171 | } |
172 | } |
173 | |
174 | impl Default for &'_ Styles { |
175 | fn default() -> Self { |
176 | const STYLES: Styles = Styles::styled(); |
177 | &STYLES |
178 | } |
179 | } |
180 | |