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}