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