mirror of
https://github.com/soywod/himalaya.git
synced 2024-07-05 17:15:12 +00:00
clean doc
This commit is contained in:
parent
fff11fbe20
commit
ef3214f36f
|
@ -1,26 +1,24 @@
|
|||
use clap::Parser;
|
||||
|
||||
/// The account name argument parser
|
||||
/// The account name argument parser.
|
||||
#[derive(Debug, Parser)]
|
||||
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
|
||||
/// of your TOML configuration file.
|
||||
#[arg(value_name = "ACCOUNT")]
|
||||
/// An account name corresponds to an entry in the table at the
|
||||
/// root level of your TOML configuration file.
|
||||
#[arg(name = "account_name", value_name = "ACCOUNT")]
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// The account name flag parser
|
||||
/// The account name flag parser.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct AccountNameFlag {
|
||||
/// Override the default account
|
||||
#[arg(
|
||||
long = "account",
|
||||
short = 'a',
|
||||
name = "account-name",
|
||||
value_name = "NAME",
|
||||
global = true
|
||||
)]
|
||||
/// Override the default account.
|
||||
///
|
||||
/// An account name corresponds to an entry in the table at the
|
||||
/// root level of your TOML configuration file.
|
||||
#[arg(long = "account", short = 'a', global = true)]
|
||||
#[arg(name = "account_name", value_name = "NAME")]
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
|
|
@ -15,26 +15,32 @@ use crate::{
|
|||
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)]
|
||||
pub struct AccountConfigureCommand {
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameArg,
|
||||
|
||||
/// Force the account to reconfigure, even if it has already been
|
||||
/// configured
|
||||
/// Reset keyring passwords.
|
||||
///
|
||||
/// This argument will force passwords to be prompted again, then
|
||||
/// saved to your global keyring.
|
||||
#[arg(long, short)]
|
||||
pub force: bool,
|
||||
pub reset: bool,
|
||||
}
|
||||
|
||||
impl AccountConfigureCommand {
|
||||
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
|
||||
info!("executing account configure command");
|
||||
|
||||
let (_, account_config) =
|
||||
config.into_toml_account_config(Some(self.account.name.as_str()))?;
|
||||
let account = &self.account.name;
|
||||
let (_, account_config) = config.into_toml_account_config(Some(account))?;
|
||||
|
||||
if self.force {
|
||||
if self.reset {
|
||||
#[cfg(feature = "imap")]
|
||||
if let Some(ref config) = account_config.imap {
|
||||
let reset = match &config.auth {
|
||||
|
@ -102,11 +108,8 @@ impl AccountConfigureCommand {
|
|||
}
|
||||
|
||||
printer.print(format!(
|
||||
"Account {} successfully {}configured!",
|
||||
self.account.name,
|
||||
if self.force { "re" } else { "" }
|
||||
))?;
|
||||
|
||||
Ok(())
|
||||
"Account {account} successfully {}configured!",
|
||||
if self.reset { "re" } else { "" }
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,14 +6,17 @@ use crate::{
|
|||
account::Accounts,
|
||||
config::TomlConfig,
|
||||
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)]
|
||||
pub struct AccountListCommand {
|
||||
#[command(flatten)]
|
||||
pub table: MaxTableWidthFlag,
|
||||
pub table: TableMaxWidthFlag,
|
||||
}
|
||||
|
||||
impl AccountListCommand {
|
||||
|
@ -31,9 +34,7 @@ impl AccountListCommand {
|
|||
.unwrap_or(&Default::default()),
|
||||
max_width: self.table.max_width,
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,18 +11,19 @@ use self::{
|
|||
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)]
|
||||
pub enum AccountSubcommand {
|
||||
/// Configure an account
|
||||
#[command(alias = "cfg")]
|
||||
Configure(AccountConfigureCommand),
|
||||
|
||||
/// List all accounts
|
||||
#[command(alias = "lst")]
|
||||
List(AccountListCommand),
|
||||
|
||||
/// Synchronize an account locally
|
||||
#[command()]
|
||||
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()
|
||||
});
|
||||
|
||||
/// 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)]
|
||||
pub struct AccountSyncCommand {
|
||||
#[command(flatten)]
|
||||
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
|
||||
/// changes the synchronization plan to do.
|
||||
#[arg(long, short)]
|
||||
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>,
|
||||
|
||||
#[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>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
short = 'A',
|
||||
conflicts_with = "include_folder",
|
||||
conflicts_with = "exclude_folder"
|
||||
)]
|
||||
/// Synchronize all exsting folders.
|
||||
#[arg(long, short = 'A')]
|
||||
#[arg(conflicts_with = "include_folder", conflicts_with = "exclude_folder")]
|
||||
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;
|
||||
|
||||
/// The disable cache flag parser
|
||||
/// The disable cache flag parser.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct DisableCacheFlag {
|
||||
/// Disable any sort of cache
|
||||
pub struct CacheDisableFlag {
|
||||
/// Disable any sort of cache.
|
||||
///
|
||||
/// The action depends on commands it apply on. For example, when
|
||||
/// listing envelopes using the IMAP backend, this flag will
|
||||
/// ensure that envelopes are fetched from the IMAP server and not
|
||||
/// from the synchronized local Maildir.
|
||||
#[arg(
|
||||
long = "disable-cache",
|
||||
alias = "no-cache",
|
||||
name = "disable-cache",
|
||||
global = true
|
||||
)]
|
||||
/// ensure that envelopes are fetched from the IMAP server rather
|
||||
/// than the synchronized local Maildir.
|
||||
#[arg(long = "disable-cache", alias = "no-cache", global = true)]
|
||||
#[arg(name = "cache_disable")]
|
||||
pub disable: bool,
|
||||
}
|
||||
|
|
28
src/cli.rs
28
src/cli.rs
|
@ -19,14 +19,8 @@ use crate::{
|
|||
};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(
|
||||
name = "himalaya",
|
||||
author,
|
||||
version,
|
||||
about,
|
||||
propagate_version = true,
|
||||
infer_subcommands = true
|
||||
)]
|
||||
#[command(name = "himalaya", author, version, about)]
|
||||
#[command(propagate_version = true, infer_subcommands = true)]
|
||||
pub struct Cli {
|
||||
#[command(subcommand)]
|
||||
pub command: HimalayaCommand,
|
||||
|
@ -83,46 +77,38 @@ pub struct Cli {
|
|||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum HimalayaCommand {
|
||||
/// Manage accounts
|
||||
#[command(subcommand)]
|
||||
#[command(alias = "accounts")]
|
||||
Account(AccountSubcommand),
|
||||
|
||||
/// Manage folders
|
||||
#[command(subcommand)]
|
||||
#[command(alias = "folders")]
|
||||
Folder(FolderSubcommand),
|
||||
|
||||
/// Manage envelopes
|
||||
#[command(subcommand)]
|
||||
#[command(alias = "envelopes")]
|
||||
Envelope(EnvelopeSubcommand),
|
||||
|
||||
/// Manage flags
|
||||
#[command(subcommand)]
|
||||
#[command(alias = "flags")]
|
||||
Flag(FlagSubcommand),
|
||||
|
||||
/// Manage messages
|
||||
#[command(subcommand)]
|
||||
#[command(alias = "messages", alias = "msgs", alias = "msg")]
|
||||
Message(MessageSubcommand),
|
||||
|
||||
/// Manage templates
|
||||
#[command(subcommand)]
|
||||
#[command(alias = "attachments")]
|
||||
Attachment(AttachmentSubcommand),
|
||||
|
||||
#[command(subcommand)]
|
||||
#[command(alias = "templates", alias = "tpls", alias = "tpl")]
|
||||
Template(TemplateSubcommand),
|
||||
|
||||
/// Manage attachments
|
||||
#[command(subcommand)]
|
||||
Attachment(AttachmentSubcommand),
|
||||
|
||||
/// Generate manual pages to a directory
|
||||
#[command(arg_required_else_help = true)]
|
||||
#[command(alias = "manuals", alias = "mans")]
|
||||
Manual(ManualGenerateCommand),
|
||||
|
||||
/// Print completion script for a shell to stdout
|
||||
#[command(arg_required_else_help = true)]
|
||||
#[command(alias = "completions")]
|
||||
Completion(CompletionGenerateCommand),
|
||||
|
@ -136,8 +122,8 @@ impl HimalayaCommand {
|
|||
Self::Envelope(cmd) => cmd.execute(printer, config).await,
|
||||
Self::Flag(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::Template(cmd) => cmd.execute(printer, config).await,
|
||||
Self::Manual(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};
|
||||
|
||||
/// 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)]
|
||||
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))]
|
||||
pub shell: Shell,
|
||||
}
|
||||
|
|
|
@ -121,10 +121,7 @@ impl TomlConfig {
|
|||
match path.map(Into::into) {
|
||||
Some(ref path) if path.exists() => Self::from_path(path),
|
||||
Some(path) => Self::from_wizard(path).await,
|
||||
None => match Self::first_valid_default_path() {
|
||||
Some(path) => Self::from_path(&path),
|
||||
None => Self::from_wizard(Self::default_path()?).await,
|
||||
},
|
||||
None => Self::from_default_paths().await,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
use clap::Parser;
|
||||
|
||||
/// The envelope id argument parser
|
||||
/// The envelope id argument parser.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct EnvelopeIdArg {
|
||||
/// The envelope id
|
||||
/// The envelope id.
|
||||
#[arg(value_name = "ID", required = true)]
|
||||
pub id: usize,
|
||||
}
|
||||
|
||||
/// The envelopes ids arguments parser
|
||||
/// The envelopes ids arguments parser.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct EnvelopeIdsArgs {
|
||||
/// The list of envelopes ids
|
||||
/// The list of envelopes ids.
|
||||
#[arg(value_name = "ID", required = true)]
|
||||
pub ids: Vec<usize>,
|
||||
}
|
||||
|
|
|
@ -5,35 +5,43 @@ use log::info;
|
|||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
folder::arg::name::FolderNameOptionalArg,
|
||||
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)]
|
||||
pub struct EnvelopeListCommand {
|
||||
#[command(flatten)]
|
||||
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")]
|
||||
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")]
|
||||
pub page_size: Option<usize>,
|
||||
|
||||
#[command(flatten)]
|
||||
pub table: MaxTableWidthFlag,
|
||||
pub table: TableMaxWidthFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
}
|
||||
|
||||
impl EnvelopeListCommand {
|
||||
|
|
|
@ -7,10 +7,14 @@ use crate::{config::TomlConfig, printer::Printer};
|
|||
|
||||
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)]
|
||||
pub enum EnvelopeSubcommand {
|
||||
/// List all envelopes from a folder
|
||||
#[command(alias = "lst")]
|
||||
List(EnvelopeListCommand),
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@ use clap::Parser;
|
|||
use email::flag::{Flag, Flags};
|
||||
use log::debug;
|
||||
|
||||
/// The ids and/or flags arguments parser
|
||||
/// The ids and/or flags arguments parser.
|
||||
#[derive(Debug, Parser)]
|
||||
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
|
||||
/// an id, otherwise it is considered as a flag.
|
||||
|
|
|
@ -5,14 +5,17 @@ use log::info;
|
|||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
|
||||
folder::arg::name::FolderNameArg,
|
||||
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)]
|
||||
pub struct FlagAddCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -22,10 +25,10 @@ pub struct FlagAddCommand {
|
|||
pub args: IdsAndFlagsArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub account: AccountNameFlag,
|
||||
}
|
||||
|
||||
impl FlagAddCommand {
|
||||
|
|
|
@ -9,20 +9,22 @@ use crate::{config::TomlConfig, printer::Printer};
|
|||
|
||||
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)]
|
||||
pub enum FlagSubcommand {
|
||||
/// Add flag(s) to an envelope
|
||||
#[command(arg_required_else_help = true)]
|
||||
#[command(alias = "create")]
|
||||
Add(FlagAddCommand),
|
||||
|
||||
/// Replace flag(s) of an envelope
|
||||
#[command(arg_required_else_help = true)]
|
||||
#[command(aliases = ["update", "change", "replace"])]
|
||||
Set(FlagSetCommand),
|
||||
|
||||
/// Remove flag(s) from an envelope
|
||||
#[command(arg_required_else_help = true)]
|
||||
#[command(aliases = ["rm", "delete", "del"])]
|
||||
Remove(FlagRemoveCommand),
|
||||
|
|
|
@ -5,14 +5,17 @@ use log::info;
|
|||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
|
||||
folder::arg::name::FolderNameArg,
|
||||
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)]
|
||||
pub struct FlagRemoveCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -22,10 +25,10 @@ pub struct FlagRemoveCommand {
|
|||
pub args: IdsAndFlagsArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub account: AccountNameFlag,
|
||||
}
|
||||
|
||||
impl FlagRemoveCommand {
|
||||
|
|
|
@ -5,14 +5,17 @@ use log::info;
|
|||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
|
||||
folder::arg::name::FolderNameArg,
|
||||
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)]
|
||||
pub struct FlagSetCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -22,10 +25,10 @@ pub struct FlagSetCommand {
|
|||
pub args: IdsAndFlagsArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub account: AccountNameFlag,
|
||||
}
|
||||
|
||||
impl FlagSetCommand {
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
use clap::Parser;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// The raw message body argument parser
|
||||
/// The raw message body argument parser.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct BodyRawArg {
|
||||
/// Prefill the template with a custom body
|
||||
#[arg(raw = true, required = false)]
|
||||
#[arg(name = "body-raw", value_delimiter = ' ')]
|
||||
pub struct MessageRawBodyArg {
|
||||
/// Prefill the template with a custom body.
|
||||
#[arg(trailing_var_arg = true)]
|
||||
#[arg(name = "body-raw")]
|
||||
pub raw: Vec<String>,
|
||||
}
|
||||
|
||||
impl BodyRawArg {
|
||||
impl MessageRawBodyArg {
|
||||
pub fn raw(self) -> String {
|
||||
self.raw.join(" ").replace("\r", "").replace("\n", "\r\n")
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for BodyRawArg {
|
||||
impl Deref for MessageRawBodyArg {
|
||||
type Target = Vec<String>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use clap::Parser;
|
||||
|
||||
/// The envelope id argument parser
|
||||
/// The envelope id argument parser.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct HeaderRawArgs {
|
||||
/// Prefill the template with custom headers
|
||||
/// Prefill the template with custom headers.
|
||||
///
|
||||
/// A raw header should follow the pattern KEY:VAL.
|
||||
#[arg(long = "header", short = 'H', required = false)]
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use clap::Parser;
|
||||
|
||||
/// The reply to all argument parser
|
||||
/// The reply to all argument parser.
|
||||
#[derive(Debug, Parser)]
|
||||
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')]
|
||||
pub all: bool,
|
||||
}
|
||||
|
|
|
@ -5,12 +5,15 @@ use std::fs;
|
|||
use uuid::Uuid;
|
||||
|
||||
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,
|
||||
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)]
|
||||
pub struct AttachmentDownloadCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -20,7 +23,7 @@ pub struct AttachmentDownloadCommand {
|
|||
pub envelopes: EnvelopeIdsArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
|
|
@ -7,10 +7,13 @@ use crate::{config::TomlConfig, printer::Printer};
|
|||
|
||||
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)]
|
||||
pub enum AttachmentSubcommand {
|
||||
/// Download all attachments of one or more messages
|
||||
#[command(arg_required_else_help = true)]
|
||||
Download(AttachmentDownloadCommand),
|
||||
}
|
||||
|
|
|
@ -5,14 +5,14 @@ use log::info;
|
|||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
envelope::arg::ids::EnvelopeIdsArgs,
|
||||
folder::arg::name::{SourceFolderNameArg, TargetFolderNameArg},
|
||||
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)]
|
||||
pub struct MessageCopyCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -25,7 +25,7 @@ pub struct MessageCopyCommand {
|
|||
pub envelopes: EnvelopeIdsArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
|
|
@ -3,12 +3,17 @@ use clap::Parser;
|
|||
use log::info;
|
||||
|
||||
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,
|
||||
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)]
|
||||
pub struct MessageDeleteCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -18,7 +23,7 @@ pub struct MessageDeleteCommand {
|
|||
pub envelopes: EnvelopeIdsArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
|
|
@ -7,16 +7,21 @@ use std::io::{self, BufRead};
|
|||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
envelope::arg::ids::EnvelopeIdArg,
|
||||
folder::arg::name::FolderNameArg,
|
||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs},
|
||||
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs},
|
||||
printer::Printer,
|
||||
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)]
|
||||
pub struct MessageForwardCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -25,18 +30,14 @@ pub struct MessageForwardCommand {
|
|||
#[command(flatten)]
|
||||
pub envelope: EnvelopeIdArg,
|
||||
|
||||
/// Forward to all recipients
|
||||
#[arg(long, short = 'A')]
|
||||
pub all: bool,
|
||||
|
||||
#[command(flatten)]
|
||||
pub headers: HeaderRawArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub body: BodyRawArg,
|
||||
pub body: MessageRawBodyArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
|
|
@ -1,20 +1,30 @@
|
|||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use log::{debug, info};
|
||||
use mail_builder::MessageBuilder;
|
||||
use url::Url;
|
||||
|
||||
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)]
|
||||
pub struct MessageMailtoCommand {
|
||||
/// The mailto url
|
||||
/// The mailto url.
|
||||
#[arg()]
|
||||
pub url: Url,
|
||||
}
|
||||
|
||||
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<()> {
|
||||
info!("executing message mailto command");
|
||||
|
||||
|
@ -23,17 +33,27 @@ impl MessageMailtoCommand {
|
|||
let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
|
||||
|
||||
let mut builder = MessageBuilder::new().to(self.url.path());
|
||||
let mut body = String::new();
|
||||
|
||||
for (key, val) in self.url.query_pairs() {
|
||||
match key.to_lowercase().as_bytes() {
|
||||
b"cc" => builder = builder.cc(val.to_string()),
|
||||
b"bcc" => builder = builder.bcc(val.to_string()),
|
||||
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
|
||||
.generate_tpl_interpreter()
|
||||
.with_show_only_headers(account_config.email_writing_headers())
|
||||
|
|
|
@ -21,47 +21,42 @@ use self::{
|
|||
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)]
|
||||
pub enum MessageSubcommand {
|
||||
/// Read a message
|
||||
#[command(arg_required_else_help = true)]
|
||||
Read(MessageReadCommand),
|
||||
|
||||
/// Write a new message
|
||||
#[command(alias = "new", alias = "compose")]
|
||||
#[command(alias = "add", alias = "create", alias = "new", alias = "compose")]
|
||||
Write(MessageWriteCommand),
|
||||
|
||||
/// Reply to a message
|
||||
#[command()]
|
||||
Reply(MessageReplyCommand),
|
||||
|
||||
/// Forward a message
|
||||
#[command(alias = "fwd")]
|
||||
Forward(MessageForwardCommand),
|
||||
|
||||
/// Parse and edit a message from a mailto URL string
|
||||
#[command()]
|
||||
Mailto(MessageMailtoCommand),
|
||||
|
||||
/// Save a message to a folder
|
||||
#[command(arg_required_else_help = true)]
|
||||
#[command(alias = "add", alias = "create")]
|
||||
Save(MessageSaveCommand),
|
||||
|
||||
/// Send a message
|
||||
#[command(arg_required_else_help = true)]
|
||||
Send(MessageSendCommand),
|
||||
|
||||
/// Copy a message from a source folder to a target folder
|
||||
#[command(arg_required_else_help = true)]
|
||||
Copy(MessageCopyCommand),
|
||||
|
||||
/// Move a message from a source folder to a target folder
|
||||
#[command(arg_required_else_help = true)]
|
||||
Move(MessageMoveCommand),
|
||||
|
||||
/// Delete a message from a folder
|
||||
#[command(arg_required_else_help = true)]
|
||||
Delete(MessageDeleteCommand),
|
||||
}
|
||||
|
|
|
@ -5,14 +5,14 @@ use log::info;
|
|||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
envelope::arg::ids::EnvelopeIdsArgs,
|
||||
folder::arg::name::{SourceFolderNameArg, TargetFolderNameArg},
|
||||
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)]
|
||||
pub struct MessageMoveCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -25,7 +25,7 @@ pub struct MessageMoveCommand {
|
|||
pub envelopes: EnvelopeIdsArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
|
|
@ -4,12 +4,14 @@ use log::info;
|
|||
use mml::message::FilterParts;
|
||||
|
||||
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,
|
||||
printer::Printer,
|
||||
};
|
||||
|
||||
/// Read a message from a folder
|
||||
/// Read a message.
|
||||
///
|
||||
/// This command allows you to read a message.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct MessageReadCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -18,18 +20,18 @@ pub struct MessageReadCommand {
|
|||
#[command(flatten)]
|
||||
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
|
||||
/// backend, unedited: not decoded nor decrypted. This is useful
|
||||
/// for debugging faulty messages, but also for
|
||||
/// The raw message represents the headers and the body as it is
|
||||
/// on the backend, unedited: not decoded nor decrypted. This is
|
||||
/// useful for debugging faulty messages, but also for
|
||||
/// saving/sending/transfering messages.
|
||||
#[arg(long, short)]
|
||||
#[arg(conflicts_with = "no_headers")]
|
||||
#[arg(conflicts_with = "headers")]
|
||||
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
|
||||
/// of a message. Combined with --no-headers, you can write it to
|
||||
|
@ -38,7 +40,7 @@ pub struct MessageReadCommand {
|
|||
#[arg(conflicts_with = "raw")]
|
||||
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.
|
||||
#[arg(long)]
|
||||
|
@ -47,7 +49,7 @@ pub struct MessageReadCommand {
|
|||
pub no_headers: bool,
|
||||
|
||||
/// 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
|
||||
/// visible. If no header is given, defaults to the one set up in
|
||||
|
@ -58,7 +60,7 @@ pub struct MessageReadCommand {
|
|||
pub headers: Vec<String>,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
|
|
@ -8,16 +8,21 @@ use std::io::{self, BufRead};
|
|||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
envelope::arg::ids::EnvelopeIdArg,
|
||||
folder::arg::name::FolderNameArg,
|
||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs, reply::MessageReplyAllArg},
|
||||
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs, reply::MessageReplyAllArg},
|
||||
printer::Printer,
|
||||
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)]
|
||||
pub struct MessageReplyCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -33,10 +38,10 @@ pub struct MessageReplyCommand {
|
|||
pub headers: HeaderRawArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub body: BodyRawArg,
|
||||
pub body: MessageRawBodyArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
|
|
@ -5,22 +5,24 @@ use log::info;
|
|||
use std::io::{self, BufRead};
|
||||
|
||||
use crate::{
|
||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
||||
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||
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)]
|
||||
pub struct MessageSaveCommand {
|
||||
#[command(flatten)]
|
||||
pub folder: FolderNameArg,
|
||||
|
||||
/// The raw message to save
|
||||
#[arg(value_name = "MESSAGE", raw = true)]
|
||||
pub raw: String,
|
||||
#[command(flatten)]
|
||||
pub body: MessageRawBodyArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
@ -33,7 +35,6 @@ impl MessageSaveCommand {
|
|||
let folder = &self.folder.name;
|
||||
let account = self.account.name.as_ref().map(String::as_str);
|
||||
let cache = self.cache.disable;
|
||||
let raw_msg = &self.raw;
|
||||
|
||||
let (toml_account_config, account_config) =
|
||||
config.clone().into_account_configs(account, cache)?;
|
||||
|
@ -41,8 +42,8 @@ impl MessageSaveCommand {
|
|||
|
||||
let is_tty = atty::is(Stream::Stdin);
|
||||
let is_json = printer.is_json();
|
||||
let raw_email = if is_tty || is_json {
|
||||
raw_msg.replace("\r", "").replace("\n", "\r\n")
|
||||
let msg = if is_tty || is_json {
|
||||
self.body.raw()
|
||||
} else {
|
||||
io::stdin()
|
||||
.lock()
|
||||
|
@ -52,9 +53,7 @@ impl MessageSaveCommand {
|
|||
.join("\r\n")
|
||||
};
|
||||
|
||||
backend
|
||||
.add_raw_message(folder, raw_email.as_bytes())
|
||||
.await?;
|
||||
backend.add_raw_message(folder, msg.as_bytes()).await?;
|
||||
|
||||
printer.print(format!("Message successfully saved to {folder}!"))
|
||||
}
|
||||
|
|
|
@ -6,19 +6,21 @@ use log::info;
|
|||
use std::io::{self, BufRead};
|
||||
|
||||
use crate::{
|
||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
||||
config::TomlConfig, printer::Printer,
|
||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||
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)]
|
||||
pub struct MessageSendCommand {
|
||||
/// The raw message to send
|
||||
#[arg(value_name = "MESSAGE", raw = true)]
|
||||
pub raw: String,
|
||||
#[command(flatten)]
|
||||
pub body: MessageRawBodyArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
@ -30,7 +32,6 @@ impl MessageSendCommand {
|
|||
|
||||
let account = self.account.name.as_ref().map(String::as_str);
|
||||
let cache = self.cache.disable;
|
||||
let raw_msg = &self.raw;
|
||||
|
||||
let (toml_account_config, account_config) =
|
||||
config.clone().into_account_configs(account, cache)?;
|
||||
|
@ -39,8 +40,8 @@ impl MessageSendCommand {
|
|||
|
||||
let is_tty = atty::is(Stream::Stdin);
|
||||
let is_json = printer.is_json();
|
||||
let raw_email = if is_tty || is_json {
|
||||
raw_msg.replace("\r", "").replace("\n", "\r\n")
|
||||
let msg = if is_tty || is_json {
|
||||
self.body.raw()
|
||||
} else {
|
||||
io::stdin()
|
||||
.lock()
|
||||
|
@ -50,11 +51,11 @@ impl MessageSendCommand {
|
|||
.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() {
|
||||
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?;
|
||||
|
||||
printer.print(format!("Message successfully sent and saved to {folder}!"))
|
||||
|
|
|
@ -8,24 +8,29 @@ use std::io::{self, BufRead};
|
|||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs},
|
||||
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs},
|
||||
printer::Printer,
|
||||
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)]
|
||||
pub struct MessageWriteCommand {
|
||||
#[command(flatten)]
|
||||
pub headers: HeaderRawArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub body: BodyRawArg,
|
||||
pub body: MessageRawBodyArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
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::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
envelope::arg::ids::EnvelopeIdArg,
|
||||
folder::arg::name::FolderNameArg,
|
||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs},
|
||||
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs},
|
||||
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)]
|
||||
pub struct TemplateForwardCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -26,10 +30,10 @@ pub struct TemplateForwardCommand {
|
|||
pub headers: HeaderRawArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub body: BodyRawArg,
|
||||
pub body: MessageRawBodyArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
|
|
@ -14,28 +14,31 @@ use self::{
|
|||
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)]
|
||||
pub enum TemplateSubcommand {
|
||||
/// Write a new template
|
||||
#[command(alias = "new", alias = "compose")]
|
||||
#[command(alias = "create", alias = "new", alias = "compose")]
|
||||
Write(TemplateWriteCommand),
|
||||
|
||||
/// Reply to a template
|
||||
#[command()]
|
||||
#[command(arg_required_else_help = true)]
|
||||
Reply(TemplateReplyCommand),
|
||||
|
||||
/// Generate a template for forwarding an email
|
||||
#[command(arg_required_else_help = true)]
|
||||
#[command(alias = "fwd")]
|
||||
Forward(TemplateForwardCommand),
|
||||
|
||||
/// Save a template to a folder
|
||||
#[command(arg_required_else_help = true)]
|
||||
#[command(alias = "add", alias = "create")]
|
||||
#[command(alias = "add")]
|
||||
Save(TemplateSaveCommand),
|
||||
|
||||
/// Send a template
|
||||
#[command(arg_required_else_help = true)]
|
||||
#[command()]
|
||||
Send(TemplateSendCommand),
|
||||
}
|
||||
|
||||
|
|
|
@ -5,15 +5,20 @@ use log::info;
|
|||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
envelope::arg::ids::EnvelopeIdArg,
|
||||
folder::arg::name::FolderNameArg,
|
||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs, reply::MessageReplyAllArg},
|
||||
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs, reply::MessageReplyAllArg},
|
||||
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)]
|
||||
pub struct TemplateReplyCommand {
|
||||
#[command(flatten)]
|
||||
|
@ -29,10 +34,10 @@ pub struct TemplateReplyCommand {
|
|||
pub headers: HeaderRawArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub body: BodyRawArg,
|
||||
pub body: MessageRawBodyArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
|
|
@ -6,22 +6,27 @@ use mml::MmlCompilerBuilder;
|
|||
use std::io::{self, BufRead};
|
||||
|
||||
use crate::{
|
||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
||||
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||
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)]
|
||||
pub struct TemplateSaveCommand {
|
||||
#[command(flatten)]
|
||||
pub folder: FolderNameArg,
|
||||
|
||||
/// The raw template to save
|
||||
#[arg(raw = true, value_delimiter = ' ')]
|
||||
pub raw: Vec<String>,
|
||||
#[command(flatten)]
|
||||
pub body: TemplateRawBodyArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
@ -42,7 +47,7 @@ impl TemplateSaveCommand {
|
|||
let is_tty = atty::is(Stream::Stdin);
|
||||
let is_json = printer.is_json();
|
||||
let tpl = if is_tty || is_json {
|
||||
self.raw.join(" ").replace("\r", "")
|
||||
self.body.raw()
|
||||
} else {
|
||||
io::stdin()
|
||||
.lock()
|
||||
|
|
|
@ -7,19 +7,23 @@ use mml::MmlCompilerBuilder;
|
|||
use std::io::{self, BufRead};
|
||||
|
||||
use crate::{
|
||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
||||
config::TomlConfig, printer::Printer,
|
||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||
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)]
|
||||
pub struct TemplateSendCommand {
|
||||
/// The raw template to save
|
||||
#[arg(raw = true, value_delimiter = ' ')]
|
||||
pub raw: Vec<String>,
|
||||
#[command(flatten)]
|
||||
pub body: TemplateRawBodyArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
@ -40,7 +44,7 @@ impl TemplateSendCommand {
|
|||
let is_tty = atty::is(Stream::Stdin);
|
||||
let is_json = printer.is_json();
|
||||
let tpl = if is_tty || is_json {
|
||||
self.raw.join(" ").replace("\r", "")
|
||||
self.body.raw()
|
||||
} else {
|
||||
io::stdin()
|
||||
.lock()
|
||||
|
|
|
@ -4,24 +4,25 @@ use email::message::Message;
|
|||
use log::info;
|
||||
|
||||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
config::TomlConfig,
|
||||
message::arg::{body::BodyRawArg, header::HeaderRawArgs},
|
||||
account::arg::name::AccountNameFlag, cache::arg::disable::CacheDisableFlag, config::TomlConfig,
|
||||
email::template::arg::body::TemplateRawBodyArg, message::arg::header::HeaderRawArgs,
|
||||
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)]
|
||||
pub struct TemplateWriteCommand {
|
||||
#[command(flatten)]
|
||||
pub headers: HeaderRawArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub body: BodyRawArg,
|
||||
pub body: TemplateRawBodyArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
pub mod arg;
|
||||
pub mod command;
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
use clap::Parser;
|
||||
use email::account::config::DEFAULT_INBOX_FOLDER;
|
||||
|
||||
/// The folder name argument parser
|
||||
/// The folder name argument parser.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct FolderNameArg {
|
||||
/// The name of the folder
|
||||
#[arg(name = "folder-name", value_name = "FOLDER")]
|
||||
/// The name of the folder.
|
||||
#[arg(name = "folder_name", value_name = "FOLDER")]
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// The optional folder name argument parser
|
||||
/// The optional folder name argument parser.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct FolderNameOptionalArg {
|
||||
/// The name of the folder
|
||||
#[arg(name = "folder-name", value_name = "FOLDER", default_value = DEFAULT_INBOX_FOLDER)]
|
||||
/// The name of the folder.
|
||||
#[arg(name = "folder_name", value_name = "FOLDER", default_value = DEFAULT_INBOX_FOLDER)]
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// The source folder name argument parser
|
||||
/// The source folder name argument parser.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct SourceFolderNameArg {
|
||||
/// The name of the source folder
|
||||
/// The name of the source folder.
|
||||
#[arg(name = "from-folder-name", value_name = "FROM")]
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// The target folder name argument parser
|
||||
/// The target folder name argument parser.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct TargetFolderNameArg {
|
||||
/// The name of the target folder
|
||||
/// The name of the target folder.
|
||||
#[arg(name = "to-folder-name", value_name = "TO")]
|
||||
pub name: String,
|
||||
}
|
||||
|
|
|
@ -3,21 +3,24 @@ use clap::Parser;
|
|||
use log::info;
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/// Create a new folder
|
||||
/// Create a new folder.
|
||||
///
|
||||
/// This command allows you to create a new folder using the given
|
||||
/// name.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct FolderCreateCommand {
|
||||
#[command(flatten)]
|
||||
pub folder: FolderNameArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub account: AccountNameFlag,
|
||||
}
|
||||
|
||||
impl FolderCreateCommand {
|
||||
|
|
|
@ -5,24 +5,24 @@ use log::info;
|
|||
use std::process;
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/// Delete a folder
|
||||
/// Delete a folder.
|
||||
///
|
||||
/// All emails from a given folder are definitely deleted. The folder
|
||||
/// is also deleted after execution of the command.
|
||||
/// All emails from the given folder are definitely deleted. The
|
||||
/// folder is also deleted after execution of the command.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct FolderDeleteCommand {
|
||||
#[command(flatten)]
|
||||
pub folder: FolderNameArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub account: AccountNameFlag,
|
||||
}
|
||||
|
||||
impl FolderDeleteCommand {
|
||||
|
|
|
@ -3,14 +3,14 @@ use clap::Parser;
|
|||
use log::info;
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/// Expunge a folder
|
||||
/// Expunge a folder.
|
||||
///
|
||||
/// 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.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct FolderExpungeCommand {
|
||||
|
@ -18,10 +18,10 @@ pub struct FolderExpungeCommand {
|
|||
pub folder: FolderNameArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub account: AccountNameFlag,
|
||||
}
|
||||
|
||||
impl FolderExpungeCommand {
|
||||
|
|
|
@ -5,24 +5,26 @@ use log::info;
|
|||
use crate::{
|
||||
account::arg::name::AccountNameFlag,
|
||||
backend::Backend,
|
||||
cache::arg::disable::DisableCacheFlag,
|
||||
cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig,
|
||||
folder::Folders,
|
||||
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)]
|
||||
pub struct FolderListCommand {
|
||||
#[command(flatten)]
|
||||
pub table: MaxTableWidthFlag,
|
||||
pub table: TableMaxWidthFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
}
|
||||
|
||||
impl FolderListCommand {
|
||||
|
|
|
@ -14,26 +14,24 @@ use self::{
|
|||
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)]
|
||||
pub enum FolderSubcommand {
|
||||
/// Create a new folder
|
||||
#[command(alias = "add")]
|
||||
#[command(alias = "add", alias = "new")]
|
||||
Create(FolderCreateCommand),
|
||||
|
||||
/// List all folders
|
||||
#[command(alias = "lst")]
|
||||
List(FolderListCommand),
|
||||
|
||||
/// Expunge a folder
|
||||
#[command()]
|
||||
Expunge(FolderExpungeCommand),
|
||||
|
||||
/// Purge a folder
|
||||
#[command()]
|
||||
Purge(FolderPurgeCommand),
|
||||
|
||||
/// Delete a folder
|
||||
#[command(alias = "remove", alias = "rm")]
|
||||
Delete(FolderDeleteCommand),
|
||||
}
|
||||
|
|
|
@ -5,24 +5,24 @@ use log::info;
|
|||
use std::process;
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/// Purge a folder
|
||||
/// Purge a folder.
|
||||
///
|
||||
/// All emails from a given folder are definitely deleted. The purged
|
||||
/// folder will remain empty after executing of the command.
|
||||
/// All emails from the given folder are definitely deleted. The
|
||||
/// purged folder will remain empty after execution of the command.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct FolderPurgeCommand {
|
||||
#[command(flatten)]
|
||||
pub folder: FolderNameArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
pub account: AccountNameFlag,
|
||||
}
|
||||
|
||||
impl FolderPurgeCommand {
|
||||
|
|
25
src/main.rs
25
src/main.rs
|
@ -1,7 +1,10 @@
|
|||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
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 std::env;
|
||||
|
||||
|
@ -9,7 +12,7 @@ use std::env;
|
|||
async fn main() -> Result<()> {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
if let Err((_, err)) = coredump::register_panic_handler() {
|
||||
warn!("cannot register custom panic handler: {err}");
|
||||
warn!("cannot register coredump panic handler: {err}");
|
||||
debug!("{err:?}");
|
||||
}
|
||||
|
||||
|
@ -18,15 +21,15 @@ async fn main() -> Result<()> {
|
|||
.format_timestamp(None)
|
||||
.init();
|
||||
|
||||
let raw_args: Vec<String> = env::args().collect();
|
||||
if raw_args.len() > 1 && raw_args[1].starts_with("mailto:") {
|
||||
// TODO
|
||||
// let cmd = MessageMailtoCommand::command()
|
||||
// .no_binary_name(true)
|
||||
// .try_get_matches_from([&raw_args[1]]);
|
||||
// match cmd {
|
||||
// Ok(m) => m.exec
|
||||
// }
|
||||
// if the first argument starts by "mailto:", execute straight the
|
||||
// mailto message command
|
||||
if let Some(ref url) = env::args().nth(1).filter(|arg| arg.starts_with("mailto:")) {
|
||||
let mut printer = StdoutPrinter::default();
|
||||
let config = TomlConfig::from_default_paths().await?;
|
||||
|
||||
return MessageMailtoCommand::new(url)?
|
||||
.execute(&mut printer, &config)
|
||||
.await;
|
||||
}
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
|
|
@ -7,10 +7,15 @@ use std::{fs, path::PathBuf};
|
|||
|
||||
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)]
|
||||
pub struct ManualGenerateCommand {
|
||||
/// Directory where man files should be generated in
|
||||
/// Directory where man files should be generated in.
|
||||
#[arg(value_parser = dir_parser)]
|
||||
pub dir: PathBuf,
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
use clap::Parser;
|
||||
|
||||
/// The table max width argument parser
|
||||
/// The table max width argument parser.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct MaxTableWidthFlag {
|
||||
/// The maximum width the table should not exceed
|
||||
#[arg(long, short = 'w', value_name = "PIXELS")]
|
||||
pub struct TableMaxWidthFlag {
|
||||
/// The maximum width the table should not exceed.
|
||||
///
|
||||
/// 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>,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue