diff --git a/Cargo.lock b/Cargo.lock index c8e53a2..dd13777 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -852,6 +852,31 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crossterm" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" +dependencies = [ + "bitflags 1.3.2", + "crossterm_winapi", + "libc", + "mio", + "parking_lot 0.12.1", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -1151,6 +1176,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.16.9" @@ -1649,6 +1680,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fuzzy-matcher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" +dependencies = [ + "thread_local", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -1871,6 +1911,7 @@ dependencies = [ "email_address", "erased-serde", "indicatif", + "inquire", "mail-builder", "md5", "mml-lib", @@ -2150,6 +2191,23 @@ dependencies = [ "generic-array", ] +[[package]] +name = "inquire" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe95f33091b9b7b517a5849bce4dce1b550b430fc20d58059fcaa319ed895d8b" +dependencies = [ + "bitflags 2.5.0", + "crossterm", + "dyn-clone", + "fuzzy-matcher", + "fxhash", + "newline-converter", + "once_cell", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "instant" version = "0.1.12" @@ -2578,6 +2636,15 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "999681fe3c0524336e98ece1c25ee4278607f25cc1e361ad0f9201c8bf56dc2c" +[[package]] +name = "newline-converter" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b6b097ecb1cbfed438542d16e84fd7ad9b0c76c8a65b7f9039212a3d14dc7f" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "nix" version = "0.26.4" @@ -4068,6 +4135,27 @@ dependencies = [ "thiserror", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -4633,6 +4721,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + [[package]] name = "unicode-width" version = "0.1.11" diff --git a/Cargo.toml b/Cargo.toml index 9e09ff0..ca4db63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ email-lib = { version = "=0.24.1", default-features = false, features = ["derive email_address = "0.2.4" erased-serde = "0.3" indicatif = "0.17" +inquire = "0.7.4" mail-builder = "0.3" md5 = "0.7" mml-lib = { version = "=1.0.12", default-features = false, features = ["derive"] } diff --git a/src/account/wizard.rs b/src/account/wizard.rs index 047e3c2..a2176e3 100644 --- a/src/account/wizard.rs +++ b/src/account/wizard.rs @@ -1,11 +1,11 @@ #[cfg(feature = "account-sync")] use crate::account::config::SyncConfig; -use color_eyre::{eyre::bail, Result}; +use color_eyre::{eyre::OptionExt, Result}; #[cfg(feature = "account-sync")] use dialoguer::Confirm; -use dialoguer::Input; use email_address::EmailAddress; -use std::str::FromStr; +use inquire::validator::{ErrorMessage, Validation}; +use std::{path::PathBuf, str::FromStr}; #[cfg(feature = "account-sync")] use crate::wizard_prompt; @@ -14,24 +14,26 @@ use crate::wizard_warn; use crate::{ backend::{self, config::BackendConfig, BackendKind}, message::config::{MessageConfig, MessageSendConfig}, - ui::THEME, }; use super::TomlAccountConfig; pub(crate) async fn configure() -> Result> { - let mut config = TomlAccountConfig::default(); + let mut config = TomlAccountConfig { + email: inquire::Text::new("Email address: ") + .with_validator(|email: &_| { + if EmailAddress::is_valid(email) { + Ok(Validation::Valid) + } else { + Ok(Validation::Invalid(ErrorMessage::Custom(format!( + "Invalid email address: {email}" + )))) + } + }) + .prompt()?, - config.email = Input::with_theme(&*THEME) - .with_prompt("Email address") - .validate_with(|email: &String| { - if EmailAddress::is_valid(email) { - Ok(()) - } else { - bail!("Invalid email address: {email}") - } - }) - .interact()?; + ..Default::default() + }; let addr = EmailAddress::from_str(&config.email).unwrap(); @@ -44,25 +46,26 @@ pub(crate) async fn configure() -> Result> { .ok() }); - let account_name = Input::with_theme(&*THEME) - .with_prompt("Account name") - .default(addr.domain().split_once('.').unwrap().0.to_owned()) - .interact()?; + let account_name = inquire::Text::new("Account name: ") + .with_default( + addr.domain() + .split_once('.') + .ok_or_eyre("not a valid domain, without any .")? + .0, + ) + .prompt()?; config.display_name = Some( - Input::with_theme(&*THEME) - .with_prompt("Full display name") - .default(addr.local_part().to_owned()) - .interact()?, + inquire::Text::new("Full display name: ") + .with_default(addr.local_part()) + .prompt()?, ); - config.downloads_dir = Some( - Input::with_theme(&*THEME) - .with_prompt("Downloads directory") - .default(String::from("~/Downloads")) - .interact()? - .into(), - ); + config.downloads_dir = Some(PathBuf::from( + inquire::Text::new("Downloads directory: ") + .with_default("~/Downloads") + .prompt()?, + )); let email = &config.email; #[cfg(feature = "account-discovery")]