Skip to content

Commit

Permalink
make use of pimalaya-tui
Browse files Browse the repository at this point in the history
  • Loading branch information
soywod committed Aug 31, 2024
1 parent 197b20d commit 1934119
Show file tree
Hide file tree
Showing 29 changed files with 1,173 additions and 2,050 deletions.
1,846 changes: 1,019 additions & 827 deletions Cargo.lock

Large diffs are not rendered by default.

76 changes: 27 additions & 49 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "neverest"
description = "CLI to synchronize, backup and restore emails"
version = "1.0.0-beta"
version = "1.0.0"
authors = ["soywod <[email protected]>"]
edition = "2021"
license = "MIT"
Expand All @@ -17,72 +17,50 @@ rustdoc-args = ["--cfg", "docsrs", "--document-private-items"]

[features]
default = [
# Enables the IMAP backend, which allows the synchronizer to connect
# to remote IMAP servers.
#
# doc: <https://pimalaya.org/neverest/cli/latest/configuration/imap.html>
"imap",

# Enables the Maildir backend, which allows the synchronizer to
# access your emails locally, using the file system.
#
# spec: <https://cr.yp.to/proto/maildir.html>
# doc: <https://pimalaya.org/neverest/cli/latest/configuration/maildir.html>
"maildir",
"notmuch",

# Enables the Notmuch backend, which allows the synchronizer to
# access your emails locally, using the Notmuch email system. This
# feature turns on the maildir feature, since Notmuch requires a
# Maildir folder to operate. This feature also requires the
# libnotmuch to be installed and available on your system.
#
# site: <https://notmuchmail.org/>
# doc: <https://pimalaya.org/neverest/cli/latest/configuration/notmuch.html>
# "notmuch",

# Enables the wizard configurator, which interactively helps you to
# configure your default account. It also automatically discovers
# remote IMAP settings from your email address.
#
# doc: <https://pimalaya.org/neverest/cli/latest/configuration/index.html#automatically-using-the-wizard>
"keyring",
"oauth2",
"wizard",
]

imap = ["email-lib/imap"]
maildir = ["email-lib/maildir"]
notmuch = ["email-lib/notmuch"]
wizard = [
"dep:console",
"dep:email_address",
"dep:oauth-lib",
"dep:secret-lib",
"dep:toml_edit",
"email-lib/account-discovery",
]
imap = ["email-lib/imap", "pimalaya-tui/imap"]
maildir = ["email-lib/maildir", "pimalaya-tui/maildir"]
notmuch = ["email-lib/notmuch", "pimalaya-tui/notmuch"]

keyring = ["email-lib/keyring", "pimalaya-tui/keyring", "secret-lib?/keyring-tokio"]
oauth2 = ["dep:oauth-lib", "email-lib/oauth2", "pimalaya-tui/oauth2", "keyring"]
wizard = ["dep:console", "dep:secret-lib", "email-lib/autoconfig"]

[dependencies]
clap = { version = "4.4", features = ["derive", "wrap_help"] }
clap_complete = "4.4"
clap_mangen = "0.2"
color-eyre = "0.6"
console = { version = "0.15.2", optional = true }
dialoguer = "0.10.2"
dirs = "4"
email-lib = { version = "=0.24.0", default-features = false, features = ["account-sync", "derive"] }
email_address = { version = "0.2.4", optional = true }
erased-serde = "0.3"
indicatif = "0.17"
email-lib = { version = "=0.25.0", default-features = false, features = ["pool", "sync", "derive"] }
oauth-lib = { version = "=0.1.1", optional = true }
once_cell = "1.16"
secret-lib = { version = "=0.4.4", optional = true, features = ["derive"] }
pimalaya-tui = { version = "=0.1.0", default-features = false, features = ["cli", "config", "tracing"] }
secret-lib = { version = "=0.4.6", optional = true, features = ["derive"] }
serde = { version = "1", features = ["derive"] }
serde-toml-merge = "0.3"
serde_json = "1"
shellexpand-utils = "=0.2.1"
termcolor = "1"
tokio = { version = "1.23", default-features = false, features = ["macros", "rt-multi-thread"] }
toml = "0.8"
toml_edit = { version = "0.22", optional = true }
tracing = "0.1"
tracing-error = "0.2"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

# TODO: delete console as soon as we can replace them with a crossterm
# alternative
console = { version = "0.15.2", optional = true }
indicatif = "0.17"

[patch.crates-io]
imap-codec = { git = "https://github.com/duesee/imap-codec" }
imap-next = { git = "https://github.com/duesee/imap-next", branch = "jakoschiko_poison-message-with-fragmentizer" }
imap-client = { git = "https://github.com/pimalaya/imap-client" }
oauth-lib = { git = "https://github.com/pimalaya/core" }
email-lib = { git = "https://github.com/pimalaya/core" }
pimalaya-tui = { git = "https://github.com/pimalaya/tui" }
12 changes: 6 additions & 6 deletions src/account/command/configure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use color_eyre::eyre::Result;
use email::imap::config::ImapAuthConfig;
#[cfg(feature = "smtp")]
use email::smtp::config::SmtpAuthConfig;
use pimalaya_tui::{cli::printer::Printer, prompt};
use tracing::{debug, info, instrument, warn};

use crate::{
account::arg::name::OptionalAccountNameArg, backend::config::BackendConfig, config::Config,
printer::Printer, ui::prompt,
};

/// Configure an account.
Expand Down Expand Up @@ -65,12 +65,12 @@ impl ConfigureAccountCommand {
BackendConfig::Imap(config) => match &config.auth {
ImapAuthConfig::Passwd(config) => {
config
.configure(|| prompt::passwd("Left IMAP password"))
.configure(|| Ok(prompt::password("Left IMAP password")?))
.await?;
}
ImapAuthConfig::OAuth2(config) => {
config
.configure(|| prompt::secret("Left IMAP OAuth 2.0 client secret"))
.configure(|| Ok(prompt::secret("Left IMAP OAuth 2.0 client secret")?))
.await?;
}
},
Expand All @@ -82,19 +82,19 @@ impl ConfigureAccountCommand {
BackendConfig::Imap(config) => match &config.auth {
ImapAuthConfig::Passwd(config) => {
config
.configure(|| prompt::passwd("Right IMAP password"))
.configure(|| Ok(prompt::password("Right IMAP password")?))
.await?;
}
ImapAuthConfig::OAuth2(config) => {
config
.configure(|| prompt::secret("Right IMAP OAuth 2.0 client secret"))
.configure(|| Ok(prompt::secret("Right IMAP OAuth 2.0 client secret")?))
.await?;
}
},
_ => (),
};

let re = if self.reset { "re" } else { "" };
printer.print(format!("Account {name} successfully {re}configured!"))
printer.out(format!("Account {name} successfully {re}configured!"))
}
}
21 changes: 11 additions & 10 deletions src/account/command/doctor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
//! This module contains the [`clap`] command for checking up left and
//! right backends integrity of a given account.

use std::sync::Arc;

use clap::Parser;
use color_eyre::eyre::Result;
use email::backend::{Backend, BackendBuilder};
Expand All @@ -12,12 +14,11 @@ use email::imap::{ImapContextBuilder, ImapContextSync};
use email::maildir::{MaildirContextBuilder, MaildirContextSync};
#[cfg(feature = "notmuch")]
use email::notmuch::{NotmuchContextBuilder, NotmuchContextSync};
use std::sync::Arc;
use pimalaya_tui::cli::printer::Printer;
use tracing::{info, instrument};

use crate::{
account::arg::name::OptionalAccountNameArg, backend::config::BackendConfig, config::Config,
printer::Printer,
};

