+ //! Example showing various localized interactions
+
+ use icu_locale::locale;
+ use l10n_embed_derive::localize;
+ use l10n_embed_interaction::{Confirm, Editor, Input, Password, Select};
+ use l10n_embed_interaction::{InteractionEnvironment, InteractionError};
+
+ #[localize("examples/prompt/locale/**/prompt_selection.ftl")]
+ enum PromptSelection {
+ Confirm,
+ Editor,
+ Input,
+ Password,
+ }
+
+ #[localize("examples/prompt/locale/**/prompts.ftl")]
+ enum Prompt {
+ Confirm,
+ Input,
+ Password,
+ PasswordConfirmation,
+ Select,
+ }
+
+ #[localize("examples/prompt/locale/**/errors.ftl")]
+ enum PromptError {
+ NonAlphabeticInput,
+ NonPalindromeInput,
+ PasswordTooShort {
+ provided_length: usize,
+ expected_length: usize,
+ },
+ PasswordMismatch,
+ }
+
+ const ALWAYS_INTERACTIVE: &str = "Attempted to interact in a non-interactive environment";
+ const DEFAULT_SELECTION: usize = 2;
+ const MINIMUM_PASSWORD_LENGTH: usize = 2;
+ const PROMPT_SELECTIONS: [PromptSelection; 4] = [
+ PromptSelection::Confirm,
+ PromptSelection::Editor,
+ PromptSelection::Input,
+ PromptSelection::Password,
+ ];
+
+ fn main() -> Result<(), InteractionError> {
+ let environment = InteractionEnvironment::new(locale!("en-US"), true);
+
+ let selected_index = Select::new(&environment, Prompt::Select)
+ .with_items(&PROMPT_SELECTIONS)
+ .with_default(DEFAULT_SELECTION)
+ .interact()?
+ .expect(ALWAYS_INTERACTIVE);
+
+ match PROMPT_SELECTIONS[selected_index] {
+ PromptSelection::Confirm => {
+ let confirmation = Confirm::new(&environment, Prompt::Confirm)
+ .with_default(true)
+ .interact()?
+ .expect(ALWAYS_INTERACTIVE);
+
+ let message = match confirmation {
+ true => "hooray!",
+ false => "dang..",
+ };
+ println!("{message}");
+ }
+ PromptSelection::Editor => {
+ let edited = Editor::new(&environment, "toml").edit("Some text for you to edit!")?;
+
+ match edited {
+ Some(saved_text) => println!(
+ "The file was saved successfully (total lines: {})",
+ saved_text.lines().count()
+ ),
+ None => println!("No text was saved.."),
+ }
+ }
+ PromptSelection::Input => {
+ let input = Input::new(&environment, Prompt::Input)
+ // `Input::with_default` accepts anything that implements `Localize`,
+ // so this default could also be localized
+ .with_default("racecar")
+ .with_validator(|input| {
+ if !input
+ .chars()
+ .all(|character| character.is_alphabetic() && !character.is_whitespace())
+ {
+ Err(PromptError::NonAlphabeticInput)
+ } else if input != &input.chars().rev().collect::<String>() {
+ Err(PromptError::NonPalindromeInput)
+ } else {
+ Ok(())
+ }
+ })
+ .interact()?
+ .expect(ALWAYS_INTERACTIVE);
+
+ println!("Your palindrome is: {input}!")
+ }
+ PromptSelection::Password => {
+ let password = Password::new(&environment, Prompt::Password)
+ .with_validator(|password| {
+ if password.len() >= MINIMUM_PASSWORD_LENGTH {
+ Ok(())
+ } else {
+ Err(PromptError::PasswordTooShort {
+ provided_length: password.len(),
+ expected_length: MINIMUM_PASSWORD_LENGTH,
+ })
+ }
+ })
+ .with_confirmation(Prompt::PasswordConfirmation, PromptError::PasswordMismatch)
+ .interact()?
+ .expect(ALWAYS_INTERACTIVE);
+
+ println!("Your password is: {password}");
+ }
+ }
+
+ Ok(())
+ }