Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help message revamp #161

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- **Breaking**. Allow lifetime customization of RenderConfig. [#101](https://github.com/mikaelmello/inquire/pull/101). Thanks to @arturfast for the suggestion [#95](https://github.com/mikaelmello/inquire/issues/95).
- Add new option on MultiSelect prompts to set all options to be selected by default. Thanks to @conikeec for the suggestion (#151)!
- **Breaking**. Improved user experience on Password prompts. When there is a validation error, the input is cleared if the password is rendered using the `Hidden` display mode, matching the user expectation of having to write the password from scratch again. Thanks to @CM-IV for the questions on #149!
- **Breaking**. Help messages are now defined through a new type, `HelpMessage`, containing three variants: `None`, `Default` and `Custom(String)`. This allows better default help messages tailored to the customizations of each prompt, e.g. hint `esc` to leave the prompt only when applicable. Thanks to @dariocurr for the request on #143! #161.
- Add strict clippy lints to improve code consistency and readability.
- Expand workflow clippy task to lint all-features in workspace.
- Add docs badge to readme.
Expand Down
2 changes: 1 addition & 1 deletion inquire/examples/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() {
message: "Are you happy?",
default: Some(false),
placeholder: Some("si|no"),
help_message: Some("It's alright if you're not"),
help_message: "It's alright if you're not".into(),
formatter: &|ans| match ans {
true => "si".to_owned(),
false => "no".to_owned(),
Expand Down
2 changes: 1 addition & 1 deletion inquire/examples/text_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn main() {
initial_value: None,
default: None,
placeholder: Some("Good"),
help_message: None,
help_message: None.into(),
formatter: Text::DEFAULT_FORMATTER,
validators: Vec::new(),
page_size: Text::DEFAULT_PAGE_SIZE,
Expand Down
4 changes: 4 additions & 0 deletions inquire/src/autocompletion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,12 @@ impl Clone for Box<dyn Autocomplete> {
/// Empty struct and implementation of Autocomplete trait. Used for the default
/// autocompleter of `Text` prompts.
#[derive(Clone, Default)]
#[deprecated(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am very comfortable with it.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I'm not sure if this is a "I'm comfortable with adding this" or "I'm comfortable with the struct, we don't need the deprecated" lol

For context, the only use was as the default value inside the prompt impl when the prompt config was None, so I even thought of just removing the NoAutoComplete struct altogether

note = "All applicable APIs accept a Option<Autocomplete>, so use None instead. This struct will be removed in a future release."
)]
pub struct NoAutoCompletion;

#[allow(deprecated)]
impl Autocomplete for NoAutoCompletion {
fn get_suggestions(&mut self, _: &str) -> Result<Vec<String>, CustomUserError> {
Ok(vec![])
Expand Down
16 changes: 11 additions & 5 deletions inquire/src/prompts/confirm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
formatter::{BoolFormatter, DEFAULT_BOOL_FORMATTER},
parser::{BoolParser, DEFAULT_BOOL_PARSER},
terminal::{get_default_terminal, Terminal},
ui::{Backend, RenderConfig},
ui::{Backend, HelpMessage, RenderConfig},
CustomType,
};

Expand Down Expand Up @@ -68,7 +68,7 @@ pub struct Confirm<'a> {
pub placeholder: Option<&'a str>,

/// Help message to be presented to the user.
pub help_message: Option<&'a str>,
pub help_message: HelpMessage,

/// Function that formats the user input and presents it to the user as the final rendering of the prompt.
pub formatter: BoolFormatter<'a>,
Expand Down Expand Up @@ -117,7 +117,7 @@ impl<'a> Confirm<'a> {
message,
default: None,
placeholder: None,
help_message: None,
help_message: HelpMessage::default(),
formatter: Self::DEFAULT_FORMATTER,
parser: Self::DEFAULT_PARSER,
default_value_formatter: Self::DEFAULT_DEFAULT_VALUE_FORMATTER,
Expand All @@ -139,8 +139,14 @@ impl<'a> Confirm<'a> {
}

/// Sets the help message of the prompt.
pub fn with_help_message(mut self, message: &'a str) -> Self {
self.help_message = Some(message);
pub fn with_help_message(mut self, message: &str) -> Self {
self.help_message = message.into();
self
}

/// Sets the prompt to not display a help message.
pub fn without_help_message(mut self) -> Self {
self.help_message = HelpMessage::None;
self
}

Expand Down
16 changes: 11 additions & 5 deletions inquire/src/prompts/custom_type/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
parser::CustomTypeParser,
prompts::prompt::Prompt,
terminal::get_default_terminal,
ui::{Backend, CustomTypeBackend, RenderConfig},
ui::{Backend, CustomTypeBackend, HelpMessage, RenderConfig},
validator::CustomTypeValidator,
};

Expand Down Expand Up @@ -87,7 +87,7 @@ pub struct CustomType<'a, T> {
pub placeholder: Option<&'a str>,

/// Help message to be presented to the user.
pub help_message: Option<&'a str>,
pub help_message: HelpMessage,

/// Function that formats the user input and presents it to the user as the final rendering of the prompt.
pub formatter: CustomTypeFormatter<'a, T>,
Expand Down Expand Up @@ -136,7 +136,7 @@ where
message,
default: None,
placeholder: None,
help_message: None,
help_message: HelpMessage::default(),
formatter: &|val| val.to_string(),
default_value_formatter: &|val| val.to_string(),
parser: &|a| a.parse::<T>().map_err(|_e| ()),
Expand All @@ -159,8 +159,14 @@ where
}

/// Sets the help message of the prompt.
pub fn with_help_message(mut self, message: &'a str) -> Self {
self.help_message = Some(message);
pub fn with_help_message(mut self, message: &str) -> Self {
self.help_message = message.into();
self
}

/// Sets the prompt to not display a help message.
pub fn without_help_message(mut self) -> Self {
self.help_message = HelpMessage::None;
self
}

Expand Down
15 changes: 8 additions & 7 deletions inquire/src/prompts/custom_type/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub struct CustomTypePrompt<'a, T> {
message: &'a str,
config: CustomTypeConfig,
error: Option<ErrorMessage>,
help_message: Option<&'a str>,
help_message: Option<String>,
default: Option<T>,
input: Input,
formatter: CustomTypeFormatter<'a, T>,
Expand All @@ -35,7 +35,7 @@ where
config: (&co).into(),
error: None,
default: co.default,
help_message: co.help_message,
help_message: co.help_message.into_or_default(None),
formatter: co.formatter,
default_value_formatter: co.default_value_formatter,
validators: co.validators,
Expand Down Expand Up @@ -78,7 +78,8 @@ where
}
}

impl<'a, B, T> Prompt<B, CustomTypeConfig, CustomTypePromptAction, T> for CustomTypePrompt<'a, T>
impl<'a, B, T> Prompt<'a, B, CustomTypeConfig, CustomTypePromptAction, T>
for CustomTypePrompt<'a, T>
where
B: CustomTypeBackend,
T: Clone,
Expand All @@ -87,6 +88,10 @@ where
self.message
}

fn help_message(&self) -> Option<&str> {
self.help_message.as_deref()
}

fn config(&self) -> &CustomTypeConfig {
&self.config
}
Expand Down Expand Up @@ -138,10 +143,6 @@ where

backend.render_prompt(prompt, default_message.as_deref(), &self.input)?;

if let Some(message) = self.help_message {
backend.render_help_message(message)?;
}

Ok(())
}
}
18 changes: 7 additions & 11 deletions inquire/src/prompts/dateselect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
formatter::{self, DateFormatter},
prompts::prompt::Prompt,
terminal::{get_default_terminal, Terminal},
ui::{Backend, RenderConfig},
ui::{Backend, HelpMessage, RenderConfig},
validator::DateValidator,
};

