mirror of
https://github.com/soywod/himalaya.git
synced 2024-07-08 18:45:13 +00:00
clean doc
This commit is contained in:
parent
fff11fbe20
commit
ef3214f36f
|
@ -1,26 +1,24 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
/// The account name argument parser
|
/// The account name argument parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct AccountNameArg {
|
pub struct AccountNameArg {
|
||||||
/// The name of the account
|
/// The name of the account.
|
||||||
///
|
///
|
||||||
/// The account names are taken from the table at the root level
|
/// An account name corresponds to an entry in the table at the
|
||||||
/// of your TOML configuration file.
|
/// root level of your TOML configuration file.
|
||||||
#[arg(value_name = "ACCOUNT")]
|
#[arg(name = "account_name", value_name = "ACCOUNT")]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The account name flag parser
|
/// The account name flag parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct AccountNameFlag {
|
pub struct AccountNameFlag {
|
||||||
/// Override the default account
|
/// Override the default account.
|
||||||
#[arg(
|
///
|
||||||
long = "account",
|
/// An account name corresponds to an entry in the table at the
|
||||||
short = 'a',
|
/// root level of your TOML configuration file.
|
||||||
name = "account-name",
|
#[arg(long = "account", short = 'a', global = true)]
|
||||||
value_name = "NAME",
|
#[arg(name = "account_name", value_name = "NAME")]
|
||||||
global = true
|
|
||||||
)]
|
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,26 +15,32 @@ use crate::{
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Configure the given account
|
/// Configure an account.
|
||||||
|
///
|
||||||
|
/// This command is mostly used to define or reset passwords managed
|
||||||
|
/// by your global keyring. If you do not use the keyring system, you
|
||||||
|
/// can skip this command.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct AccountConfigureCommand {
|
pub struct AccountConfigureCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameArg,
|
pub account: AccountNameArg,
|
||||||
|
|
||||||
/// Force the account to reconfigure, even if it has already been
|
/// Reset keyring passwords.
|
||||||
/// configured
|
///
|
||||||
|
/// This argument will force passwords to be prompted again, then
|
||||||
|
/// saved to your global keyring.
|
||||||
#[arg(long, short)]
|
#[arg(long, short)]
|
||||||
pub force: bool,
|
pub reset: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountConfigureCommand {
|
impl AccountConfigureCommand {
|
||||||
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
|
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
|
||||||
info!("executing account configure command");
|
info!("executing account configure command");
|
||||||
|
|
||||||
let (_, account_config) =
|
let account = &self.account.name;
|
||||||
config.into_toml_account_config(Some(self.account.name.as_str()))?;
|
let (_, account_config) = config.into_toml_account_config(Some(account))?;
|
||||||
|
|
||||||
if self.force {
|
if self.reset {
|
||||||
#[cfg(feature = "imap")]
|
#[cfg(feature = "imap")]
|
||||||
if let Some(ref config) = account_config.imap {
|
if let Some(ref config) = account_config.imap {
|
||||||
let reset = match &config.auth {
|
let reset = match &config.auth {
|
||||||
|
@ -102,11 +108,8 @@ impl AccountConfigureCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
printer.print(format!(
|
printer.print(format!(
|
||||||
"Account {} successfully {}configured!",
|
"Account {account} successfully {}configured!",
|
||||||
self.account.name,
|
if self.reset { "re" } else { "" }
|
||||||
if self.force { "re" } else { "" }
|
))
|
||||||
))?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,17 @@ use crate::{
|
||||||
account::Accounts,
|
account::Accounts,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
printer::{PrintTableOpts, Printer},
|
printer::{PrintTableOpts, Printer},
|
||||||
ui::arg::max_width::MaxTableWidthFlag,
|
ui::arg::max_width::TableMaxWidthFlag,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// List all accounts
|
/// List all accounts.
|
||||||
|
///
|
||||||
|
/// This command lists all accounts defined in your TOML configuration
|
||||||
|
/// file.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct AccountListCommand {
|
pub struct AccountListCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub table: MaxTableWidthFlag,
|
pub table: TableMaxWidthFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountListCommand {
|
impl AccountListCommand {
|
||||||
|
@ -31,9 +34,7 @@ impl AccountListCommand {
|
||||||
.unwrap_or(&Default::default()),
|
.unwrap_or(&Default::default()),
|
||||||
max_width: self.table.max_width,
|
max_width: self.table.max_width,
|
||||||
},
|
},
|
||||||
)?;
|
)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,18 +11,19 @@ use self::{
|
||||||
configure::AccountConfigureCommand, list::AccountListCommand, sync::AccountSyncCommand,
|
configure::AccountConfigureCommand, list::AccountListCommand, sync::AccountSyncCommand,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Subcommand to manage accounts
|
/// Manage accounts.
|
||||||
|
///
|
||||||
|
/// An account is a set of settings, identified by an account
|
||||||
|
/// name. Settings are directly taken from your TOML configuration
|
||||||
|
/// file.
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
pub enum AccountSubcommand {
|
pub enum AccountSubcommand {
|
||||||
/// Configure an account
|
|
||||||
#[command(alias = "cfg")]
|
#[command(alias = "cfg")]
|
||||||
Configure(AccountConfigureCommand),
|
Configure(AccountConfigureCommand),
|
||||||
|
|
||||||
/// List all accounts
|
|
||||||
#[command(alias = "lst")]
|
#[command(alias = "lst")]
|
||||||
List(AccountListCommand),
|
List(AccountListCommand),
|
||||||
|
|
||||||
/// Synchronize an account locally
|
|
||||||
#[command()]
|
#[command()]
|
||||||
Sync(AccountSyncCommand),
|
Sync(AccountSyncCommand),
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,30 +32,49 @@ const SUB_PROGRESS_DONE_STYLE: Lazy<ProgressStyle> = Lazy::new(|| {
|
||||||
ProgressStyle::with_template(" {prefix:.bold} \n {wide_bar:.green} {percent}% ").unwrap()
|
ProgressStyle::with_template(" {prefix:.bold} \n {wide_bar:.green} {percent}% ").unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Synchronize an account.
|
||||||
|
///
|
||||||
|
/// This command allows you to synchronize all folders and emails
|
||||||
|
/// (including envelopes and messages) of an account into a local
|
||||||
|
/// Maildir folder.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct AccountSyncCommand {
|
pub struct AccountSyncCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameArg,
|
pub account: AccountNameArg,
|
||||||
|
|
||||||
/// Run the synchronization without applying changes
|
/// Run the synchronization without applying any changes.
|
||||||
///
|
///
|
||||||
/// Instead, a report will be printed to stdout containing all the
|
/// Instead, a report will be printed to stdout containing all the
|
||||||
/// changes the synchronization plan to do.
|
/// changes the synchronization plan to do.
|
||||||
#[arg(long, short)]
|
#[arg(long, short)]
|
||||||
pub dry_run: bool,
|
pub dry_run: bool,
|
||||||
|
|
||||||
#[arg(long, short = 'f', value_name = "FOLDER", action = ArgAction::Append, conflicts_with = "exclude_folder", conflicts_with = "all_folders")]
|
/// Synchronize only specific folders.
|
||||||
|
///
|
||||||
|
/// Only the given folders will be synchronized (including
|
||||||
|
/// associated envelopes and messages). Useful when you need to
|
||||||
|
/// speed up the synchronization process. A good usecase is to
|
||||||
|
/// synchronize only the INBOX in order to quickly check for new
|
||||||
|
/// messages.
|
||||||
|
#[arg(long, short = 'f')]
|
||||||
|
#[arg(value_name = "FOLDER", action = ArgAction::Append)]
|
||||||
|
#[arg(conflicts_with = "exclude_folder", conflicts_with = "all_folders")]
|
||||||
pub include_folder: Vec<String>,
|
pub include_folder: Vec<String>,
|
||||||
|
|
||||||
#[arg(long, short = 'x', value_name = "FOLDER", action = ArgAction::Append, conflicts_with = "include_folder", conflicts_with = "all_folders")]
|
/// Omit specific folders from the synchronization.
|
||||||
|
///
|
||||||
|
/// The given folders will be excluded from the synchronization
|
||||||
|
/// (including associated envelopes and messages). Useful when you
|
||||||
|
/// have heavy folders that you do not want to take care of, or to
|
||||||
|
/// speed up the synchronization process.
|
||||||
|
#[arg(long, short = 'x')]
|
||||||
|
#[arg(value_name = "FOLDER", action = ArgAction::Append)]
|
||||||
|
#[arg(conflicts_with = "include_folder", conflicts_with = "all_folders")]
|
||||||
pub exclude_folder: Vec<String>,
|
pub exclude_folder: Vec<String>,
|
||||||
|
|
||||||
#[arg(
|
/// Synchronize all exsting folders.
|
||||||
long,
|
#[arg(long, short = 'A')]
|
||||||
short = 'A',
|
#[arg(conflicts_with = "include_folder", conflicts_with = "exclude_folder")]
|
||||||
conflicts_with = "include_folder",
|
|
||||||
conflicts_with = "exclude_folder"
|
|
||||||
)]
|
|
||||||
pub all_folders: bool,
|
pub all_folders: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
src/cache/arg/disable.rs
vendored
18
src/cache/arg/disable.rs
vendored
|
@ -1,19 +1,15 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
/// The disable cache flag parser
|
/// The disable cache flag parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct DisableCacheFlag {
|
pub struct CacheDisableFlag {
|
||||||
/// Disable any sort of cache
|
/// Disable any sort of cache.
|
||||||
///
|
///
|
||||||
/// The action depends on commands it apply on. For example, when
|
/// The action depends on commands it apply on. For example, when
|
||||||
/// listing envelopes using the IMAP backend, this flag will
|
/// listing envelopes using the IMAP backend, this flag will
|
||||||
/// ensure that envelopes are fetched from the IMAP server and not
|
/// ensure that envelopes are fetched from the IMAP server rather
|
||||||
/// from the synchronized local Maildir.
|
/// than the synchronized local Maildir.
|
||||||
#[arg(
|
#[arg(long = "disable-cache", alias = "no-cache", global = true)]
|
||||||
long = "disable-cache",
|
#[arg(name = "cache_disable")]
|
||||||
alias = "no-cache",
|
|
||||||
name = "disable-cache",
|
|
||||||
global = true
|
|
||||||
)]
|
|
||||||
pub disable: bool,
|
pub disable: bool,
|
||||||
}
|
}
|
||||||
|
|
28
src/cli.rs
28
src/cli.rs
|
@ -19,14 +19,8 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(
|
#[command(name = "himalaya", author, version, about)]
|
||||||
name = "himalaya",
|
#[command(propagate_version = true, infer_subcommands = true)]
|
||||||
author,
|
|
||||||
version,
|
|
||||||
about,
|
|
||||||
propagate_version = true,
|
|
||||||
infer_subcommands = true
|
|
||||||
)]
|
|
||||||
pub struct Cli {
|
pub struct Cli {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
pub command: HimalayaCommand,
|
pub command: HimalayaCommand,
|
||||||
|
@ -83,46 +77,38 @@ pub struct Cli {
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
pub enum HimalayaCommand {
|
pub enum HimalayaCommand {
|
||||||
/// Manage accounts
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
#[command(alias = "accounts")]
|
#[command(alias = "accounts")]
|
||||||
Account(AccountSubcommand),
|
Account(AccountSubcommand),
|
||||||
|
|
||||||
/// Manage folders
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
#[command(alias = "folders")]
|
#[command(alias = "folders")]
|
||||||
Folder(FolderSubcommand),
|
Folder(FolderSubcommand),
|
||||||
|
|
||||||
/// Manage envelopes
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
#[command(alias = "envelopes")]
|
#[command(alias = "envelopes")]
|
||||||
Envelope(EnvelopeSubcommand),
|
Envelope(EnvelopeSubcommand),
|
||||||
|
|
||||||
/// Manage flags
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
#[command(alias = "flags")]
|
#[command(alias = "flags")]
|
||||||
Flag(FlagSubcommand),
|
Flag(FlagSubcommand),
|
||||||
|
|
||||||
/// Manage messages
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
#[command(alias = "messages", alias = "msgs", alias = "msg")]
|
#[command(alias = "messages", alias = "msgs", alias = "msg")]
|
||||||
Message(MessageSubcommand),
|
Message(MessageSubcommand),
|
||||||
|
|
||||||
/// Manage templates
|
#[command(subcommand)]
|
||||||
|
#[command(alias = "attachments")]
|
||||||
|
Attachment(AttachmentSubcommand),
|
||||||
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
#[command(alias = "templates", alias = "tpls", alias = "tpl")]
|
#[command(alias = "templates", alias = "tpls", alias = "tpl")]
|
||||||
Template(TemplateSubcommand),
|
Template(TemplateSubcommand),
|
||||||
|
|
||||||
/// Manage attachments
|
|
||||||
#[command(subcommand)]
|
|
||||||
Attachment(AttachmentSubcommand),
|
|
||||||
|
|
||||||
/// Generate manual pages to a directory
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
#[command(alias = "manuals", alias = "mans")]
|
#[command(alias = "manuals", alias = "mans")]
|
||||||
Manual(ManualGenerateCommand),
|
Manual(ManualGenerateCommand),
|
||||||
|
|
||||||
/// Print completion script for a shell to stdout
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
#[command(alias = "completions")]
|
#[command(alias = "completions")]
|
||||||
Completion(CompletionGenerateCommand),
|
Completion(CompletionGenerateCommand),
|
||||||
|
@ -136,8 +122,8 @@ impl HimalayaCommand {
|
||||||
Self::Envelope(cmd) => cmd.execute(printer, config).await,
|
Self::Envelope(cmd) => cmd.execute(printer, config).await,
|
||||||
Self::Flag(cmd) => cmd.execute(printer, config).await,
|
Self::Flag(cmd) => cmd.execute(printer, config).await,
|
||||||
Self::Message(cmd) => cmd.execute(printer, config).await,
|
Self::Message(cmd) => cmd.execute(printer, config).await,
|
||||||
Self::Template(cmd) => cmd.execute(printer, config).await,
|
|
||||||
Self::Attachment(cmd) => cmd.execute(printer, config).await,
|
Self::Attachment(cmd) => cmd.execute(printer, config).await,
|
||||||
|
Self::Template(cmd) => cmd.execute(printer, config).await,
|
||||||
Self::Manual(cmd) => cmd.execute(printer).await,
|
Self::Manual(cmd) => cmd.execute(printer).await,
|
||||||
Self::Completion(cmd) => cmd.execute(printer).await,
|
Self::Completion(cmd) => cmd.execute(printer).await,
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,14 @@ use std::io;
|
||||||
|
|
||||||
use crate::{cli::Cli, printer::Printer};
|
use crate::{cli::Cli, printer::Printer};
|
||||||
|
|
||||||
/// Print completion script for a shell to stdout
|
/// Print completion script for a shell to stdout.
|
||||||
|
///
|
||||||
|
/// This command allows you to generate completion script for a given
|
||||||
|
/// shell. The script is printed to the standard output. If you want
|
||||||
|
/// to write it to a file, just use unix redirection.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct CompletionGenerateCommand {
|
pub struct CompletionGenerateCommand {
|
||||||
/// Shell for which completion script should be generated for
|
/// Shell for which completion script should be generated for.
|
||||||
#[arg(value_parser = value_parser!(Shell))]
|
#[arg(value_parser = value_parser!(Shell))]
|
||||||
pub shell: Shell,
|
pub shell: Shell,
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,10 +121,7 @@ impl TomlConfig {
|
||||||
match path.map(Into::into) {
|
match path.map(Into::into) {
|
||||||
Some(ref path) if path.exists() => Self::from_path(path),
|
Some(ref path) if path.exists() => Self::from_path(path),
|
||||||
Some(path) => Self::from_wizard(path).await,
|
Some(path) => Self::from_wizard(path).await,
|
||||||
None => match Self::first_valid_default_path() {
|
None => Self::from_default_paths().await,
|
||||||
Some(path) => Self::from_path(&path),
|
|
||||||
None => Self::from_wizard(Self::default_path()?).await,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
/// The envelope id argument parser
|
/// The envelope id argument parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct EnvelopeIdArg {
|
pub struct EnvelopeIdArg {
|
||||||
/// The envelope id
|
/// The envelope id.
|
||||||
#[arg(value_name = "ID", required = true)]
|
#[arg(value_name = "ID", required = true)]
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The envelopes ids arguments parser
|
/// The envelopes ids arguments parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct EnvelopeIdsArgs {
|
pub struct EnvelopeIdsArgs {
|
||||||
/// The list of envelopes ids
|
/// The list of envelopes ids.
|
||||||
#[arg(value_name = "ID", required = true)]
|
#[arg(value_name = "ID", required = true)]
|
||||||
pub ids: Vec<usize>,
|
pub ids: Vec<usize>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,35 +5,43 @@ use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
folder::arg::name::FolderNameOptionalArg,
|
folder::arg::name::FolderNameOptionalArg,
|
||||||
printer::{PrintTableOpts, Printer},
|
printer::{PrintTableOpts, Printer},
|
||||||
ui::arg::max_width::MaxTableWidthFlag,
|
ui::arg::max_width::TableMaxWidthFlag,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// List all envelopes from a folder
|
/// List all envelopes.
|
||||||
|
///
|
||||||
|
/// This command allows you to list all envelopes included in the
|
||||||
|
/// given folder.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct EnvelopeListCommand {
|
pub struct EnvelopeListCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub folder: FolderNameOptionalArg,
|
pub folder: FolderNameOptionalArg,
|
||||||
|
|
||||||
/// The page number
|
/// The page number.
|
||||||
|
///
|
||||||
|
/// The page number starts from 1 (which is the default). Giving a
|
||||||
|
/// page number to big will result in a out of bound error.
|
||||||
#[arg(long, short, value_name = "NUMBER", default_value = "1")]
|
#[arg(long, short, value_name = "NUMBER", default_value = "1")]
|
||||||
pub page: usize,
|
pub page: usize,
|
||||||
|
|
||||||
/// The page size
|
/// The page size.
|
||||||
|
///
|
||||||
|
/// Determine the amount of envelopes a page should contain.
|
||||||
#[arg(long, short = 's', value_name = "NUMBER")]
|
#[arg(long, short = 's', value_name = "NUMBER")]
|
||||||
pub page_size: Option<usize>,
|
pub page_size: Option<usize>,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub table: MaxTableWidthFlag,
|
pub table: TableMaxWidthFlag,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
|
||||||
pub cache: DisableCacheFlag,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnvelopeListCommand {
|
impl EnvelopeListCommand {
|
||||||
|
|
|
@ -7,10 +7,14 @@ use crate::{config::TomlConfig, printer::Printer};
|
||||||
|
|
||||||
use self::list::EnvelopeListCommand;
|
use self::list::EnvelopeListCommand;
|
||||||
|
|
||||||
/// Subcommand to manage envelopes
|
/// Manage envelopes.
|
||||||
|
///
|
||||||
|
/// An envelope is a small representation of a message. It contains an
|
||||||
|
/// identifier (given by the backend), some flags as well as few
|
||||||
|
/// headers from the message itself. This subcommand allows you to
|
||||||
|
/// manage them.
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
pub enum EnvelopeSubcommand {
|
pub enum EnvelopeSubcommand {
|
||||||
/// List all envelopes from a folder
|
|
||||||
#[command(alias = "lst")]
|
#[command(alias = "lst")]
|
||||||
List(EnvelopeListCommand),
|
List(EnvelopeListCommand),
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@ use clap::Parser;
|
||||||
use email::flag::{Flag, Flags};
|
use email::flag::{Flag, Flags};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
/// The ids and/or flags arguments parser
|
/// The ids and/or flags arguments parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct IdsAndFlagsArgs {
|
pub struct IdsAndFlagsArgs {
|
||||||
/// The list of ids and/or flags
|
/// The list of ids and/or flags.
|
||||||
///
|
///
|
||||||
/// Every argument that can be parsed as an integer is considered
|
/// Every argument that can be parsed as an integer is considered
|
||||||
/// an id, otherwise it is considered as a flag.
|
/// an id, otherwise it is considered as a flag.
|
||||||
|
|
|
@ -5,14 +5,17 @@ use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
|
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
|
||||||
folder::arg::name::FolderNameArg,
|
folder::arg::name::FolderNameArg,
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Add flag(s) to an envelope
|
/// Add flag(s) to an envelope.
|
||||||
|
///
|
||||||
|
/// This command allows you to attach the given flag(s) to the given
|
||||||
|
/// envelope(s).
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct FlagAddCommand {
|
pub struct FlagAddCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -22,10 +25,10 @@ pub struct FlagAddCommand {
|
||||||
pub args: IdsAndFlagsArgs,
|
pub args: IdsAndFlagsArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub account: AccountNameFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FlagAddCommand {
|
impl FlagAddCommand {
|
||||||
|
|
|
@ -9,20 +9,22 @@ use crate::{config::TomlConfig, printer::Printer};
|
||||||
|
|
||||||
use self::{add::FlagAddCommand, remove::FlagRemoveCommand, set::FlagSetCommand};
|
use self::{add::FlagAddCommand, remove::FlagRemoveCommand, set::FlagSetCommand};
|
||||||
|
|
||||||
/// Subcommand to manage flags
|
/// Manage flags.
|
||||||
|
///
|
||||||
|
/// A flag is a tag associated to an envelope. Existing flags are
|
||||||
|
/// seen, answered, flagged, deleted, draft. Other flags are
|
||||||
|
/// considered custom, which are not always supported (the
|
||||||
|
/// synchronization does not take care of them yet).
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
pub enum FlagSubcommand {
|
pub enum FlagSubcommand {
|
||||||
/// Add flag(s) to an envelope
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
#[command(alias = "create")]
|
#[command(alias = "create")]
|
||||||
Add(FlagAddCommand),
|
Add(FlagAddCommand),
|
||||||
|
|
||||||
/// Replace flag(s) of an envelope
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
#[command(aliases = ["update", "change", "replace"])]
|
#[command(aliases = ["update", "change", "replace"])]
|
||||||
Set(FlagSetCommand),
|
Set(FlagSetCommand),
|
||||||
|
|
||||||
/// Remove flag(s) from an envelope
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
#[command(aliases = ["rm", "delete", "del"])]
|
#[command(aliases = ["rm", "delete", "del"])]
|
||||||
Remove(FlagRemoveCommand),
|
Remove(FlagRemoveCommand),
|
||||||
|
|
|
@ -5,14 +5,17 @@ use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
|
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
|
||||||
folder::arg::name::FolderNameArg,
|
folder::arg::name::FolderNameArg,
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Remove flag(s) from an envelope
|
/// Remove flag(s) from an envelope.
|
||||||
|
///
|
||||||
|
/// This command allows you to remove the given flag(s) from the given
|
||||||
|
/// envelope(s).
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct FlagRemoveCommand {
|
pub struct FlagRemoveCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -22,10 +25,10 @@ pub struct FlagRemoveCommand {
|
||||||
pub args: IdsAndFlagsArgs,
|
pub args: IdsAndFlagsArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub account: AccountNameFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FlagRemoveCommand {
|
impl FlagRemoveCommand {
|
||||||
|
|
|
@ -5,14 +5,17 @@ use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
|
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
|
||||||
folder::arg::name::FolderNameArg,
|
folder::arg::name::FolderNameArg,
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Replace flag(s) of an envelope
|
/// Replace flag(s) of an envelope.
|
||||||
|
///
|
||||||
|
/// This command allows you to replace existing flags of the given
|
||||||
|
/// envelope(s) with the given flag(s).
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct FlagSetCommand {
|
pub struct FlagSetCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -22,10 +25,10 @@ pub struct FlagSetCommand {
|
||||||
pub args: IdsAndFlagsArgs,
|
pub args: IdsAndFlagsArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub account: AccountNameFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FlagSetCommand {
|
impl FlagSetCommand {
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
/// The raw message body argument parser
|
/// The raw message body argument parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct BodyRawArg {
|
pub struct MessageRawBodyArg {
|
||||||
/// Prefill the template with a custom body
|
/// Prefill the template with a custom body.
|
||||||
#[arg(raw = true, required = false)]
|
#[arg(trailing_var_arg = true)]
|
||||||
#[arg(name = "body-raw", value_delimiter = ' ')]
|
#[arg(name = "body-raw")]
|
||||||
pub raw: Vec<String>,
|
pub raw: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BodyRawArg {
|
impl MessageRawBodyArg {
|
||||||
pub fn raw(self) -> String {
|
pub fn raw(self) -> String {
|
||||||
self.raw.join(" ").replace("\r", "").replace("\n", "\r\n")
|
self.raw.join(" ").replace("\r", "").replace("\n", "\r\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for BodyRawArg {
|
impl Deref for MessageRawBodyArg {
|
||||||
type Target = Vec<String>;
|
type Target = Vec<String>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
/// The envelope id argument parser
|
/// The envelope id argument parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct HeaderRawArgs {
|
pub struct HeaderRawArgs {
|
||||||
/// Prefill the template with custom headers
|
/// Prefill the template with custom headers.
|
||||||
///
|
///
|
||||||
/// A raw header should follow the pattern KEY:VAL.
|
/// A raw header should follow the pattern KEY:VAL.
|
||||||
#[arg(long = "header", short = 'H', required = false)]
|
#[arg(long = "header", short = 'H', required = false)]
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
/// The reply to all argument parser
|
/// The reply to all argument parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MessageReplyAllArg {
|
pub struct MessageReplyAllArg {
|
||||||
/// Reply to all recipients
|
/// Reply to all recipients.
|
||||||
|
///
|
||||||
|
/// This argument will add all recipients for the To and Cc
|
||||||
|
/// headers.
|
||||||
#[arg(long, short = 'A')]
|
#[arg(long, short = 'A')]
|
||||||
pub all: bool,
|
pub all: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,15 @@ use std::fs;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig, envelope::arg::ids::EnvelopeIdsArgs, folder::arg::name::FolderNameArg,
|
config::TomlConfig, envelope::arg::ids::EnvelopeIdsArgs, folder::arg::name::FolderNameArg,
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Download attachments of a message
|
/// Download all attachments for the given message.
|
||||||
|
///
|
||||||
|
/// This command allows you to download all attachments found for the
|
||||||
|
/// given message to your downloads directory.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct AttachmentDownloadCommand {
|
pub struct AttachmentDownloadCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -20,7 +23,7 @@ pub struct AttachmentDownloadCommand {
|
||||||
pub envelopes: EnvelopeIdsArgs,
|
pub envelopes: EnvelopeIdsArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
|
@ -7,10 +7,13 @@ use crate::{config::TomlConfig, printer::Printer};
|
||||||
|
|
||||||
use self::download::AttachmentDownloadCommand;
|
use self::download::AttachmentDownloadCommand;
|
||||||
|
|
||||||
/// Subcommand dedicated to attachments
|
/// Manage attachments.
|
||||||
|
///
|
||||||
|
/// A message body can be composed of multiple MIME parts. An
|
||||||
|
/// attachment is the representation of a binary part of a message
|
||||||
|
/// body.
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
pub enum AttachmentSubcommand {
|
pub enum AttachmentSubcommand {
|
||||||
/// Download all attachments of one or more messages
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
Download(AttachmentDownloadCommand),
|
Download(AttachmentDownloadCommand),
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,14 @@ use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
envelope::arg::ids::EnvelopeIdsArgs,
|
envelope::arg::ids::EnvelopeIdsArgs,
|
||||||
folder::arg::name::{SourceFolderNameArg, TargetFolderNameArg},
|
folder::arg::name::{SourceFolderNameArg, TargetFolderNameArg},
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Copy a message from a source folder to a target folder
|
/// Copy a message from a source folder to a target folder.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MessageCopyCommand {
|
pub struct MessageCopyCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -25,7 +25,7 @@ pub struct MessageCopyCommand {
|
||||||
pub envelopes: EnvelopeIdsArgs,
|
pub envelopes: EnvelopeIdsArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
|
@ -3,12 +3,17 @@ use clap::Parser;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig, envelope::arg::ids::EnvelopeIdsArgs, folder::arg::name::FolderNameArg,
|
config::TomlConfig, envelope::arg::ids::EnvelopeIdsArgs, folder::arg::name::FolderNameArg,
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Delete a message from a folder
|
/// Mark as deleted a message from a folder.
|
||||||
|
///
|
||||||
|
/// This command does not really delete the message: if the given
|
||||||
|
/// folder points to the trash folder, it adds the "deleted" flag to
|
||||||
|
/// its envelope, otherwise it moves it to the trash folder. Only the
|
||||||
|
/// expunge folder command truly deletes messages.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MessageDeleteCommand {
|
pub struct MessageDeleteCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -18,7 +23,7 @@ pub struct MessageDeleteCommand {
|
||||||
pub envelopes: EnvelopeIdsArgs,
|
pub envelopes: EnvelopeIdsArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
|
@ -7,16 +7,21 @@ use std::io::{self, BufRead};
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
envelope::arg::ids::EnvelopeIdArg,
|
envelope::arg::ids::EnvelopeIdArg,
|
||||||
folder::arg::name::FolderNameArg,
|
folder::arg::name::FolderNameArg,
|
||||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs},
|
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs},
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
ui::editor,
|
ui::editor,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Forward a new message
|
/// Forward a message.
|
||||||
|
///
|
||||||
|
/// This command allows you to forward the given message using the
|
||||||
|
/// editor defined in your environment variable $EDITOR. When the
|
||||||
|
/// edition process finishes, you can choose between saving or sending
|
||||||
|
/// the final message.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MessageForwardCommand {
|
pub struct MessageForwardCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -25,18 +30,14 @@ pub struct MessageForwardCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub envelope: EnvelopeIdArg,
|
pub envelope: EnvelopeIdArg,
|
||||||
|
|
||||||
/// Forward to all recipients
|
|
||||||
#[arg(long, short = 'A')]
|
|
||||||
pub all: bool,
|
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub headers: HeaderRawArgs,
|
pub headers: HeaderRawArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub body: BodyRawArg,
|
pub body: MessageRawBodyArg,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
|
@ -1,20 +1,30 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use log::info;
|
use log::{debug, info};
|
||||||
use mail_builder::MessageBuilder;
|
use mail_builder::MessageBuilder;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::{backend::Backend, config::TomlConfig, printer::Printer, ui::editor};
|
use crate::{backend::Backend, config::TomlConfig, printer::Printer, ui::editor};
|
||||||
|
|
||||||
/// Parse and edit a message from a mailto URL string
|
/// Parse and edit a message from a mailto URL string.
|
||||||
|
///
|
||||||
|
/// This command allows you to edit a message from the mailto format
|
||||||
|
/// using the editor defined in your environment variable
|
||||||
|
/// $EDITOR. When the edition process finishes, you can choose between
|
||||||
|
/// saving or sending the final message.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MessageMailtoCommand {
|
pub struct MessageMailtoCommand {
|
||||||
/// The mailto url
|
/// The mailto url.
|
||||||
#[arg()]
|
#[arg()]
|
||||||
pub url: Url,
|
pub url: Url,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageMailtoCommand {
|
impl MessageMailtoCommand {
|
||||||
|
pub fn new(url: &str) -> Result<Self> {
|
||||||
|
let url = Url::parse(url)?;
|
||||||
|
Ok(Self { url })
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
|
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
|
||||||
info!("executing message mailto command");
|
info!("executing message mailto command");
|
||||||
|
|
||||||
|
@ -23,17 +33,27 @@ impl MessageMailtoCommand {
|
||||||
let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
|
let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
|
||||||
|
|
||||||
let mut builder = MessageBuilder::new().to(self.url.path());
|
let mut builder = MessageBuilder::new().to(self.url.path());
|
||||||
|
let mut body = String::new();
|
||||||
|
|
||||||
for (key, val) in self.url.query_pairs() {
|
for (key, val) in self.url.query_pairs() {
|
||||||
match key.to_lowercase().as_bytes() {
|
match key.to_lowercase().as_bytes() {
|
||||||
b"cc" => builder = builder.cc(val.to_string()),
|
b"cc" => builder = builder.cc(val.to_string()),
|
||||||
b"bcc" => builder = builder.bcc(val.to_string()),
|
b"bcc" => builder = builder.bcc(val.to_string()),
|
||||||
b"subject" => builder = builder.subject(val),
|
b"subject" => builder = builder.subject(val),
|
||||||
b"body" => builder = builder.text_body(val),
|
b"body" => body += &val,
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match account_config.signature() {
|
||||||
|
Ok(Some(ref signature)) => builder = builder.text_body(body + "\n\n" + signature),
|
||||||
|
Ok(None) => builder = builder.text_body(body),
|
||||||
|
Err(err) => {
|
||||||
|
debug!("cannot add signature to mailto message, skipping it: {err}");
|
||||||
|
debug!("{err:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let tpl = account_config
|
let tpl = account_config
|
||||||
.generate_tpl_interpreter()
|
.generate_tpl_interpreter()
|
||||||
.with_show_only_headers(account_config.email_writing_headers())
|
.with_show_only_headers(account_config.email_writing_headers())
|
||||||
|
|
|
@ -21,47 +21,42 @@ use self::{
|
||||||
write::MessageWriteCommand,
|
write::MessageWriteCommand,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Subcommand to manage messages
|
/// Manage messages.
|
||||||
|
///
|
||||||
|
/// A message is the content of an email. It is composed of headers
|
||||||
|
/// (located at the top of the message) and a body (located at the
|
||||||
|
/// bottom of the message). Both are separated by two new lines. This
|
||||||
|
/// subcommand allows you to manage them.
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
pub enum MessageSubcommand {
|
pub enum MessageSubcommand {
|
||||||
/// Read a message
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
Read(MessageReadCommand),
|
Read(MessageReadCommand),
|
||||||
|
|
||||||
/// Write a new message
|
#[command(alias = "add", alias = "create", alias = "new", alias = "compose")]
|
||||||
#[command(alias = "new", alias = "compose")]
|
|
||||||
Write(MessageWriteCommand),
|
Write(MessageWriteCommand),
|
||||||
|
|
||||||
/// Reply to a message
|
|
||||||
#[command()]
|
#[command()]
|
||||||
Reply(MessageReplyCommand),
|
Reply(MessageReplyCommand),
|
||||||
|
|
||||||
/// Forward a message
|
|
||||||
#[command(alias = "fwd")]
|
#[command(alias = "fwd")]
|
||||||
Forward(MessageForwardCommand),
|
Forward(MessageForwardCommand),
|
||||||
|
|
||||||
/// Parse and edit a message from a mailto URL string
|
|
||||||
#[command()]
|
#[command()]
|
||||||
Mailto(MessageMailtoCommand),
|
Mailto(MessageMailtoCommand),
|
||||||
|
|
||||||
/// Save a message to a folder
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
#[command(alias = "add", alias = "create")]
|
#[command(alias = "add", alias = "create")]
|
||||||
Save(MessageSaveCommand),
|
Save(MessageSaveCommand),
|
||||||
|
|
||||||
/// Send a message
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
Send(MessageSendCommand),
|
Send(MessageSendCommand),
|
||||||
|
|
||||||
/// Copy a message from a source folder to a target folder
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
Copy(MessageCopyCommand),
|
Copy(MessageCopyCommand),
|
||||||
|
|
||||||
/// Move a message from a source folder to a target folder
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
Move(MessageMoveCommand),
|
Move(MessageMoveCommand),
|
||||||
|
|
||||||
/// Delete a message from a folder
|
|
||||||
#[command(arg_required_else_help = true)]
|
#[command(arg_required_else_help = true)]
|
||||||
Delete(MessageDeleteCommand),
|
Delete(MessageDeleteCommand),
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,14 @@ use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
envelope::arg::ids::EnvelopeIdsArgs,
|
envelope::arg::ids::EnvelopeIdsArgs,
|
||||||
folder::arg::name::{SourceFolderNameArg, TargetFolderNameArg},
|
folder::arg::name::{SourceFolderNameArg, TargetFolderNameArg},
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Move a message from a source folder to a target folder
|
/// Move a message from a source folder to a target folder.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MessageMoveCommand {
|
pub struct MessageMoveCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -25,7 +25,7 @@ pub struct MessageMoveCommand {
|
||||||
pub envelopes: EnvelopeIdsArgs,
|
pub envelopes: EnvelopeIdsArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
|
@ -4,12 +4,14 @@ use log::info;
|
||||||
use mml::message::FilterParts;
|
use mml::message::FilterParts;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig, envelope::arg::ids::EnvelopeIdsArgs, folder::arg::name::FolderNameArg,
|
config::TomlConfig, envelope::arg::ids::EnvelopeIdsArgs, folder::arg::name::FolderNameArg,
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Read a message from a folder
|
/// Read a message.
|
||||||
|
///
|
||||||
|
/// This command allows you to read a message.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MessageReadCommand {
|
pub struct MessageReadCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -18,18 +20,18 @@ pub struct MessageReadCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub envelopes: EnvelopeIdsArgs,
|
pub envelopes: EnvelopeIdsArgs,
|
||||||
|
|
||||||
/// Read the raw version of the message
|
/// Read the raw version of the given message.
|
||||||
///
|
///
|
||||||
/// The raw message represents the message as it is on the
|
/// The raw message represents the headers and the body as it is
|
||||||
/// backend, unedited: not decoded nor decrypted. This is useful
|
/// on the backend, unedited: not decoded nor decrypted. This is
|
||||||
/// for debugging faulty messages, but also for
|
/// useful for debugging faulty messages, but also for
|
||||||
/// saving/sending/transfering messages.
|
/// saving/sending/transfering messages.
|
||||||
#[arg(long, short)]
|
#[arg(long, short)]
|
||||||
#[arg(conflicts_with = "no_headers")]
|
#[arg(conflicts_with = "no_headers")]
|
||||||
#[arg(conflicts_with = "headers")]
|
#[arg(conflicts_with = "headers")]
|
||||||
pub raw: bool,
|
pub raw: bool,
|
||||||
|
|
||||||
/// Read only body of text/html parts
|
/// Read only body of text/html parts.
|
||||||
///
|
///
|
||||||
/// This argument is useful when you need to read the HTML version
|
/// This argument is useful when you need to read the HTML version
|
||||||
/// of a message. Combined with --no-headers, you can write it to
|
/// of a message. Combined with --no-headers, you can write it to
|
||||||
|
@ -38,7 +40,7 @@ pub struct MessageReadCommand {
|
||||||
#[arg(conflicts_with = "raw")]
|
#[arg(conflicts_with = "raw")]
|
||||||
pub html: bool,
|
pub html: bool,
|
||||||
|
|
||||||
/// Read only the body of the message
|
/// Read only the body of the message.
|
||||||
///
|
///
|
||||||
/// All headers will be removed from the message.
|
/// All headers will be removed from the message.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
|
@ -47,7 +49,7 @@ pub struct MessageReadCommand {
|
||||||
pub no_headers: bool,
|
pub no_headers: bool,
|
||||||
|
|
||||||
/// List of headers that should be visible at the top of the
|
/// List of headers that should be visible at the top of the
|
||||||
/// message
|
/// message.
|
||||||
///
|
///
|
||||||
/// If a given header is not found in the message, it will not be
|
/// If a given header is not found in the message, it will not be
|
||||||
/// visible. If no header is given, defaults to the one set up in
|
/// visible. If no header is given, defaults to the one set up in
|
||||||
|
@ -58,7 +60,7 @@ pub struct MessageReadCommand {
|
||||||
pub headers: Vec<String>,
|
pub headers: Vec<String>,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
|
@ -8,16 +8,21 @@ use std::io::{self, BufRead};
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
envelope::arg::ids::EnvelopeIdArg,
|
envelope::arg::ids::EnvelopeIdArg,
|
||||||
folder::arg::name::FolderNameArg,
|
folder::arg::name::FolderNameArg,
|
||||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs, reply::MessageReplyAllArg},
|
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs, reply::MessageReplyAllArg},
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
ui::editor,
|
ui::editor,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Reply a new message
|
/// Reply to a message.
|
||||||
|
///
|
||||||
|
/// This command allows you to reply to the given message using the
|
||||||
|
/// editor defined in your environment variable $EDITOR. When the
|
||||||
|
/// edition process finishes, you can choose between saving or sending
|
||||||
|
/// the final message.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MessageReplyCommand {
|
pub struct MessageReplyCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -33,10 +38,10 @@ pub struct MessageReplyCommand {
|
||||||
pub headers: HeaderRawArgs,
|
pub headers: HeaderRawArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub body: BodyRawArg,
|
pub body: MessageRawBodyArg,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
|
@ -5,22 +5,24 @@ use log::info;
|
||||||
use std::io::{self, BufRead};
|
use std::io::{self, BufRead};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
config::TomlConfig, folder::arg::name::FolderNameArg, message::arg::body::MessageRawBodyArg,
|
||||||
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Save a message to a folder
|
/// Save a message to a folder.
|
||||||
|
///
|
||||||
|
/// This command allows you to add a raw message to the given folder.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MessageSaveCommand {
|
pub struct MessageSaveCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub folder: FolderNameArg,
|
pub folder: FolderNameArg,
|
||||||
|
|
||||||
/// The raw message to save
|
#[command(flatten)]
|
||||||
#[arg(value_name = "MESSAGE", raw = true)]
|
pub body: MessageRawBodyArg,
|
||||||
pub raw: String,
|
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
@ -33,7 +35,6 @@ impl MessageSaveCommand {
|
||||||
let folder = &self.folder.name;
|
let folder = &self.folder.name;
|
||||||
let account = self.account.name.as_ref().map(String::as_str);
|
let account = self.account.name.as_ref().map(String::as_str);
|
||||||
let cache = self.cache.disable;
|
let cache = self.cache.disable;
|
||||||
let raw_msg = &self.raw;
|
|
||||||
|
|
||||||
let (toml_account_config, account_config) =
|
let (toml_account_config, account_config) =
|
||||||
config.clone().into_account_configs(account, cache)?;
|
config.clone().into_account_configs(account, cache)?;
|
||||||
|
@ -41,8 +42,8 @@ impl MessageSaveCommand {
|
||||||
|
|
||||||
let is_tty = atty::is(Stream::Stdin);
|
let is_tty = atty::is(Stream::Stdin);
|
||||||
let is_json = printer.is_json();
|
let is_json = printer.is_json();
|
||||||
let raw_email = if is_tty || is_json {
|
let msg = if is_tty || is_json {
|
||||||
raw_msg.replace("\r", "").replace("\n", "\r\n")
|
self.body.raw()
|
||||||
} else {
|
} else {
|
||||||
io::stdin()
|
io::stdin()
|
||||||
.lock()
|
.lock()
|
||||||
|
@ -52,9 +53,7 @@ impl MessageSaveCommand {
|
||||||
.join("\r\n")
|
.join("\r\n")
|
||||||
};
|
};
|
||||||
|
|
||||||
backend
|
backend.add_raw_message(folder, msg.as_bytes()).await?;
|
||||||
.add_raw_message(folder, raw_email.as_bytes())
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
printer.print(format!("Message successfully saved to {folder}!"))
|
printer.print(format!("Message successfully saved to {folder}!"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,19 +6,21 @@ use log::info;
|
||||||
use std::io::{self, BufRead};
|
use std::io::{self, BufRead};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig, printer::Printer,
|
config::TomlConfig, message::arg::body::MessageRawBodyArg, printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Send a message from a folder
|
/// Send a message.
|
||||||
|
///
|
||||||
|
/// This command allows you to send a raw message and to save a copy
|
||||||
|
/// to your send folder.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MessageSendCommand {
|
pub struct MessageSendCommand {
|
||||||
/// The raw message to send
|
#[command(flatten)]
|
||||||
#[arg(value_name = "MESSAGE", raw = true)]
|
pub body: MessageRawBodyArg,
|
||||||
pub raw: String,
|
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
@ -30,7 +32,6 @@ impl MessageSendCommand {
|
||||||
|
|
||||||
let account = self.account.name.as_ref().map(String::as_str);
|
let account = self.account.name.as_ref().map(String::as_str);
|
||||||
let cache = self.cache.disable;
|
let cache = self.cache.disable;
|
||||||
let raw_msg = &self.raw;
|
|
||||||
|
|
||||||
let (toml_account_config, account_config) =
|
let (toml_account_config, account_config) =
|
||||||
config.clone().into_account_configs(account, cache)?;
|
config.clone().into_account_configs(account, cache)?;
|
||||||
|
@ -39,8 +40,8 @@ impl MessageSendCommand {
|
||||||
|
|
||||||
let is_tty = atty::is(Stream::Stdin);
|
let is_tty = atty::is(Stream::Stdin);
|
||||||
let is_json = printer.is_json();
|
let is_json = printer.is_json();
|
||||||
let raw_email = if is_tty || is_json {
|
let msg = if is_tty || is_json {
|
||||||
raw_msg.replace("\r", "").replace("\n", "\r\n")
|
self.body.raw()
|
||||||
} else {
|
} else {
|
||||||
io::stdin()
|
io::stdin()
|
||||||
.lock()
|
.lock()
|
||||||
|
@ -50,11 +51,11 @@ impl MessageSendCommand {
|
||||||
.join("\r\n")
|
.join("\r\n")
|
||||||
};
|
};
|
||||||
|
|
||||||
backend.send_raw_message(raw_email.as_bytes()).await?;
|
backend.send_raw_message(msg.as_bytes()).await?;
|
||||||
|
|
||||||
if account_config.email_sending_save_copy.unwrap_or_default() {
|
if account_config.email_sending_save_copy.unwrap_or_default() {
|
||||||
backend
|
backend
|
||||||
.add_raw_message_with_flag(&folder, raw_email.as_bytes(), Flag::Seen)
|
.add_raw_message_with_flag(&folder, msg.as_bytes(), Flag::Seen)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
printer.print(format!("Message successfully sent and saved to {folder}!"))
|
printer.print(format!("Message successfully sent and saved to {folder}!"))
|
||||||
|
|
|
@ -8,24 +8,29 @@ use std::io::{self, BufRead};
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs},
|
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs},
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
ui::editor,
|
ui::editor,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Write a new message
|
/// Write a new message.
|
||||||
|
///
|
||||||
|
/// This command allows you to write a new message using the editor
|
||||||
|
/// defined in your environment variable $EDITOR. When the edition
|
||||||
|
/// process finishes, you can choose between saving or sending the
|
||||||
|
/// final message.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MessageWriteCommand {
|
pub struct MessageWriteCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub headers: HeaderRawArgs,
|
pub headers: HeaderRawArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub body: BodyRawArg,
|
pub body: MessageRawBodyArg,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
25
src/email/message/template/arg/body.rs
Normal file
25
src/email/message/template/arg/body.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
use clap::Parser;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
/// The raw template body argument parser.
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
pub struct TemplateRawBodyArg {
|
||||||
|
/// Prefill the template with a custom body.
|
||||||
|
#[arg(trailing_var_arg = true)]
|
||||||
|
#[arg(name = "body-raw")]
|
||||||
|
pub raw: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TemplateRawBodyArg {
|
||||||
|
pub fn raw(self) -> String {
|
||||||
|
self.raw.join(" ").replace("\r", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for TemplateRawBodyArg {
|
||||||
|
type Target = Vec<String>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.raw
|
||||||
|
}
|
||||||
|
}
|
1
src/email/message/template/arg/mod.rs
Normal file
1
src/email/message/template/arg/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod body;
|
|
@ -5,15 +5,19 @@ use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
envelope::arg::ids::EnvelopeIdArg,
|
envelope::arg::ids::EnvelopeIdArg,
|
||||||
folder::arg::name::FolderNameArg,
|
folder::arg::name::FolderNameArg,
|
||||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs},
|
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs},
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Generate a forward message template
|
/// Generate a template for forwarding a message.
|
||||||
|
///
|
||||||
|
/// The generated template is prefilled with your email in a From
|
||||||
|
/// header as well as your signature. The forwarded message is also
|
||||||
|
/// prefilled in the body of the template, prefixed by a separator.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct TemplateForwardCommand {
|
pub struct TemplateForwardCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -26,10 +30,10 @@ pub struct TemplateForwardCommand {
|
||||||
pub headers: HeaderRawArgs,
|
pub headers: HeaderRawArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub body: BodyRawArg,
|
pub body: MessageRawBodyArg,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
|
@ -14,28 +14,31 @@ use self::{
|
||||||
send::TemplateSendCommand, write::TemplateWriteCommand,
|
send::TemplateSendCommand, write::TemplateWriteCommand,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Subcommand to manage templates
|
/// Manage templates.
|
||||||
|
///
|
||||||
|
/// A template is an editable version of a message (headers +
|
||||||
|
/// body). It uses a specific language called MML that allows you to
|
||||||
|
/// attach file or encrypt content. This subcommand allows you manage
|
||||||
|
/// them.
|
||||||
|
///
|
||||||
|
/// You can learn more about MML at
|
||||||
|
/// <https://crates.io/crates/mml-lib>.
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
pub enum TemplateSubcommand {
|
pub enum TemplateSubcommand {
|
||||||
/// Write a new template
|
#[command(alias = "create", alias = "new", alias = "compose")]
|
||||||
#[command(alias = "new", alias = "compose")]
|
|
||||||
Write(TemplateWriteCommand),
|
Write(TemplateWriteCommand),
|
||||||
|
|
||||||
/// Reply to a template
|
#[command(arg_required_else_help = true)]
|
||||||
#[command()]
|
|
||||||
Reply(TemplateReplyCommand),
|
Reply(TemplateReplyCommand),
|
||||||
|
|
||||||
/// Generate a template for forwarding an email
|
#[command(arg_required_else_help = true)]
|
||||||
#[command(alias = "fwd")]
|
#[command(alias = "fwd")]
|
||||||
Forward(TemplateForwardCommand),
|
Forward(TemplateForwardCommand),
|
||||||
|
|
||||||
/// Save a template to a folder
|
#[command(alias = "add")]
|
||||||
#[command(arg_required_else_help = true)]
|
|
||||||
#[command(alias = "add", alias = "create")]
|
|
||||||
Save(TemplateSaveCommand),
|
Save(TemplateSaveCommand),
|
||||||
|
|
||||||
/// Send a template
|
#[command()]
|
||||||
#[command(arg_required_else_help = true)]
|
|
||||||
Send(TemplateSendCommand),
|
Send(TemplateSendCommand),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,20 @@ use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
envelope::arg::ids::EnvelopeIdArg,
|
envelope::arg::ids::EnvelopeIdArg,
|
||||||
folder::arg::name::FolderNameArg,
|
folder::arg::name::FolderNameArg,
|
||||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs, reply::MessageReplyAllArg},
|
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs, reply::MessageReplyAllArg},
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Generate a reply message template
|
/// Generate a template for replying to a message.
|
||||||
|
///
|
||||||
|
/// The generated template is prefilled with your email in a From
|
||||||
|
/// header as well as your signature. The replied message is also
|
||||||
|
/// prefilled in the body of the template, with all lines prefixed by
|
||||||
|
/// the symbol greater than ">".
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct TemplateReplyCommand {
|
pub struct TemplateReplyCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
|
@ -29,10 +34,10 @@ pub struct TemplateReplyCommand {
|
||||||
pub headers: HeaderRawArgs,
|
pub headers: HeaderRawArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub body: BodyRawArg,
|
pub body: MessageRawBodyArg,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
|
@ -6,22 +6,27 @@ use mml::MmlCompilerBuilder;
|
||||||
use std::io::{self, BufRead};
|
use std::io::{self, BufRead};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
config::TomlConfig, email::template::arg::body::TemplateRawBodyArg,
|
||||||
|
folder::arg::name::FolderNameArg, printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Save a template to a folder
|
/// Save a template to a folder.
|
||||||
|
///
|
||||||
|
/// This command allows you to save a template to the given
|
||||||
|
/// folder. The template is compiled into a MIME message before being
|
||||||
|
/// saved to the folder. If you want to save a raw message, use the
|
||||||
|
/// message save command instead.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct TemplateSaveCommand {
|
pub struct TemplateSaveCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub folder: FolderNameArg,
|
pub folder: FolderNameArg,
|
||||||
|
|
||||||
/// The raw template to save
|
#[command(flatten)]
|
||||||
#[arg(raw = true, value_delimiter = ' ')]
|
pub body: TemplateRawBodyArg,
|
||||||
pub raw: Vec<String>,
|
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
@ -42,7 +47,7 @@ impl TemplateSaveCommand {
|
||||||
let is_tty = atty::is(Stream::Stdin);
|
let is_tty = atty::is(Stream::Stdin);
|
||||||
let is_json = printer.is_json();
|
let is_json = printer.is_json();
|
||||||
let tpl = if is_tty || is_json {
|
let tpl = if is_tty || is_json {
|
||||||
self.raw.join(" ").replace("\r", "")
|
self.body.raw()
|
||||||
} else {
|
} else {
|
||||||
io::stdin()
|
io::stdin()
|
||||||
.lock()
|
.lock()
|
||||||
|
|
|
@ -7,19 +7,23 @@ use mml::MmlCompilerBuilder;
|
||||||
use std::io::{self, BufRead};
|
use std::io::{self, BufRead};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig, printer::Printer,
|
config::TomlConfig, email::template::arg::body::TemplateRawBodyArg, printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Send a template
|
/// Send a template.
|
||||||
|
///
|
||||||
|
/// This command allows you to send a template and save a copy to the
|
||||||
|
/// sent folder. The template is compiled into a MIME message before
|
||||||
|
/// being sent. If you want to send a raw message, use the message
|
||||||
|
/// send command instead.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct TemplateSendCommand {
|
pub struct TemplateSendCommand {
|
||||||
/// The raw template to save
|
#[command(flatten)]
|
||||||
#[arg(raw = true, value_delimiter = ' ')]
|
pub body: TemplateRawBodyArg,
|
||||||
pub raw: Vec<String>,
|
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
@ -40,7 +44,7 @@ impl TemplateSendCommand {
|
||||||
let is_tty = atty::is(Stream::Stdin);
|
let is_tty = atty::is(Stream::Stdin);
|
||||||
let is_json = printer.is_json();
|
let is_json = printer.is_json();
|
||||||
let tpl = if is_tty || is_json {
|
let tpl = if is_tty || is_json {
|
||||||
self.raw.join(" ").replace("\r", "")
|
self.body.raw()
|
||||||
} else {
|
} else {
|
||||||
io::stdin()
|
io::stdin()
|
||||||
.lock()
|
.lock()
|
||||||
|
|
|
@ -4,24 +4,25 @@ use email::message::Message;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag, cache::arg::disable::CacheDisableFlag, config::TomlConfig,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
email::template::arg::body::TemplateRawBodyArg, message::arg::header::HeaderRawArgs,
|
||||||
config::TomlConfig,
|
|
||||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs},
|
|
||||||
printer::Printer,
|
printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Write a new template
|
/// Generate a template for writing a new message from scratch.
|
||||||
|
///
|
||||||
|
/// The generated template is prefilled with your email in a From
|
||||||
|
/// header as well as your signature.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct TemplateWriteCommand {
|
pub struct TemplateWriteCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub headers: HeaderRawArgs,
|
pub headers: HeaderRawArgs,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub body: BodyRawArg,
|
pub body: TemplateRawBodyArg,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
pub mod arg;
|
||||||
pub mod command;
|
pub mod command;
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use email::account::config::DEFAULT_INBOX_FOLDER;
|
use email::account::config::DEFAULT_INBOX_FOLDER;
|
||||||
|
|
||||||
/// The folder name argument parser
|
/// The folder name argument parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct FolderNameArg {
|
pub struct FolderNameArg {
|
||||||
/// The name of the folder
|
/// The name of the folder.
|
||||||
#[arg(name = "folder-name", value_name = "FOLDER")]
|
#[arg(name = "folder_name", value_name = "FOLDER")]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The optional folder name argument parser
|
/// The optional folder name argument parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct FolderNameOptionalArg {
|
pub struct FolderNameOptionalArg {
|
||||||
/// The name of the folder
|
/// The name of the folder.
|
||||||
#[arg(name = "folder-name", value_name = "FOLDER", default_value = DEFAULT_INBOX_FOLDER)]
|
#[arg(name = "folder_name", value_name = "FOLDER", default_value = DEFAULT_INBOX_FOLDER)]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The source folder name argument parser
|
/// The source folder name argument parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct SourceFolderNameArg {
|
pub struct SourceFolderNameArg {
|
||||||
/// The name of the source folder
|
/// The name of the source folder.
|
||||||
#[arg(name = "from-folder-name", value_name = "FROM")]
|
#[arg(name = "from-folder-name", value_name = "FROM")]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The target folder name argument parser
|
/// The target folder name argument parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct TargetFolderNameArg {
|
pub struct TargetFolderNameArg {
|
||||||
/// The name of the target folder
|
/// The name of the target folder.
|
||||||
#[arg(name = "to-folder-name", value_name = "TO")]
|
#[arg(name = "to-folder-name", value_name = "TO")]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,24 @@ use clap::Parser;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Create a new folder
|
/// Create a new folder.
|
||||||
|
///
|
||||||
|
/// This command allows you to create a new folder using the given
|
||||||
|
/// name.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct FolderCreateCommand {
|
pub struct FolderCreateCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub folder: FolderNameArg,
|
pub folder: FolderNameArg,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub account: AccountNameFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FolderCreateCommand {
|
impl FolderCreateCommand {
|
||||||
|
|
|
@ -5,24 +5,24 @@ use log::info;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Delete a folder
|
/// Delete a folder.
|
||||||
///
|
///
|
||||||
/// All emails from a given folder are definitely deleted. The folder
|
/// All emails from the given folder are definitely deleted. The
|
||||||
/// is also deleted after execution of the command.
|
/// folder is also deleted after execution of the command.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct FolderDeleteCommand {
|
pub struct FolderDeleteCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub folder: FolderNameArg,
|
pub folder: FolderNameArg,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub account: AccountNameFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FolderDeleteCommand {
|
impl FolderDeleteCommand {
|
||||||
|
|
|
@ -3,14 +3,14 @@ use clap::Parser;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Expunge a folder
|
/// Expunge a folder.
|
||||||
///
|
///
|
||||||
/// The concept of expunging is similar to the IMAP one: it definitely
|
/// The concept of expunging is similar to the IMAP one: it definitely
|
||||||
/// deletes emails from a given folder that contain the "deleted"
|
/// deletes emails from the given folder that contain the "deleted"
|
||||||
/// flag.
|
/// flag.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct FolderExpungeCommand {
|
pub struct FolderExpungeCommand {
|
||||||
|
@ -18,10 +18,10 @@ pub struct FolderExpungeCommand {
|
||||||
pub folder: FolderNameArg,
|
pub folder: FolderNameArg,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub account: AccountNameFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FolderExpungeCommand {
|
impl FolderExpungeCommand {
|
||||||
|
|
|
@ -5,24 +5,26 @@ use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
cache::arg::disable::DisableCacheFlag,
|
cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
folder::Folders,
|
folder::Folders,
|
||||||
printer::{PrintTableOpts, Printer},
|
printer::{PrintTableOpts, Printer},
|
||||||
ui::arg::max_width::MaxTableWidthFlag,
|
ui::arg::max_width::TableMaxWidthFlag,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// List all folders
|
/// List all folders.
|
||||||
|
///
|
||||||
|
/// This command allows you to list all exsting folders.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct FolderListCommand {
|
pub struct FolderListCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub table: MaxTableWidthFlag,
|
pub table: TableMaxWidthFlag,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
|
||||||
pub cache: DisableCacheFlag,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FolderListCommand {
|
impl FolderListCommand {
|
||||||
|
|
|
@ -14,26 +14,24 @@ use self::{
|
||||||
list::FolderListCommand, purge::FolderPurgeCommand,
|
list::FolderListCommand, purge::FolderPurgeCommand,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Subcommand to manage accounts
|
/// Manage folders.
|
||||||
|
///
|
||||||
|
/// A folder (AKA mailbox, or directory) contains envelopes and
|
||||||
|
/// messages. This subcommand allows you to manage them.
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
pub enum FolderSubcommand {
|
pub enum FolderSubcommand {
|
||||||
/// Create a new folder
|
#[command(alias = "add", alias = "new")]
|
||||||
#[command(alias = "add")]
|
|
||||||
Create(FolderCreateCommand),
|
Create(FolderCreateCommand),
|
||||||
|
|
||||||
/// List all folders
|
|
||||||
#[command(alias = "lst")]
|
#[command(alias = "lst")]
|
||||||
List(FolderListCommand),
|
List(FolderListCommand),
|
||||||
|
|
||||||
/// Expunge a folder
|
|
||||||
#[command()]
|
#[command()]
|
||||||
Expunge(FolderExpungeCommand),
|
Expunge(FolderExpungeCommand),
|
||||||
|
|
||||||
/// Purge a folder
|
|
||||||
#[command()]
|
#[command()]
|
||||||
Purge(FolderPurgeCommand),
|
Purge(FolderPurgeCommand),
|
||||||
|
|
||||||
/// Delete a folder
|
|
||||||
#[command(alias = "remove", alias = "rm")]
|
#[command(alias = "remove", alias = "rm")]
|
||||||
Delete(FolderDeleteCommand),
|
Delete(FolderDeleteCommand),
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,24 +5,24 @@ use log::info;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||||
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Purge a folder
|
/// Purge a folder.
|
||||||
///
|
///
|
||||||
/// All emails from a given folder are definitely deleted. The purged
|
/// All emails from the given folder are definitely deleted. The
|
||||||
/// folder will remain empty after executing of the command.
|
/// purged folder will remain empty after execution of the command.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct FolderPurgeCommand {
|
pub struct FolderPurgeCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub folder: FolderNameArg,
|
pub folder: FolderNameArg,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub cache: CacheDisableFlag,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub cache: DisableCacheFlag,
|
pub account: AccountNameFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FolderPurgeCommand {
|
impl FolderPurgeCommand {
|
||||||
|
|
25
src/main.rs
25
src/main.rs
|
@ -1,7 +1,10 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use env_logger::{Builder as LoggerBuilder, Env, DEFAULT_FILTER_ENV};
|
use env_logger::{Builder as LoggerBuilder, Env, DEFAULT_FILTER_ENV};
|
||||||
use himalaya::{cli::Cli, config::TomlConfig, printer::StdoutPrinter};
|
use himalaya::{
|
||||||
|
cli::Cli, config::TomlConfig, message::command::mailto::MessageMailtoCommand,
|
||||||
|
printer::StdoutPrinter,
|
||||||
|
};
|
||||||
use log::{debug, warn};
|
use log::{debug, warn};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
@ -9,7 +12,7 @@ use std::env;
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
if let Err((_, err)) = coredump::register_panic_handler() {
|
if let Err((_, err)) = coredump::register_panic_handler() {
|
||||||
warn!("cannot register custom panic handler: {err}");
|
warn!("cannot register coredump panic handler: {err}");
|
||||||
debug!("{err:?}");
|
debug!("{err:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,15 +21,15 @@ async fn main() -> Result<()> {
|
||||||
.format_timestamp(None)
|
.format_timestamp(None)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
let raw_args: Vec<String> = env::args().collect();
|
// if the first argument starts by "mailto:", execute straight the
|
||||||
if raw_args.len() > 1 && raw_args[1].starts_with("mailto:") {
|
// mailto message command
|
||||||
// TODO
|
if let Some(ref url) = env::args().nth(1).filter(|arg| arg.starts_with("mailto:")) {
|
||||||
// let cmd = MessageMailtoCommand::command()
|
let mut printer = StdoutPrinter::default();
|
||||||
// .no_binary_name(true)
|
let config = TomlConfig::from_default_paths().await?;
|
||||||
// .try_get_matches_from([&raw_args[1]]);
|
|
||||||
// match cmd {
|
return MessageMailtoCommand::new(url)?
|
||||||
// Ok(m) => m.exec
|
.execute(&mut printer, &config)
|
||||||
// }
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
|
@ -7,10 +7,15 @@ use std::{fs, path::PathBuf};
|
||||||
|
|
||||||
use crate::{cli::Cli, printer::Printer};
|
use crate::{cli::Cli, printer::Printer};
|
||||||
|
|
||||||
/// Generate manual pages to a directory
|
/// Generate manual pages to a directory.
|
||||||
|
///
|
||||||
|
/// This command allows you to generate manual pages (following the
|
||||||
|
/// man page format) to the given directory. If the directory does not
|
||||||
|
/// exist, it will be created. Any existing man pages will be
|
||||||
|
/// overriden.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct ManualGenerateCommand {
|
pub struct ManualGenerateCommand {
|
||||||
/// Directory where man files should be generated in
|
/// Directory where man files should be generated in.
|
||||||
#[arg(value_parser = dir_parser)]
|
#[arg(value_parser = dir_parser)]
|
||||||
pub dir: PathBuf,
|
pub dir: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
/// The table max width argument parser
|
/// The table max width argument parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct MaxTableWidthFlag {
|
pub struct TableMaxWidthFlag {
|
||||||
/// The maximum width the table should not exceed
|
/// The maximum width the table should not exceed.
|
||||||
#[arg(long, short = 'w', value_name = "PIXELS")]
|
///
|
||||||
|
/// This argument will force the table not to exceed the given
|
||||||
|
/// width in pixels. Columns may shrink with ellipsis in order to
|
||||||
|
/// fit the width.
|
||||||
|
#[arg(long, short = 'w', name = "table_max_width", value_name = "PIXELS")]
|
||||||
pub max_width: Option<usize>,
|
pub max_width: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue