Skip to content

Commit

Permalink
Don't require static lifetime for autocompleter and validator
Browse files Browse the repository at this point in the history
  • Loading branch information
stormshield-guillaumed committed Sep 30, 2024
1 parent 446ce3d commit a2aad18
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## [Unreleased] <!-- ReleaseDate -->

- Don't require static lifetime for autocompleter and validator.
- Fix autocomplete suggestions not being updated after a suggestion is accepted. Thanks @moritz-hoelting and @istudyatuni for reporting and fixing it!
- Fix incorrect cursor placement when inputting CJK characters. Thanks @phostann (#270) for reporting it!
- Removed unused dependency (newline-converter). Thanks @jonassmedegaard (#267) for catching it!
Expand Down
4 changes: 2 additions & 2 deletions inquire/src/prompts/text/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ pub struct TextConfig {
pub page_size: usize,
}

impl From<&Text<'_>> for TextConfig {
fn from(value: &Text<'_>) -> Self {
impl From<&Text<'_, '_>> for TextConfig {
fn from(value: &Text<'_, '_>) -> Self {
Self {
page_size: value.page_size,
}
Expand Down
31 changes: 23 additions & 8 deletions inquire/src/prompts/text/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ const DEFAULT_HELP_MESSAGE_WITH_AC: &str = "↑↓ to move, tab to autocomplete,
/// Err(_) => println!("An error happened when asking for your name, try again later."),
/// }
/// ```
#[derive(Clone)]
pub struct Text<'a> {
pub struct Text<'a, 'b> {
/// Message to be presented to the user.
pub message: &'a str,

Expand All @@ -98,15 +97,15 @@ pub struct Text<'a> {
pub formatter: StringFormatter<'a>,

/// Autocompleter responsible for handling suggestions and input completions.
pub autocompleter: Option<Box<dyn Autocomplete>>,
pub autocompleter: Option<Box<dyn Autocomplete + 'b>>,

/// Collection of validators to apply to the user input.
///
/// Validators are executed in the order they are stored, stopping at and displaying to the user
/// only the first validation error that might appear.
///
/// The possible error is displayed to the user one line above the prompt.
pub validators: Vec<Box<dyn StringValidator>>,
pub validators: Vec<Box<dyn StringValidator + 'b>>,

/// Page size of the suggestions displayed to the user, when applicable.
pub page_size: usize,
Expand All @@ -122,7 +121,24 @@ pub struct Text<'a> {
pub render_config: RenderConfig<'a>,
}

impl<'a> Text<'a> {
impl<'a> Clone for Text<'a, 'static> {
fn clone(&self) -> Self {
Self {
message: self.message,
initial_value: self.initial_value,
default: self.default,
placeholder: self.placeholder,
help_message: self.help_message,
formatter: self.formatter,
autocompleter: self.autocompleter.clone(),
validators: self.validators.clone(),
page_size: self.page_size,
render_config: self.render_config,
}
}
}

impl<'a, 'b> Text<'a, 'b> {
/// Default formatter, set to [DEFAULT_STRING_FORMATTER](crate::formatter::DEFAULT_STRING_FORMATTER)
pub const DEFAULT_FORMATTER: StringFormatter<'a> = DEFAULT_STRING_FORMATTER;

Expand Down Expand Up @@ -182,7 +198,7 @@ impl<'a> Text<'a> {
/// Sets a new autocompleter
pub fn with_autocomplete<AC>(mut self, ac: AC) -> Self
where
AC: Autocomplete + 'static,
AC: Autocomplete + 'b,
{
self.autocompleter = Some(Box::new(ac));
self
Expand Down Expand Up @@ -210,7 +226,7 @@ impl<'a> Text<'a> {
/// The possible error is displayed to the user one line above the prompt.
pub fn with_validator<V>(mut self, validator: V) -> Self
where
V: StringValidator + 'static,
V: StringValidator + 'b,
{
self.validators.push(Box::new(validator));
self
Expand All @@ -226,7 +242,6 @@ impl<'a> Text<'a> {
/// The possible error is displayed to the user one line above the prompt.
pub fn with_validators(mut self, validators: &[Box<dyn StringValidator>]) -> Self {
for validator in validators {
#[allow(suspicious_double_ref_op)]
self.validators.push(validator.clone());
}
self
Expand Down
16 changes: 8 additions & 8 deletions inquire/src/prompts/text/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ use crate::{

use super::{action::TextPromptAction, config::TextConfig, DEFAULT_HELP_MESSAGE_WITH_AC};

pub struct TextPrompt<'a> {
pub struct TextPrompt<'a, 'b> {
message: &'a str,
config: TextConfig,
default: Option<&'a str>,
help_message: Option<&'a str>,
input: Input,
formatter: StringFormatter<'a>,
validators: Vec<Box<dyn StringValidator>>,
validators: Vec<Box<dyn StringValidator + 'b>>,
error: Option<ErrorMessage>,
autocompleter: Box<dyn Autocomplete>,
autocompleter: Box<dyn Autocomplete + 'b>,
suggested_options: Vec<String>,
suggestion_cursor_index: Option<usize>,
}

impl<'a> From<Text<'a>> for TextPrompt<'a> {
fn from(so: Text<'a>) -> Self {
impl<'a, 'b> From<Text<'a, 'b>> for TextPrompt<'a, 'b> {
fn from(so: Text<'a, 'b>) -> Self {
let input = Input::new_with(so.initial_value.unwrap_or_default());
let input = if let Some(placeholder) = so.placeholder {
input.with_placeholder(placeholder)
Expand All @@ -56,13 +56,13 @@ impl<'a> From<Text<'a>> for TextPrompt<'a> {
}
}

impl<'a> From<&'a str> for Text<'a> {
impl<'a, 'b> From<&'a str> for Text<'a, 'b> {
fn from(val: &'a str) -> Self {
Text::new(val)
}
}

impl<'a> TextPrompt<'a> {
impl<'a, 'b> TextPrompt<'a, 'b> {
fn update_suggestions(&mut self) -> InquireResult<()> {
self.suggested_options = self.autocompleter.get_suggestions(self.input.content())?;
self.suggestion_cursor_index = None;
Expand Down Expand Up @@ -161,7 +161,7 @@ impl<'a> TextPrompt<'a> {
}
}

impl<'a, Backend> Prompt<Backend> for TextPrompt<'a>
impl<'a, 'b, Backend> Prompt<Backend> for TextPrompt<'a, 'b>
where
Backend: TextBackend,
{
Expand Down
2 changes: 1 addition & 1 deletion inquire/src/prompts/text/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::Text;
use crate::ui::{Key, KeyModifiers};
use crate::validator::{ErrorMessage, Validation};

fn default<'a>() -> Text<'a> {
fn default<'a, 'b>() -> Text<'a, 'b> {
Text::new("Question?")
}

Expand Down

0 comments on commit a2aad18

Please sign in to comment.