/// Check up the given account.
Expand All @@ -37,7 +38,7 @@ impl DoctorAccountCommand {
info!("executing doctor account command");

let (name, config) = config.into_account_config(self.account.name.as_deref())?;
printer.print_log(format!("Checking `{name}` account integrity…"))?;
printer.log(format!("Checking `{name}` account integrity…"))?;

let folder_filter = config.folder.map(|c| c.filters).unwrap_or_default();
let envelope_filter = config.envelope.map(|c| c.filters).unwrap_or_default();
Expand All @@ -51,23 +52,23 @@ impl DoctorAccountCommand {
match left_backend {
#[cfg(feature = "imap")]
BackendConfig::Imap(imap_config) => {
printer.print_log("Checking left IMAP integrity…")?;
printer.log("Checking left IMAP integrity…")?;
let ctx = ImapContextBuilder::new(left_config.clone(), Arc::new(imap_config));
BackendBuilder::new(left_config.clone(), ctx)
.check_up::<Backend<ImapContextSync>>()
.await?;
}
#[cfg(feature = "maildir")]
BackendConfig::Maildir(maildir_config) => {
printer.print_log("Checking left Maildir integrity…")?;
printer.log("Checking left Maildir integrity…")?;
let ctx = MaildirContextBuilder::new(left_config.clone(), Arc::new(maildir_config));
BackendBuilder::new(left_config.clone(), ctx)
.check_up::<Backend<MaildirContextSync>>()
.await?;
}
#[cfg(feature = "notmuch")]
BackendConfig::Notmuch(notmuch_config) => {
printer.print_log("Checking left Notmuch integrity…")?;
printer.log("Checking left Notmuch integrity…")?;
let ctx = NotmuchContextBuilder::new(left_config.clone(), Arc::new(notmuch_config));
BackendBuilder::new(left_config.clone(), ctx)
.check_up::<Backend<NotmuchContextSync>>()
Expand All @@ -83,15 +84,15 @@ impl DoctorAccountCommand {
match right_backend {
#[cfg(feature = "imap")]
BackendConfig::Imap(imap_config) => {
printer.print_log("Checking right IMAP integrity…")?;
printer.log("Checking right IMAP integrity…")?;
let ctx = ImapContextBuilder::new(right_config.clone(), Arc::new(imap_config));
BackendBuilder::new(right_config.clone(), ctx)
.check_up::<Backend<ImapContextSync>>()
.await?;
}
#[cfg(feature = "maildir")]
BackendConfig::Maildir(maildir_config) => {
printer.print_log("Checking right Maildir integrity…")?;
printer.log("Checking right Maildir integrity…")?;
let ctx =
MaildirContextBuilder::new(right_config.clone(), Arc::new(maildir_config));
BackendBuilder::new(right_config.clone(), ctx)
Expand All @@ -100,7 +101,7 @@ impl DoctorAccountCommand {
}
#[cfg(feature = "notmuch")]
BackendConfig::Notmuch(notmuch_config) => {
printer.print_log("Checking right Notmuch integrity…")?;
printer.log("Checking right Notmuch integrity…")?;
let ctx =
NotmuchContextBuilder::new(right_config.clone(), Arc::new(notmuch_config));
BackendBuilder::new(right_config.clone(), ctx)
Expand All @@ -109,6 +110,6 @@ impl DoctorAccountCommand {
}
};

printer.print("Checkup successfully completed!")
printer.out("Checkup successfully completed!")
}
}
41 changes: 21 additions & 20 deletions src/account/command/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
//! This module contains the [`clap`] command for synchronizing two
//! backends of a given account.

use std::{
collections::{BTreeSet, HashMap},
sync::{Arc, Mutex},
};

use clap::{ArgAction, Parser};
use color_eyre::eyre::Result;
#[cfg(feature = "imap")]
Expand All @@ -19,15 +24,11 @@ use email::{
};
use indicatif::{MultiProgress, ProgressBar, ProgressFinish, ProgressStyle};
use once_cell::sync::Lazy;
use std::{
collections::{BTreeSet, HashMap},
sync::{Arc, Mutex},
};
use pimalaya_tui::cli::printer::Printer;
use tracing::{info, instrument};

use crate::{
account::arg::name::OptionalAccountNameArg, backend::config::BackendConfig, config::Config,
printer::Printer,
};

static MAIN_PROGRESS_STYLE: Lazy<ProgressStyle> = Lazy::new(|| {
Expand Down Expand Up @@ -199,28 +200,28 @@ impl SynchronizeAccountCommand {
let mut hunks_count = report.folder.patch.len();

if !report.folder.patch.is_empty() {
printer.print_log("Folders patch:")?;
printer.log("Folders patch:")?;
for (hunk, _) in report.folder.patch {
printer.print_log(format!(" - {hunk}"))?;
printer.log(format!(" - {hunk}"))?;
}
printer.print_log("")?;
printer.log("")?;
}

if !report.email.patch.is_empty() {
printer.print_log("Envelopes patch:")?;
printer.log("Envelopes patch:")?;
for (hunk, _) in report.email.patch {
hunks_count += 1;
printer.print_log(format!(" - {hunk}"))?;
printer.log(format!(" - {hunk}"))?;
}
printer.print_log("")?;
printer.log("")?;
}

printer.print(format!(
printer.out(format!(
"Estimated patch length for account {account_name} to be synchronized: {hunks_count}"
))?;
} else if printer.is_json() {
sync_builder.sync().await?;
printer.print(format!("Account {account_name} successfully synchronized!"))?;
printer.out(format!("Account {account_name} successfully synchronized!"))?;
} else {
let multi = MultiProgress::new();
let sub_progresses = Mutex::new(HashMap::new());
Expand Down Expand Up @@ -300,11 +301,11 @@ impl SynchronizeAccountCommand {
.filter_map(|(hunk, err)| err.as_ref().map(|err| (hunk, err)))
.collect::<Vec<_>>();
if !folders_patch_err.is_empty() {
printer.print_log("")?;
printer.print_log("Errors occurred while applying the folders patch:")?;
printer.log("")?;
printer.log("Errors occurred while applying the folders patch:")?;
folders_patch_err
.iter()
.try_for_each(|(hunk, err)| printer.print_log(format!(" - {hunk}: {err}")))?;
.try_for_each(|(hunk, err)| printer.log(format!(" - {hunk}: {err}")))?;
}

let envelopes_patch_err = report
Expand All @@ -314,14 +315,14 @@ impl SynchronizeAccountCommand {
.filter_map(|(hunk, err)| err.as_ref().map(|err| (hunk, err)))
.collect::<Vec<_>>();
if !envelopes_patch_err.is_empty() {
printer.print_log("")?;
printer.print_log("Errors occurred while applying the envelopes patch:")?;
printer.log("")?;
printer.log("Errors occurred while applying the envelopes patch:")?;
for (hunk, err) in envelopes_patch_err {
printer.print_log(format!(" - {hunk}: {err}"))?;
printer.log(format!(" - {hunk}: {err}"))?;
}
}

printer.print(format!("Account {account_name} successfully synchronized!"))?;
printer.out(format!("Account {account_name} successfully synchronized!"))?;
}

Ok(())
Expand Down
8 changes: 5 additions & 3 deletions src/account/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use email::{
};
use serde::{Deserialize, Serialize};

use crate::backend::config::{BackendConfig, BackendGlobalConfig};
#[cfg(all(feature = "imap", feature = "keyring"))]
use crate::backend::config::BackendConfig;
use crate::backend::config::BackendGlobalConfig;

/// The account configuration.
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
Expand Down Expand Up @@ -48,7 +50,7 @@ impl AccountConfig {
/// entries by default ones, based on the given account name.
pub fn configure(&mut self, account_name: &str) -> Result<()> {
match &mut self.left.backend {
#[cfg(feature = "imap")]
#[cfg(all(feature = "imap", feature = "keyring"))]
BackendConfig::Imap(config) => {
config
.auth
Expand All @@ -58,7 +60,7 @@ impl AccountConfig {
}

match &mut self.right.backend {
#[cfg(feature = "imap")]
#[cfg(all(feature = "imap", feature = "keyring"))]
BackendConfig::Imap(config) => {
config
.auth
Expand Down
Loading

0 comments on commit 1934119

Please sign in to comment.