inquire/ui/render_config.rs
1use std::env;
2
3use super::{Color, StyleSheet, Styled};
4
5/// Rendering configuration that can be applied to a prompt.
6///
7/// Render configurations can set mostly style sheets for particular
8/// parts of the prompt layout. Additionally, it allows you to set
9/// the content of a few tokens, such as prompt or error message prefixes.
10///
11/// # Example
12///
13/// ```
14/// use inquire::ui::{Color, RenderConfig, Styled};
15///
16/// let empty: RenderConfig = RenderConfig::empty();
17/// let default: RenderConfig = RenderConfig::default();
18///
19/// let prompt_prefix = Styled::new("$").with_fg(Color::DarkRed);
20/// let mine = default.with_prompt_prefix(prompt_prefix);
21/// ```
22#[derive(Copy, Clone, Debug)]
23pub struct RenderConfig {
24 /// Prefix added before prompts.
25 ///
26 /// Note: a space character will be added to separate the prefix
27 /// and the prompt message.
28 pub prompt_prefix: Styled<&'static str>,
29
30 /// Prefix added before answered prompts.
31 ///
32 /// Note: a space character will be added to separate the prefix
33 /// and the prompt message.
34 pub answered_prompt_prefix: Styled<&'static str>,
35
36 /// Style of the prompt message, applicable to all prompt types.
37 pub prompt: StyleSheet,
38
39 /// Render configuration of default values.
40 ///
41 /// Note: default values are displayed wrapped in parenthesis, e.g. (yes).
42 /// Non-styled space characters is added before the default value display
43 /// and after the default value, as separators.
44 pub default_value: StyleSheet,
45
46 /// Render configuration of placeholders.
47 ///
48 /// Note: placeholders are displayed wrapped in parenthesis, e.g. (yes).
49 /// Non-styled space characters is added before the default value display
50 /// and after the default value, as separators.
51 pub placeholder: StyleSheet,
52
53 /// Render configuration of help messages.
54 ///
55 /// Note: help messages are displayed wrapped in brackets, e.g. [Be careful!].
56 pub help_message: StyleSheet,
57
58 /// Character used to mask password text inputs when in mode
59 /// [`Masked`](crate::prompts::PasswordDisplayMode).
60 ///
61 /// Note: Styles for masked text inputs are set in the
62 /// [`text_input`](crate::ui::RenderConfig::text_input) configuration.
63 pub password_mask: char,
64
65 /// Style sheet for text inputs.
66 ///
67 /// Note: a non-styled space character is added before the text input as
68 /// a separator from the prompt message (or default value display).
69 pub text_input: StyleSheet,
70
71 /// Render configuration of final prompt answers (submissions).
72 ///
73 /// Note: a non-styled space character is added before the answer as
74 /// a separator from the prompt message (or default value display).
75 pub answer: StyleSheet,
76
77 /// Render configuration of the message printed in the place of an answer
78 /// when the prompt is canceled by the user - by pressing ESC.
79 ///
80 /// Note: a non-styled space character is added before the indicator as
81 /// a separator from the prompt message.
82 pub canceled_prompt_indicator: Styled<&'static str>,
83
84 /// Render configuration for error messages.
85 pub error_message: ErrorMessageRenderConfig,
86
87 /// Prefix for the current highlighted option.
88 ///
89 /// Note: a space character will be added to separate the prefix
90 /// and the option value or the checkbox.
91 pub highlighted_option_prefix: Styled<&'static str>,
92
93 /// Prefix for the option listed at the top of the page, when it is possible
94 /// to scroll up.
95 ///
96 /// Note: a space character will be added to separate the prefix
97 /// and the option value or the checkbox.
98 pub scroll_up_prefix: Styled<&'static str>,
99
100 /// Prefix for the option listed at the bottom of the page, when it is possible
101 /// to scroll down.
102 ///
103 /// Note: a space character will be added to separate the prefix
104 /// and the option value or the checkbox.
105 pub scroll_down_prefix: Styled<&'static str>,
106
107 /// Selected checkbox in multi-select options.
108 ///
109 /// Note: a space character will be added to separate the checkbox
110 /// from a possible prefix, and to separate the checkbox from the
111 /// option value to the right.
112 pub selected_checkbox: Styled<&'static str>,
113
114 /// Unselected checkbox in multi-select options.
115 ///
116 /// Note: a space character will be added to separate the checkbox
117 /// from a possible prefix, and to separate the checkbox from the
118 /// option value to the right.
119 pub unselected_checkbox: Styled<&'static str>,
120
121 /// Definition of index prefixes in option lists.
122 pub option_index_prefix: IndexPrefix,
123
124 /// Style sheet for options.
125 ///
126 /// Note: a non-styled space character is added before the option value as
127 /// a separator from the prefix.
128 pub option: StyleSheet,
129
130 /// Style sheet for the option that is currently selected. If the value is
131 /// None, it will fall back to `option`.
132 ///
133 /// Note: a non-styled space character is added before the option value as
134 /// a separator from the prefix.
135 pub selected_option: Option<StyleSheet>,
136
137 /// Render configuration for calendar
138
139 #[cfg(feature = "date")]
140 /// Render configuration for date prompts`
141 pub calendar: calendar::CalendarRenderConfig,
142
143 /// Style sheet of the hint in editor prompts.
144 ///
145 /// The hint is formatted as `[(e) to open {}, (enter) to submit]`
146 /// with the editor name.
147 #[cfg(feature = "editor")]
148 pub editor_prompt: StyleSheet,
149}
150
151impl RenderConfig {
152 /// RenderConfig in which no colors or attributes are applied.
153 pub fn empty() -> Self {
154 Self {
155 prompt_prefix: Styled::new("?"),
156 answered_prompt_prefix: Styled::new("?"),
157 prompt: StyleSheet::empty(),
158 default_value: StyleSheet::empty(),
159 placeholder: StyleSheet::empty(),
160 help_message: StyleSheet::empty(),
161 text_input: StyleSheet::empty(),
162 error_message: ErrorMessageRenderConfig::empty(),
163 answer: StyleSheet::empty(),
164 canceled_prompt_indicator: Styled::new("<canceled>"),
165 password_mask: '*',
166 highlighted_option_prefix: Styled::new(">"),
167 scroll_up_prefix: Styled::new("^"),
168 scroll_down_prefix: Styled::new("v"),
169 selected_checkbox: Styled::new("[x]"),
170 unselected_checkbox: Styled::new("[ ]"),
171 option_index_prefix: IndexPrefix::None,
172 option: StyleSheet::empty(),
173 selected_option: None,
174
175 #[cfg(feature = "date")]
176 calendar: calendar::CalendarRenderConfig::empty(),
177
178 #[cfg(feature = "editor")]
179 editor_prompt: StyleSheet::empty(),
180 }
181 }
182
183 /// RenderConfig where default colors and attributes are applied.
184 pub fn default_colored() -> Self {
185 Self {
186 prompt_prefix: Styled::new("?").with_fg(Color::LightGreen),
187 answered_prompt_prefix: Styled::new(">").with_fg(Color::LightGreen),
188 prompt: StyleSheet::empty(),
189 default_value: StyleSheet::empty(),
190 placeholder: StyleSheet::new().with_fg(Color::DarkGrey),
191 help_message: StyleSheet::empty().with_fg(Color::LightCyan),
192 text_input: StyleSheet::empty(),
193 error_message: ErrorMessageRenderConfig::default_colored(),
194 password_mask: '*',
195 answer: StyleSheet::empty().with_fg(Color::LightCyan),
196 canceled_prompt_indicator: Styled::new("<canceled>").with_fg(Color::DarkRed),
197 highlighted_option_prefix: Styled::new(">").with_fg(Color::LightCyan),
198 scroll_up_prefix: Styled::new("^"),
199 scroll_down_prefix: Styled::new("v"),
200 selected_checkbox: Styled::new("[x]").with_fg(Color::LightGreen),
201 unselected_checkbox: Styled::new("[ ]"),
202 option_index_prefix: IndexPrefix::None,
203 option: StyleSheet::empty(),
204 selected_option: Some(StyleSheet::new().with_fg(Color::LightCyan)),
205
206 #[cfg(feature = "date")]
207 calendar: calendar::CalendarRenderConfig::default_colored(),
208
209 #[cfg(feature = "editor")]
210 editor_prompt: StyleSheet::new().with_fg(Color::DarkCyan),
211 }
212 }
213
214 /// Sets the prompt prefix and its style sheet.
215 pub fn with_prompt_prefix(mut self, prompt_prefix: Styled<&'static str>) -> Self {
216 self.prompt_prefix = prompt_prefix;
217 self
218 }
219
220 /// Sets style for text inputs.
221 pub fn with_text_input(mut self, text_input: StyleSheet) -> Self {
222 self.text_input = text_input;
223 self
224 }
225
226 /// Sets the style sheet for default values.
227 pub fn with_default_value(mut self, default_value: StyleSheet) -> Self {
228 self.default_value = default_value;
229 self
230 }
231
232 /// Sets the style sheet for help messages.
233 pub fn with_help_message(mut self, help_message: StyleSheet) -> Self {
234 self.help_message = help_message;
235 self
236 }
237
238 /// Sets the style sheet for answers.
239 pub fn with_answer(mut self, answer: StyleSheet) -> Self {
240 self.answer = answer;
241 self
242 }
243
244 /// Sets the render configuration for error messages.
245 pub fn with_error_message(mut self, error_message: ErrorMessageRenderConfig) -> Self {
246 self.error_message = error_message;
247 self
248 }
249
250 /// Sets the styled component for prefixes in highlighted options.
251 pub fn with_highlighted_option_prefix(
252 mut self,
253 highlighted_option_prefix: Styled<&'static str>,
254 ) -> Self {
255 self.highlighted_option_prefix = highlighted_option_prefix;
256 self
257 }
258
259 /// Sets the styled component for prefixes in scroll-up indicators.
260 pub fn with_scroll_up_prefix(mut self, scroll_up_prefix: Styled<&'static str>) -> Self {
261 self.scroll_up_prefix = scroll_up_prefix;
262 self
263 }
264
265 /// Sets the styled component for prefixes in scroll-down indicators.
266 pub fn with_scroll_down_prefix(mut self, scroll_down_prefix: Styled<&'static str>) -> Self {
267 self.scroll_down_prefix = scroll_down_prefix;
268 self
269 }
270
271 /// Sets the styled component for selected checkboxes.
272 pub fn with_selected_checkbox(mut self, selected_checkbox: Styled<&'static str>) -> Self {
273 self.selected_checkbox = selected_checkbox;
274 self
275 }
276
277 /// Sets the styled component for unselected checkboxes.
278 pub fn with_unselected_checkbox(mut self, unselected_checkbox: Styled<&'static str>) -> Self {
279 self.unselected_checkbox = unselected_checkbox;
280 self
281 }
282
283 /// Sets the index prefix for option lists.
284 pub fn with_option_index_prefix(mut self, index_prefix: IndexPrefix) -> Self {
285 self.option_index_prefix = index_prefix;
286 self
287 }
288
289 /// Sets the style sheet for option values.
290 pub fn with_option(mut self, option: StyleSheet) -> Self {
291 self.option = option;
292 self
293 }
294
295 /// Sets the style sheet for currently selected option.
296 pub fn with_selected_option(mut self, selected_option: Option<StyleSheet>) -> Self {
297 self.selected_option = selected_option;
298 self
299 }
300
301 /// Sets the indicator for canceled prompts.
302 pub fn with_canceled_prompt_indicator(
303 mut self,
304 canceled_prompt_indicator: Styled<&'static str>,
305 ) -> Self {
306 self.canceled_prompt_indicator = canceled_prompt_indicator;
307 self
308 }
309
310 #[cfg(feature = "date")]
311 /// Sets the render configuration for calendars.
312 pub fn with_calendar_config(mut self, calendar: calendar::CalendarRenderConfig) -> Self {
313 self.calendar = calendar;
314 self
315 }
316
317 #[cfg(feature = "editor")]
318 /// Sets the render configuration for editor prompts.
319 pub fn with_editor_prompt(mut self, editor_prompt: StyleSheet) -> Self {
320 self.editor_prompt = editor_prompt;
321 self
322 }
323}
324
325impl Default for RenderConfig {
326 fn default() -> Self {
327 match env::var("NO_COLOR") {
328 Ok(_) => Self::empty(),
329 Err(_) => Self::default_colored(),
330 }
331 }
332}
333
334/// Definition of index prefixes in option lists.
335#[derive(Copy, Clone, Debug, PartialEq, Eq)]
336pub enum IndexPrefix {
337 /// Lists of options will not display any hints regarding
338 /// the position/index of the positions.
339 None,
340
341 /// A simple index (1-based) will be displayed before the
342 /// option string representation.
343 Simple,
344
345 /// A simple index (1-based) will be displayed before the
346 /// option string representation.
347 ///
348 /// The number representation of the index is padded with
349 /// spaces so that the length is the same of the largest
350 /// index. That is, if the list has 100 options, the first 9
351 /// options will be rendered as `" 1", " 2", ...`. Then all
352 /// indexes with two digits will be padded with one space, and
353 /// finally the last option with index 100 will not need to be
354 /// padded.
355 SpacePadded,
356
357 /// A simple index (1-based) will be displayed before the
358 /// option string representation.
359 ///
360 /// The number representation of the index is padded with
361 /// zeroes so that the length is the same of the largest
362 /// index. That is, if the list has 100 options, the first 9
363 /// options will be rendered as `"001", "002", ...`. Then all
364 /// indexes with two digits will be padded with one zero, and
365 /// finally the last option with index 100 will not need to be
366 /// padded.
367 ZeroPadded,
368}
369
370/// Render configuration for error messages.
371#[derive(Copy, Clone, Debug)]
372pub struct ErrorMessageRenderConfig {
373 /// Prefix style.
374 pub prefix: Styled<&'static str>,
375
376 /// Separator style.
377 ///
378 /// Note: This separator is a space character. It might be useful to
379 /// style it if you want to set a background color for error messages.
380 pub separator: StyleSheet,
381
382 /// Message style.
383 pub message: StyleSheet,
384
385 /// Default message used for validators that do not defined custom error messages.
386 pub default_message: &'static str,
387}
388
389impl ErrorMessageRenderConfig {
390 /// Render configuration in which no colors or attributes are applied.
391 pub fn empty() -> Self {
392 Self {
393 prefix: Styled::new("#"),
394 separator: StyleSheet::empty(),
395 message: StyleSheet::empty(),
396 default_message: "Invalid input.",
397 }
398 }
399
400 /// Render configuration where default colors and attributes are applied.
401 pub fn default_colored() -> Self {
402 Self {
403 prefix: Styled::new("#").with_fg(Color::LightRed),
404 separator: StyleSheet::empty(),
405 message: StyleSheet::empty().with_fg(Color::LightRed),
406 default_message: "Invalid input.",
407 }
408 }
409
410 /// Sets the prefix.
411 pub fn with_prefix(mut self, prefix: Styled<&'static str>) -> Self {
412 self.prefix = prefix;
413 self
414 }
415
416 /// Sets the separator stylesheet.
417 ///
418 /// Note: This separator is a space character. It might be useful to
419 /// style it if you want to set a background color for error messages.
420 pub fn with_separator(mut self, separator: StyleSheet) -> Self {
421 self.separator = separator;
422 self
423 }
424
425 /// Sets the message stylesheet.
426 pub fn with_message(mut self, message: StyleSheet) -> Self {
427 self.message = message;
428 self
429 }
430}
431
432#[cfg(feature = "date")]
433pub mod calendar {
434 //! Module containing additional render config for date prompts.
435
436 use super::{Color, StyleSheet, Styled};
437
438 /// Calendar configuration for error messages.
439 #[derive(Copy, Clone, Debug)]
440 pub struct CalendarRenderConfig {
441 /// Prefix style.
442 pub prefix: Styled<&'static str>,
443
444 /// Style sheet for the calendar header, e.g. january 2021.
445 pub header: StyleSheet,
446
447 /// Style sheet for the calendar week header, e.g. su mo tu we th fr sa.
448 pub week_header: StyleSheet,
449
450 /// Style sheet for the currently selected date.
451 ///
452 /// When `None`, no custom style sheet will be applied and the native
453 /// terminal cursor will be used in the first char of the date number.
454 ///
455 /// Whem `Some(_)`, the style sheet will be applied to the two columns
456 /// where the number is positioned, padded to spaces in the left if the
457 /// number only has one digit. e.g. " 5" or "23".
458 pub selected_date: Option<StyleSheet>,
459
460 /// Style sheet for today's date, just for hinting purposes.
461 pub today_date: StyleSheet,
462
463 /// Style sheet for dates that are from the previous or next month
464 /// displayed in the calendar.
465 pub different_month_date: StyleSheet,
466
467 /// Style sheet for dates that can not be selected due to the
468 /// min/max settings.
469 pub unavailable_date: StyleSheet,
470 }
471
472 impl CalendarRenderConfig {
473 /// Render configuration in which no colors or attributes are applied.
474 pub fn empty() -> Self {
475 Self {
476 prefix: Styled::new(">"),
477 header: StyleSheet::empty(),
478 week_header: StyleSheet::empty(),
479 selected_date: None,
480 today_date: StyleSheet::empty(),
481 different_month_date: StyleSheet::empty(),
482 unavailable_date: StyleSheet::empty(),
483 }
484 }
485
486 /// Render configuration where default colors and attributes are applied.
487 pub fn default_colored() -> Self {
488 Self {
489 prefix: Styled::new(">").with_fg(Color::LightGreen),
490 header: StyleSheet::empty(),
491 week_header: StyleSheet::empty(),
492 selected_date: Some(
493 StyleSheet::empty()
494 .with_fg(Color::Black)
495 .with_bg(Color::Grey),
496 ),
497 today_date: StyleSheet::empty().with_fg(Color::LightGreen),
498 different_month_date: StyleSheet::empty().with_fg(Color::DarkGrey),
499 unavailable_date: StyleSheet::empty().with_fg(Color::DarkGrey),
500 }
501 }
502
503 /// Sets the prefix.
504 pub fn with_prefix(mut self, prefix: Styled<&'static str>) -> Self {
505 self.prefix = prefix;
506 self
507 }
508 }
509}