Expand Down Expand Up @@ -82,7 +82,7 @@ pub struct DateSelect<'a> {
pub max_date: Option<NaiveDate>,

/// Help message to be presented to the user.
pub help_message: Option<&'a str>,
pub help_message: HelpMessage,

/// Whether vim mode is enabled. When enabled, the user can
/// navigate through the options using hjkl.
Expand Down Expand Up @@ -117,10 +117,6 @@ impl<'a> DateSelect<'a> {
/// Default value of vim mode. It is true because there is no typing functionality to be lost here.
pub const DEFAULT_VIM_MODE: bool = true;

/// Default help message.
pub const DEFAULT_HELP_MESSAGE: Option<&'a str> =
Some("arrows to move, with ctrl to move months and years, enter to select");

/// Default validators added to the [DateSelect] prompt, none.
pub const DEFAULT_VALIDATORS: Vec<Box<dyn DateValidator>> = vec![];

Expand All @@ -140,7 +136,7 @@ impl<'a> DateSelect<'a> {
starting_date: get_current_date(),
min_date: Self::DEFAULT_MIN_DATE,
max_date: Self::DEFAULT_MAX_DATE,
help_message: Self::DEFAULT_HELP_MESSAGE,
help_message: HelpMessage::default(),
vim_mode: Self::DEFAULT_VIM_MODE,
formatter: Self::DEFAULT_FORMATTER,
validators: Self::DEFAULT_VALIDATORS,
Expand All @@ -150,14 +146,14 @@ impl<'a> DateSelect<'a> {
}

/// Sets the help message of the prompt.
pub fn with_help_message(mut self, message: &'a str) -> Self {
self.help_message = Some(message);
pub fn with_help_message(mut self, message: &str) -> Self {
self.help_message = message.into();
self
}

/// Removes the set help message.
/// Sets the prompt to not display a help message.
pub fn without_help_message(mut self) -> Self {
self.help_message = None;
self.help_message = HelpMessage::None;
self
}

Expand Down
23 changes: 15 additions & 8 deletions inquire/src/prompts/dateselect/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ pub struct DateSelectPrompt<'a> {
message: &'a str,
config: DateSelectConfig,
current_date: NaiveDate,
help_message: Option<&'a str>,
help_message: Option<String>,
formatter: DateFormatter<'a>,
validators: Vec<Box<dyn DateValidator>>,
error: Option<ErrorMessage>,
}

impl<'a> DateSelectPrompt<'a> {
pub fn new(so: DateSelect<'a>) -> InquireResult<Self> {
let config = (&so).into();
if let Some(min_date) = so.min_date {
if min_date > so.starting_date {
return Err(InquireError::InvalidConfiguration(
Expand All @@ -44,11 +45,16 @@ impl<'a> DateSelectPrompt<'a> {
}
}

let default_help_message =
Some("arrows to move, with ctrl to move months and years, enter to select");
let help_message = so
.help_message
.into_or_default(default_help_message.map(|s| s.into()));
Ok(Self {
message: so.message,
current_date: so.starting_date,
config: (&so).into(),
help_message: so.help_message,
config,
help_message,
formatter: so.formatter,
validators: so.validators,
error: None,
Expand Down Expand Up @@ -116,14 +122,19 @@ impl<'a> DateSelectPrompt<'a> {
}
}

impl<'a, B> Prompt<B, DateSelectConfig, DateSelectPromptAction, NaiveDate> for DateSelectPrompt<'a>
impl<'a, B> Prompt<'a, B, DateSelectConfig, DateSelectPromptAction, NaiveDate>
for DateSelectPrompt<'a>
where
B: DateSelectBackend,
{
fn message(&self) -> &str {
self.message
}

fn help_message(&self) -> Option<&str> {
self.help_message.as_deref()
}

fn format_answer(&self, answer: &NaiveDate) -> String {
(self.formatter)(*answer)
}
Expand Down Expand Up @@ -178,10 +189,6 @@ where
self.config.max_date,
)?;

if let Some(help_message) = self.help_message {
backend.render_help_message(help_message)?;
}

Ok(())
}
}
19 changes: 11 additions & 8 deletions inquire/src/prompts/editor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
formatter::StringFormatter,
prompts::prompt::Prompt,
terminal::get_default_terminal,
ui::{Backend, EditorBackend, RenderConfig},
ui::{Backend, EditorBackend, HelpMessage, RenderConfig},
validator::StringValidator,
};

Expand Down Expand Up @@ -66,7 +66,7 @@ pub struct Editor<'a> {
pub predefined_text: Option<&'a str>,

/// Help message to be presented to the user.
pub help_message: Option<&'a str>,
pub help_message: HelpMessage,

/// Function that formats the user input and presents it to the user as the final rendering of the prompt.
pub formatter: StringFormatter<'a>,
Expand Down Expand Up @@ -97,9 +97,6 @@ impl<'a> Editor<'a> {
/// Default validators added to the [Editor] prompt, none.
pub const DEFAULT_VALIDATORS: Vec<Box<dyn StringValidator>> = vec![];

/// Default help message.
pub const DEFAULT_HELP_MESSAGE: Option<&'a str> = None;

/// Creates a [Editor] with the provided message and default options.
pub fn new(message: &'a str) -> Self {
Self {
Expand All @@ -108,16 +105,22 @@ impl<'a> Editor<'a> {
editor_command_args: &[],
file_extension: ".txt",
predefined_text: None,
help_message: Self::DEFAULT_HELP_MESSAGE,
help_message: HelpMessage::default(),
validators: Self::DEFAULT_VALIDATORS,
formatter: Self::DEFAULT_FORMATTER,
render_config: RenderConfig::default(),
}
}

/// Sets the help message of the prompt.
pub fn with_help_message(mut self, message: &'a str) -> Self {
self.help_message = Some(message);
pub fn with_help_message(mut self, message: &str) -> Self {
self.help_message = message.into();
self
}

/// Sets the prompt to not display a help message.
pub fn without_help_message(mut self) -> Self {
self.help_message = HelpMessage::None;
self
}

Expand Down
Loading