//! 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(())
}