diff --git a/src/prompts/confirm.rs b/src/prompts/confirm.rs index 328f792f..f182b741 100644 --- a/src/prompts/confirm.rs +++ b/src/prompts/confirm.rs @@ -4,7 +4,7 @@ use crate::theme::{SimpleTheme, TermThemeRenderer, Theme}; use console::{Key, Term}; -/// Renders a confirm prompt. +/// Render a confirmation prompt. /// /// ## Example usage /// @@ -20,10 +20,15 @@ use console::{Key, Term}; /// # Ok(()) } fn main() { test().unwrap(); } /// ``` pub struct Confirm<'a> { + /// Message of the confirmation prompt. prompt: String, + /// Whether to report the user's choice after selection. report: bool, + /// default option for the prompt (if any) default: Option, + /// if true, show the default value to the user, see [`show_default`](#method::show_default) show_default: bool, + /// when to react to user input, see [`wait_for_newline`](#methhod::wait_for_newline) wait_for_newline: bool, theme: &'a dyn Theme, } @@ -35,20 +40,20 @@ impl Default for Confirm<'static> { } impl Confirm<'static> { - /// Creates a confirm prompt. + /// Create a confirmation prompt. pub fn new() -> Self { Self::with_theme(&SimpleTheme) } } impl Confirm<'_> { - /// Sets the confirm prompt. + /// Set the confirmation prompt message. pub fn with_prompt>(&mut self, prompt: S) -> &mut Self { self.prompt = prompt.into(); self } - /// Indicates whether or not to report the chosen selection after interaction. + /// Indicate whether or not to report the chosen selection after interaction. /// /// The default is to report the chosen selection. pub fn report(&mut self, val: bool) -> &mut Self { @@ -76,17 +81,17 @@ impl Confirm<'_> { self } - /// Sets a default. + /// Set a default choice for the prompt. /// - /// Out of the box the prompt does not have a default and will continue - /// to display until the user inputs something and hits enter. If a default is set the user - /// can instead accept the default with enter. + /// Out of the box, the prompt does not have a default choice and will continue + /// to display until the user inputs something and hits enter. If a default is set, + /// the user can also accept the default with enter. pub fn default(&mut self, val: bool) -> &mut Self { self.default = Some(val); self } - /// Disables or enables the default value display. + /// Disable or enable the default value display. /// /// The default is to append the default value to the prompt to tell the user. pub fn show_default(&mut self, val: bool) -> &mut Self { @@ -94,29 +99,32 @@ impl Confirm<'_> { self } - /// Enables user interaction and returns the result. + /// Enable user interaction and return the result. /// /// The dialog is rendered on stderr. /// - /// Result contains `bool` if user answered "yes" or "no" or `default` (configured in [`default`](Self::default) if pushes enter. - /// This unlike [`interact_opt`](Self::interact_opt) does not allow to quit with 'Esc' or 'q'. + /// Result contains `bool` if the user answered "yes" or "no" or `default` + /// (configured in [`default`](Self::default)) if they pushed enter. + /// Unlike [`interact_opt`](Self::interact_opt), this does not allow + /// to quit the dialog with 'Esc' or 'q'. #[inline] pub fn interact(&self) -> io::Result { self.interact_on(&Term::stderr()) } - /// Enables user interaction and returns the result. + /// Enable user interaction and return the result. /// /// The dialog is rendered on stderr. /// - /// Result contains `Some(bool)` if user answered "yes" or "no" or `Some(default)` (configured in [`default`](Self::default)) if pushes enter, - /// or `None` if user cancelled with 'Esc' or 'q'. + /// Result contains `Some(bool)` if the user answered "yes" or "no" or `Some(default)` + /// (configured in [`default`](Self::default)) if they pushed enter, + /// or `None` if the user cancelled the prompt with 'Esc' or 'q'. #[inline] pub fn interact_opt(&self) -> io::Result> { self.interact_on_opt(&Term::stderr()) } - /// Like [interact](#method.interact) but allows a specific terminal to be set. + /// Like [interact](#method.interact) but allow a specific terminal to be set. /// /// ## Examples /// @@ -178,7 +186,7 @@ impl Confirm<'_> { let rv; if self.wait_for_newline { - // Waits for user input and for the user to hit the Enter key + // Wait for user input and for the user to hit the Enter key // before validation. let mut value = default_if_show; @@ -215,8 +223,8 @@ impl Confirm<'_> { render.confirm_prompt(&self.prompt, value)?; } } else { - // Default behavior: matches continuously on every keystroke, - // and does not wait for user to hit the Enter key. + // Default behavior: match continuously on every keystroke, + // and do not wait for the user to hit the Enter key. loop { let input = term.read_key()?; let value = match input { @@ -246,7 +254,7 @@ impl Confirm<'_> { } impl<'a> Confirm<'a> { - /// Creates a confirm prompt with a specific theme. + /// Create a confirm prompt with a specific theme. /// /// ## Examples /// ```rust,no_run diff --git a/src/prompts/password.rs b/src/prompts/password.rs index c419d645..cbf94a17 100644 --- a/src/prompts/password.rs +++ b/src/prompts/password.rs @@ -5,7 +5,7 @@ use crate::theme::{SimpleTheme, TermThemeRenderer, Theme}; use console::Term; use zeroize::Zeroizing; -/// Renders a password input prompt. +/// Render a password input prompt. /// /// ## Example usage /// @@ -20,10 +20,14 @@ use zeroize::Zeroizing; /// # Ok(()) } fn main() { test().unwrap(); } /// ``` pub struct Password<'a> { + /// Message of the confirmation prompt. prompt: String, + /// Whether to print a confirmation message after selecting a password. report: bool, theme: &'a dyn Theme, + /// Whether an empty password is allowed. allow_empty_password: bool, + // Confirmation prompt for passwords: see [`with_confirmation`](#method::with_confirmation). confirmation_prompt: Option<(String, String)>, } @@ -34,20 +38,20 @@ impl Default for Password<'static> { } impl Password<'static> { - /// Creates a password input prompt. + /// Create a password input prompt. pub fn new() -> Password<'static> { Self::with_theme(&SimpleTheme) } } impl Password<'_> { - /// Sets the password input prompt. + /// Set the password input prompt. pub fn with_prompt>(&mut self, prompt: S) -> &mut Self { self.prompt = prompt.into(); self } - /// Indicates whether to report confirmation after interaction. + /// Indicate whether to report a confirmation after interaction. /// /// The default is to report. pub fn report(&mut self, val: bool) -> &mut Self { @@ -55,7 +59,11 @@ impl Password<'_> { self } - /// Enables confirmation prompting. + /// Enable prompting for confirmation of the password: + /// if set, the user must type the same password again to confirm their choice. + /// + /// `prompt` is the prompt message for the confirmation prompt, + /// `mismatch_err` the error message printed upon mismatching passwords. pub fn with_confirmation(&mut self, prompt: A, mismatch_err: B) -> &mut Self where A: Into, @@ -65,15 +73,15 @@ impl Password<'_> { self } - /// Allows/Disables empty password. + /// Allow/disallow entering an empty password. /// - /// By default this setting is set to false (i.e. password is not empty). + /// By default this setting is set to false (i.e. empty passwords are not allowed). pub fn allow_empty_password(&mut self, allow_empty_password: bool) -> &mut Self { self.allow_empty_password = allow_empty_password; self } - /// Enables user interaction and returns the result. + /// Enable user interaction and return the result. /// /// If the user confirms the result is `true`, `false` otherwise. /// The dialog is rendered on stderr. @@ -81,11 +89,9 @@ impl Password<'_> { self.interact_on(&Term::stderr()) } - /// Like `interact` but allows a specific terminal to be set. + /// Like [`interact`](#method::interact), but allow a specific terminal to be set. pub fn interact_on(&self, term: &Term) -> io::Result { let mut render = TermThemeRenderer::new(term, self.theme); - render.set_prompts_reset_height(false); - loop { let password = Zeroizing::new(self.prompt_password(&mut render, &self.prompt)?); @@ -131,7 +137,7 @@ impl Password<'_> { } impl<'a> Password<'a> { - /// Creates a password input prompt with a specific theme. + /// Create a password input prompt with a specific theme. pub fn with_theme(theme: &'a dyn Theme) -> Self { Self { prompt: "".into(), diff --git a/src/prompts/select.rs b/src/prompts/select.rs index 5e4335fc..322b640c 100644 --- a/src/prompts/select.rs +++ b/src/prompts/select.rs @@ -5,7 +5,7 @@ use crate::theme::{SimpleTheme, TermThemeRenderer, Theme}; use console::{Key, Term}; -/// Renders a select prompt. +/// Render a selection prompt. /// /// User can select from one or more options. /// Interaction returns index of an item selected in the order they appear in `item` invocation or `items` slice. @@ -35,12 +35,19 @@ use console::{Key, Term}; /// } /// ``` pub struct Select<'a> { + /// The initial selected element when the selection menu is rendered, + /// indicated by its index in [`items`](#field::items). default: usize, + /// Items the user can select. items: Vec, + /// Message of the selection prompt. prompt: Option, + /// whether to report the selected value after interaction report: bool, + /// whether the selection menu should be erased from the screen after interaction clear: bool, theme: &'a dyn Theme, + /// Maximal number of items on page (`None` if unbounded). max_length: Option, } @@ -51,14 +58,14 @@ impl Default for Select<'static> { } impl Select<'static> { - /// Creates a select prompt builder with default theme. + /// Create a selection prompt builder with default theme. pub fn new() -> Self { Self::with_theme(&SimpleTheme) } } impl Select<'_> { - /// Indicates whether select menu should be erased from the screen after interaction. + /// Indicate whether the selection menu should be erased from the screen after interaction. /// /// The default is to clear the menu. pub fn clear(&mut self, val: bool) -> &mut Self { @@ -66,21 +73,19 @@ impl Select<'_> { self } - /// Sets initial selected element when select menu is rendered + /// Set the initial selected element when the selection menu is rendered. /// - /// Element is indicated by the index at which it appears in `item` method invocation or `items` slice. + /// The default element is indicated by the index at which it appears in the `item` method invocation or the `items` slice. pub fn default(&mut self, val: usize) -> &mut Self { self.default = val; self } - /// Sets an optional max length for a page. - /// - /// Max length is disabled by None + /// Set an optional max length for a page. pub fn max_length(&mut self, val: usize) -> &mut Self { // Paging subtracts two from the capacity, paging does this to // make an offset for the page indicator. So to make sure that - // we can show the intended amount of items we need to add two + // we can show the intended amount of items, we need to add two // to our value. self.max_length = Some(val + 2); self @@ -106,7 +111,7 @@ impl Select<'_> { self } - /// Adds multiple items to the selector. + /// Add multiple items to the selector. /// /// ## Examples /// ```rust,no_run @@ -130,7 +135,7 @@ impl Select<'_> { self } - /// Sets the select prompt. + /// Set the selection prompt. /// /// By default, when a prompt is set the system also prints out a confirmation after /// the selection. You can opt-out of this with [`report`](#method.report). @@ -155,7 +160,7 @@ impl Select<'_> { self } - /// Indicates whether to report the selected value after interaction. + /// Indicate whether to report the selected value after interaction. /// /// The default is to report the selection. pub fn report(&mut self, val: bool) -> &mut Self { @@ -163,18 +168,18 @@ impl Select<'_> { self } - /// Enables user interaction and returns the result. + /// Enable user interaction and return the result. /// /// The user can select the items with the 'Space' bar or 'Enter' and the index of selected item will be returned. /// The dialog is rendered on stderr. /// Result contains `index` if user selected one of items using 'Enter'. - /// This unlike [`interact_opt`](Self::interact_opt) does not allow to quit with 'Esc' or 'q'. + /// Unlike [`interact_opt`](Self::interact_opt), this does not allow to quit with 'Esc' or 'q'. #[inline] pub fn interact(&self) -> io::Result { self.interact_on(&Term::stderr()) } - /// Enables user interaction and returns the result. + /// Enable user interaction and return the result. /// /// The user can select the items with the 'Space' bar or 'Enter' and the index of selected item will be returned. /// The dialog is rendered on stderr. @@ -350,7 +355,7 @@ impl Select<'_> { } impl<'a> Select<'a> { - /// Creates a select prompt builder with a specific theme. + /// Create a selection prompt builder with a specific theme. /// /// ## Examples /// ```rust,no_run diff --git a/src/prompts/sort.rs b/src/prompts/sort.rs index 03152bf4..2782172c 100644 --- a/src/prompts/sort.rs +++ b/src/prompts/sort.rs @@ -57,7 +57,7 @@ impl Sort<'_> { /// Sets an optional max length for a page /// - /// Max length is disabled by None + /// Max length is disabled by `None` pub fn max_length(&mut self, val: usize) -> &mut Self { // Paging subtracts two from the capacity, paging does this to // make an offset for the page indicator. So to make sure that diff --git a/src/theme.rs b/src/theme.rs index fb814775..db0585ca 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -7,19 +7,22 @@ use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher}; /// Implements a theme for dialoguer. pub trait Theme { - /// Formats a prompt. + /// Format a prompt. #[inline] fn format_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { write!(f, "{}:", prompt) } - /// Formats out an error. + /// Format out an error. #[inline] fn format_error(&self, f: &mut dyn fmt::Write, err: &str) -> fmt::Result { write!(f, "error: {}", err) } - /// Formats a confirm prompt. + /// Format a confirmation prompt. + /// + /// `prompt` is the message of the confirmation prompt, + /// `default` is the default choice for the prompt (if any). fn format_confirm_prompt( &self, f: &mut dyn fmt::Write, @@ -37,7 +40,7 @@ pub trait Theme { Ok(()) } - /// Formats a confirm prompt after selection. + /// Format a confirmation prompt after selection. fn format_confirm_prompt_selection( &self, f: &mut dyn fmt::Write, @@ -60,7 +63,7 @@ pub trait Theme { } } - /// Formats an input prompt. + /// Format an input prompt. fn format_input_prompt( &self, f: &mut dyn fmt::Write, @@ -74,7 +77,7 @@ pub trait Theme { } } - /// Formats an input prompt after selection. + /// Format an input prompt after selection. #[inline] fn format_input_prompt_selection( &self, @@ -85,14 +88,14 @@ pub trait Theme { write!(f, "{}: {}", prompt, sel) } - /// Formats a password prompt. + /// Format a password prompt. #[inline] #[cfg(feature = "password")] fn format_password_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { self.format_input_prompt(f, prompt, None) } - /// Formats a password prompt after selection. + /// Format a password prompt after selection. #[inline] #[cfg(feature = "password")] fn format_password_prompt_selection( @@ -103,13 +106,13 @@ pub trait Theme { self.format_input_prompt_selection(f, prompt, "[hidden]") } - /// Formats a select prompt. + /// Format a selection prompt. #[inline] fn format_select_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { self.format_prompt(f, prompt) } - /// Formats a select prompt after selection. + /// Format a selection prompt after an item was selected. #[inline] fn format_select_prompt_selection( &self, @@ -120,19 +123,19 @@ pub trait Theme { self.format_input_prompt_selection(f, prompt, sel) } - /// Formats a multi select prompt. + /// Format a multi-selection prompt. #[inline] fn format_multi_select_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { self.format_prompt(f, prompt) } - /// Formats a sort prompt. + /// Format a sort prompt. #[inline] fn format_sort_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { self.format_prompt(f, prompt) } - /// Formats a multi_select prompt after selection. + /// Format a multi-selection prompt after an item was selected. fn format_multi_select_prompt_selection( &self, f: &mut dyn fmt::Write, @@ -146,7 +149,7 @@ pub trait Theme { Ok(()) } - /// Formats a sort prompt after selection. + /// Format a sort prompt after an item was selected. #[inline] fn format_sort_prompt_selection( &self, @@ -157,7 +160,7 @@ pub trait Theme { self.format_multi_select_prompt_selection(f, prompt, selections) } - /// Formats a select prompt item. + /// Format a single selection prompt item. fn format_select_prompt_item( &self, f: &mut dyn fmt::Write, @@ -167,7 +170,7 @@ pub trait Theme { write!(f, "{} {}", if active { ">" } else { " " }, text) } - /// Formats a multi select prompt item. + /// Format a single multi-selection prompt item. fn format_multi_select_prompt_item( &self, f: &mut dyn fmt::Write, @@ -188,7 +191,7 @@ pub trait Theme { ) } - /// Formats a sort prompt item. + /// Format a sort prompt item. fn format_sort_prompt_item( &self, f: &mut dyn fmt::Write, @@ -208,37 +211,7 @@ pub trait Theme { ) } - /// Formats a fuzzy select prompt item. - #[cfg(feature = "fuzzy-select")] - fn format_fuzzy_select_prompt_item( - &self, - f: &mut dyn fmt::Write, - text: &str, - active: bool, - highlight_matches: bool, - matcher: &SkimMatcherV2, - search_term: &str, - ) -> fmt::Result { - write!(f, "{} ", if active { ">" } else { " " })?; - - if highlight_matches { - if let Some((_score, indices)) = matcher.fuzzy_indices(text, &search_term) { - for (idx, c) in text.chars().into_iter().enumerate() { - if indices.contains(&idx) { - write!(f, "{}", style(c).for_stderr().bold())?; - } else { - write!(f, "{}", c)?; - } - } - - return Ok(()); - } - } - - write!(f, "{}", text) - } - - /// Formats a fuzzy select prompt. + /// Format a fuzzy select prompt item. #[cfg(feature = "fuzzy-select")] fn format_fuzzy_select_prompt( &self, @@ -347,7 +320,7 @@ impl Default for ColorfulTheme { } impl Theme for ColorfulTheme { - /// Formats a prompt. + /// Format a prompt. fn format_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { if !prompt.is_empty() { write!( @@ -361,7 +334,7 @@ impl Theme for ColorfulTheme { write!(f, "{}", &self.prompt_suffix) } - /// Formats an error + /// Format an error. fn format_error(&self, f: &mut dyn fmt::Write, err: &str) -> fmt::Result { write!( f, @@ -371,7 +344,7 @@ impl Theme for ColorfulTheme { ) } - /// Formats an input prompt. + /// Format an input prompt. fn format_input_prompt( &self, f: &mut dyn fmt::Write, @@ -398,7 +371,7 @@ impl Theme for ColorfulTheme { } } - /// Formats a confirm prompt. + /// Format a confirmation prompt. fn format_confirm_prompt( &self, f: &mut dyn fmt::Write, @@ -438,7 +411,7 @@ impl Theme for ColorfulTheme { } } - /// Formats a confirm prompt after selection. + /// Format a confirmation prompt after selection. fn format_confirm_prompt_selection( &self, f: &mut dyn fmt::Write, @@ -686,13 +659,16 @@ impl Theme for ColorfulTheme { } } -/// Helper struct to conveniently render a theme ot a term. +/// Helper struct to conveniently render a theme to a term. pub(crate) struct TermThemeRenderer<'a> { term: &'a Term, theme: &'a dyn Theme, + /// Height (number of lines, ignoring lines overflowing the terminal) + /// of output after the last prompt: not counting the current line. height: usize, + /// Height (number of output lines, ignoring overflowing items) + /// of the last completed prompt and everything above it. prompt_height: usize, - prompts_reset_height: bool, } impl<'a> TermThemeRenderer<'a> { @@ -702,24 +678,22 @@ impl<'a> TermThemeRenderer<'a> { theme, height: 0, prompt_height: 0, - prompts_reset_height: true, } } - #[cfg(feature = "password")] - pub fn set_prompts_reset_height(&mut self, val: bool) { - self.prompts_reset_height = val; - } - #[cfg(feature = "password")] pub fn term(&self) -> &Term { self.term } + /// Enlarge the theme by one line: allow displaying one more line of input. pub fn add_line(&mut self) { self.height += 1; } + /// Write a formatted string to this terminal. The string can be span multiple lines. + /// + /// `F` is a closure prescribing the text to write into the current instance. fn write_formatted_str< F: FnOnce(&mut TermThemeRenderer, &mut dyn fmt::Write) -> fmt::Result, >( @@ -732,6 +706,7 @@ impl<'a> TermThemeRenderer<'a> { self.term.write_str(&buf) } + /// Like [`write_formatted_string`](#method::write_formatted_string), but add a linebreak afterwards. fn write_formatted_line< F: FnOnce(&mut TermThemeRenderer, &mut dyn fmt::Write) -> fmt::Result, >( @@ -744,6 +719,9 @@ impl<'a> TermThemeRenderer<'a> { self.term.write_line(&buf) } + /// Write a formatted prompt string to this terminal. + /// + /// `F` is a closure prescribing the text to write into the current instance. fn write_formatted_prompt< F: FnOnce(&mut TermThemeRenderer, &mut dyn fmt::Write) -> fmt::Result, >( @@ -751,10 +729,8 @@ impl<'a> TermThemeRenderer<'a> { f: F, ) -> io::Result<()> { self.write_formatted_line(f)?; - if self.prompts_reset_height { - self.prompt_height = self.height; - self.height = 0; - } + self.prompt_height = self.height; + self.height = 0; Ok(()) } @@ -936,7 +912,7 @@ impl<'a> TermThemeRenderer<'a> { pub fn clear_preserve_prompt(&mut self, size_vec: &[usize]) -> io::Result<()> { let mut new_height = self.height; - //Check each item size, increment on finding an overflow + // Check each item size, increment on finding an overflow for size in size_vec { if *size > self.term.size().1 as usize { new_height += 1;