//! Prompt display and interaction management. #[cfg(feature = "mnemonic")] use keyfork_mnemonic::Wordlist; /// pub mod terminal; pub mod validators; pub use terminal::{default_terminal, DefaultTerminal, Terminal}; /// An error occurred while displaying a prompt. #[derive(thiserror::Error, Debug)] pub enum Error { /// The given handler is not a TTY and can't be used to display prompts. #[error("The given handler is not a TTY")] NotATTY, /// Validating user input failed. #[error("Validation of the input failed after {0} retries (last error: {1})")] Validation(u8, String), /// A ctrl-c interrupt was caught by the handler. #[error("User pressed ctrl-c, terminating the session")] CtrlC, /// An error occurred while interacting with a terminal. #[error("IO Error: {0}")] IO(#[from] std::io::Error), } #[allow(missing_docs)] pub type Result = std::result::Result; /// A message displayed by [`PromptHandler::prompt_message`]. pub enum Message { /// A textual message, wrapping at space boundaries when reaching the end of the terminal. Text(String), /// A data message, with no word wrapping, and automatic hiding of the message when a terminal /// is too small. Data(String), } #[doc(hidden)] pub type BoxResult = std::result::Result<(), Box>; /// A trait to allow displaying prompts and accepting input. pub trait PromptHandler { /// Prompt the user for input. /// /// # Errors /// The method may return an error if the message was not able to be displayed or if the input /// could not be read. fn prompt_input(&mut self, prompt: &str) -> Result; /// Prompt the user for input based on a wordlist. A language must be specified as the generic /// parameter `X` (any type implementing [`Wordlist`]) when parsing a wordlist. /// /// # Errors /// The method may return an error if the message was not able to be displayed or if the input /// could not be read. fn prompt_wordlist(&mut self, prompt: &str, wordlist: &[&str]) -> Result; /// Prompt the user for a passphrase, which is hidden while typing. /// /// # Errors /// The method may return an error if the message was not able to be displayed or if the input /// could not be read. fn prompt_passphrase(&mut self, prompt: &str) -> Result; /// Prompt the user with a [`Message`]. /// /// # Errors /// The method may return an error if the message was not able to be displayed or if an error /// occurred while waiting for the user to dismiss the message. fn prompt_message(&mut self, prompt: Message) -> Result<()>; /// Prompt the user for input based on a wordlist, while validating the wordlist using a /// provided parser function, returning the type from the parser. A language must be specified /// as the generic parameter `X` (any type implementing [`Wordlist`]) when parsing a wordlist. /// /// This method MUST NOT be used directly. Instead, use /// [`prompt_validated_wordlist`]. /// /// # Errors /// The method may return an error if the message was not able to be displayed, if the input /// could not be read, or if the parser returned an error. fn prompt_validated_wordlist( &mut self, prompt: &str, retries: u8, wordlist: &[&str], validator_fn: &mut dyn FnMut(String) -> BoxResult, ) -> Result<(), Error>; /// Prompt the user for a passphrase, which is hidden while typing, and validate the passphrase /// using a provided parser function, returning the type from the parser. /// /// This method MUST NOT be used directly. Instead, use /// [`prompt_validated_wordlist`]. /// /// # Errors /// The method may return an error if the message was not able to be displayed, if the input /// could not be read, or if the parser returned an error. fn prompt_validated_passphrase( &mut self, prompt: &str, retries: u8, validator_fn: &mut dyn FnMut(String) -> BoxResult, ) -> Result<(), Error>; } /// Prompt the user for input based on a wordlist, while validating the wordlist using a /// provided parser function, returning the type from the parser. A language must be specified /// as the generic parameter `X` (any type implementing [`Wordlist`]) when parsing a wordlist. /// /// # Errors /// The method may return an error if the message was not able to be displayed, if the input /// could not be read, or if the parser returned an error. #[cfg(feature = "mnemonic")] #[allow(clippy::missing_panics_doc)] pub fn prompt_validated_wordlist( handler: &mut dyn PromptHandler, prompt: &str, retries: u8, validator_fn: &dyn Fn(String) -> Result>, ) -> Result where X: Wordlist, { let wordlist = X::get_singleton(); let words = wordlist.to_str_array(); let mut opt: Option = None; handler.prompt_validated_wordlist(prompt, retries, &words, &mut |string| { opt = Some(validator_fn(string)?); Ok(()) })?; Ok(opt.unwrap()) } /// Prompt the user for a passphrase, which is hidden while typing, and validate the passphrase /// using a provided parser function, returning the type from the parser. /// /// # Errors /// The method may return an error if the message was not able to be displayed, if the input /// could not be read, or if the parser returned an error. #[allow(clippy::missing_panics_doc)] pub fn prompt_validated_passphrase( handler: &mut dyn PromptHandler, prompt: &str, retries: u8, validator_fn: impl Fn(String) -> Result>, ) -> Result { let mut opt: Option = None; handler.prompt_validated_passphrase(prompt, retries, &mut |string| { opt = Some(validator_fn(string)?); Ok(()) })?; Ok(opt.unwrap()) }