improve arg comments, rename arg Match to Command

This commit is contained in:
Clément DOUIN 2021-09-18 15:15:36 +02:00
parent e41a71648c
commit 8e2a703e2b
No known key found for this signature in database
GPG key ID: 69C9B9CFFDEE2DEF
10 changed files with 122 additions and 95 deletions

View file

@ -1,24 +1,26 @@
//! Module related to completion arguments.
//! Module related to completion CLI.
//!
//! This module provides subcommands and an argument matcher related to completion.
//! This module provides subcommands and a command matcher related to completion.
use anyhow::Result;
use clap::{self, App, Arg, ArgMatches, Shell, SubCommand};
use log::debug;
/// Enumeration of all possible matches.
pub enum Match<'a> {
type OptionShell<'a> = Option<&'a str>;
/// Completion commands.
pub enum Command<'a> {
/// Generate completion script for the given shell slice.
Generate(&'a str),
Generate(OptionShell<'a>),
}
/// Completion arg matcher.
pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
/// Completion command matcher.
pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Command<'a>>> {
if let Some(m) = m.subcommand_matches("completion") {
debug!("completion command matched");
let shell = m.value_of("shell").unwrap();
debug!("shell: {}", shell);
return Ok(Some(Match::Generate(shell)));
let shell = m.value_of("shell");
debug!("shell: `{:?}`", shell);
return Ok(Some(Command::Generate(shell)));
};
Ok(None)

View file

@ -7,8 +7,8 @@ use clap::{App, Shell};
use std::{io, str::FromStr};
/// Generate completion script from the given [`clap::App`] for the given shell slice.
pub fn generate<'a>(shell: &'a str, mut app: App<'a, 'a>) -> Result<()> {
let shell = Shell::from_str(shell)
pub fn generate<'a>(shell: Option<&'a str>, mut app: App<'a, 'a>) -> Result<()> {
let shell = Shell::from_str(shell.unwrap_or_default())
.map_err(|err| anyhow!(err))
.context("cannot parse shell")?;
app.gen_completions_to("himalaya", shell, &mut io::stdout());

View file

@ -1,3 +1,7 @@
//! Module related to config CLI.
//!
//! This module provides arguments related to config.
use clap::Arg;
/// Config arguments.

View file

@ -1,34 +1,36 @@
//! Module related to IMAP arguments.
//! Module related to IMAP CLI.
//!
//! This module provides subcommands and an argument matcher related to IMAP.
//! This module provides subcommands and a command matcher related to IMAP.
use anyhow::Result;
use clap::{App, ArgMatches};
use log::debug;
/// Enumeration of all possible matches.
pub enum Match {
type Keepalive = u64;
/// IMAP commands.
pub enum Command {
/// Start the IMAP notify mode with the give keepalive duration.
Notify(u64),
Notify(Keepalive),
/// Start the IMAP watch mode with the give keepalive duration.
Watch(u64),
Watch(Keepalive),
}
/// IMAP arg matcher.
pub fn matches(m: &ArgMatches) -> Result<Option<Match>> {
/// IMAP command matcher.
pub fn matches(m: &ArgMatches) -> Result<Option<Command>> {
if let Some(m) = m.subcommand_matches("notify") {
debug!("notify command matched");
let keepalive = clap::value_t_or_exit!(m.value_of("keepalive"), u64);
debug!("keepalive: {}", keepalive);
return Ok(Some(Match::Notify(keepalive)));
return Ok(Some(Command::Notify(keepalive)));
}
if let Some(m) = m.subcommand_matches("watch") {
debug!("watch command matched");
let keepalive = clap::value_t_or_exit!(m.value_of("keepalive"), u64);
debug!("keepalive: {}", keepalive);
return Ok(Some(Match::Watch(keepalive)));
return Ok(Some(Command::Watch(keepalive)));
}
Ok(None)

View file

@ -1,35 +1,35 @@
//! Module related to mailboxes arguments.
//! Module related to mailbox CLI.
//!
//! This module provides subcommands and an argument matcher related to mailboxes.
//! This module provides subcommands, arguments and a command matcher related to mailbox.
use anyhow::Result;
use clap::{App, Arg, ArgMatches, SubCommand};
use log::debug;
/// Enumeration of all possible matches.
pub enum Match {
/// Mailbox commands.
pub enum Commands {
/// List all available mailboxes.
List,
}
/// Mailboxes arg matcher.
pub fn matches(m: &ArgMatches) -> Result<Option<Match>> {
/// Mailbox command matcher.
pub fn matches(m: &ArgMatches) -> Result<Option<Commands>> {
if let Some(_) = m.subcommand_matches("mailboxes") {
debug!("mailboxes command matched");
return Ok(Some(Match::List));
return Ok(Some(Commands::List));
}
Ok(None)
}
/// Mailboxes subcommands.
/// Mailbox subcommands.
pub fn subcmds<'a>() -> Vec<App<'a, 'a>> {
vec![SubCommand::with_name("mailboxes")
.aliases(&["mailbox", "mboxes", "mbox", "m"])
.about("Lists all mailboxes")]
}
/// Source mailbox arg.
/// Source mailbox argument.
pub fn source_arg<'a>() -> Arg<'a, 'a> {
Arg::with_name("mailbox")
.short("m")
@ -39,7 +39,7 @@ pub fn source_arg<'a>() -> Arg<'a, 'a> {
.default_value("INBOX")
}
/// Target mailbox arg.
/// Target mailbox argument.
pub fn target_arg<'a>() -> Arg<'a, 'a> {
Arg::with_name("target")
.help("Specifies the targetted mailbox")

View file

@ -1,3 +1,7 @@
//! Module related to message CLI.
//!
//! This module provides subcommands, arguments and a command matcher related to message.
use anyhow::Result;
use clap::{self, App, Arg, ArgMatches, SubCommand};
use log::debug;
@ -15,8 +19,8 @@ type RawMsg<'a> = &'a str;
type Query = String;
type AttachmentsPaths<'a> = Vec<&'a str>;
/// Enumeration of all possible matches.
pub enum Match<'a> {
/// Message commands.
pub enum Command<'a> {
Attachments(Uid<'a>),
Copy(Uid<'a>, TargetMbox<'a>),
Delete(Uid<'a>),
@ -30,16 +34,17 @@ pub enum Match<'a> {
Send(RawMsg<'a>),
Write(AttachmentsPaths<'a>),
Flag(msg::flag::arg::Match<'a>),
Tpl(msg::tpl::arg::Match<'a>),
Flag(msg::flag::arg::Command<'a>),
Tpl(msg::tpl::arg::Command<'a>),
}
pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
/// Message command matcher.
pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Command<'a>>> {
if let Some(m) = m.subcommand_matches("attachments") {
debug!("attachments command matched");
let uid = m.value_of("uid").unwrap();
debug!("uid: {}", &uid);
return Ok(Some(Match::Attachments(uid)));
return Ok(Some(Command::Attachments(uid)));
}
if let Some(m) = m.subcommand_matches("copy") {
@ -48,18 +53,18 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
debug!("uid: {}", &uid);
let target = m.value_of("target");
debug!("target mailbox: `{:?}`", target);
return Ok(Some(Match::Copy(uid, target)));
return Ok(Some(Command::Copy(uid, target)));
}
if let Some(m) = m.subcommand_matches("delete") {
debug!("copy command matched");
let uid = m.value_of("uid").unwrap();
debug!("uid: {}", &uid);
return Ok(Some(Match::Delete(uid)));
return Ok(Some(Command::Delete(uid)));
}
if let Some(m) = msg::flag::arg::matches(&m)? {
return Ok(Some(Match::Flag(m)));
return Ok(Some(Command::Flag(m)));
}
if let Some(m) = m.subcommand_matches("forward") {
@ -68,7 +73,7 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
let paths: Vec<&str> = m.values_of("attachments").unwrap_or_default().collect();
debug!("attachments paths: {:?}", paths);
debug!("uid: {}", &uid);
return Ok(Some(Match::Forward(uid, paths)));
return Ok(Some(Command::Forward(uid, paths)));
}
if let Some(m) = m.subcommand_matches("list") {
@ -83,7 +88,7 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
.map(|page| 1.max(page) - 1)
.unwrap_or_default();
debug!("page: `{:?}`", page);
return Ok(Some(Match::List(page_size, page)));
return Ok(Some(Command::List(page_size, page)));
}
if let Some(m) = m.subcommand_matches("move") {
@ -92,7 +97,7 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
debug!("uid: {}", &uid);
let target = m.value_of("target");
debug!("target mailbox: `{:?}`", target);
return Ok(Some(Match::Move(uid, target)));
return Ok(Some(Command::Move(uid, target)));
}
if let Some(m) = m.subcommand_matches("read") {
@ -102,7 +107,7 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
debug!("mime: {}", mime);
let raw = m.is_present("raw");
debug!("raw: {}", raw);
return Ok(Some(Match::Read(uid, mime, raw)));
return Ok(Some(Command::Read(uid, mime, raw)));
}
if let Some(m) = m.subcommand_matches("reply") {
@ -113,7 +118,7 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
debug!("reply all: {}", all);
let paths: Vec<&str> = m.values_of("attachments").unwrap_or_default().collect();
debug!("attachments paths: {:?}", paths);
return Ok(Some(Match::Reply(uid, all, paths)));
return Ok(Some(Command::Reply(uid, all, paths)));
}
if let Some(m) = m.subcommand_matches("save") {
@ -122,7 +127,7 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
debug!("message: {}", &msg);
let target = m.value_of("target");
debug!("target mailbox: `{:?}`", target);
return Ok(Some(Match::Save(target, msg)));
return Ok(Some(Command::Save(target, msg)));
}
if let Some(m) = m.subcommand_matches("search") {
@ -161,34 +166,32 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
})
.1
.join(" ");
return Ok(Some(Match::Search(query, page_size, page)));
return Ok(Some(Command::Search(query, page_size, page)));
}
if let Some(m) = m.subcommand_matches("send") {
debug!("send command matched");
let msg = m.value_of("message").unwrap_or_default();
debug!("message: {}", msg);
return Ok(Some(Match::Send(msg)));
return Ok(Some(Command::Send(msg)));
}
if let Some(m) = msg::tpl::arg::matches(&m)? {
return Ok(Some(Match::Tpl(m)));
return Ok(Some(Command::Tpl(m)));
}
if let Some(m) = m.subcommand_matches("write") {
debug!("write command matched");
let attachment_paths: Vec<&str> = m.values_of("attachments").unwrap_or_default().collect();
debug!("attachments paths: {:?}", attachment_paths);
return Ok(Some(Match::Write(attachment_paths)));
return Ok(Some(Command::Write(attachment_paths)));
}
debug!("default list command matched");
Ok(Some(Match::List(None, 0)))
Ok(Some(Command::List(None, 0)))
}
// == Argument Functions ==
/// Returns an Clap-Argument to be able to use `<UID>` in the commandline like
/// for the `himalaya read` subcommand.
/// Message UID argument.
pub(crate) fn uid_arg<'a>() -> Arg<'a, 'a> {
Arg::with_name("uid")
.help("Specifies the targetted message")
@ -196,6 +199,7 @@ pub(crate) fn uid_arg<'a>() -> Arg<'a, 'a> {
.required(true)
}
/// Message reply all argument.
pub(crate) fn reply_all_arg<'a>() -> Arg<'a, 'a> {
Arg::with_name("reply-all")
.help("Includes all recipients")
@ -203,6 +207,7 @@ pub(crate) fn reply_all_arg<'a>() -> Arg<'a, 'a> {
.long("all")
}
/// Message page size argument.
fn page_size_arg<'a>() -> Arg<'a, 'a> {
Arg::with_name("page-size")
.help("Page size")
@ -211,6 +216,7 @@ fn page_size_arg<'a>() -> Arg<'a, 'a> {
.value_name("INT")
}
/// Message page argument.
fn page_arg<'a>() -> Arg<'a, 'a> {
Arg::with_name("page")
.help("Page number")
@ -220,6 +226,7 @@ fn page_arg<'a>() -> Arg<'a, 'a> {
.default_value("0")
}
/// Message attachment argument.
/// TODO: move to attachment folder
fn attachment_arg<'a>() -> Arg<'a, 'a> {
Arg::with_name("attachments")
@ -230,7 +237,7 @@ fn attachment_arg<'a>() -> Arg<'a, 'a> {
.multiple(true)
}
/// Messages subcommands.
/// Message subcommands.
pub fn subcmds<'a>() -> Vec<App<'a, 'a>> {
vec![
msg::flag::arg::subcmds(),

View file

@ -1,3 +1,7 @@
//! Module related to message flag CLI.
//!
//! This module provides subcommands, arguments and a command matcher related to message flag.
use anyhow::Result;
use clap::{self, App, Arg, ArgMatches, SubCommand};
use log::debug;
@ -7,22 +11,22 @@ use crate::domain::msg;
type Uid<'a> = &'a str;
type Flags<'a> = &'a str;
/// Enumeration of all possible matches.
pub enum Match<'a> {
/// Message flag commands.
pub enum Command<'a> {
Set(Uid<'a>, Flags<'a>),
Add(Uid<'a>, Flags<'a>),
Remove(Uid<'a>, Flags<'a>),
}
/// Message flag arg matcher.
pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
/// Message flag command matcher.
pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Command<'a>>> {
if let Some(m) = m.subcommand_matches("set") {
debug!("set command matched");
let uid = m.value_of("uid").unwrap();
debug!("uid: {}", uid);
let flags = m.value_of("flags").unwrap();
debug!("flags: {}", flags);
return Ok(Some(Match::Set(uid, flags)));
return Ok(Some(Command::Set(uid, flags)));
}
if let Some(m) = m.subcommand_matches("add") {
@ -31,7 +35,7 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
debug!("uid: {}", uid);
let flags = m.value_of("flags").unwrap();
debug!("flags: {}", flags);
return Ok(Some(Match::Add(uid, flags)));
return Ok(Some(Command::Add(uid, flags)));
}
if let Some(m) = m.subcommand_matches("remove") {
@ -40,13 +44,13 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
debug!("uid: {}", uid);
let flags = m.value_of("flags").unwrap();
debug!("flags: {}", flags);
return Ok(Some(Match::Remove(uid, flags)));
return Ok(Some(Command::Remove(uid, flags)));
}
Ok(None)
}
/// Message flag arg.
/// Message flag flags argument.
fn flags_arg<'a>() -> Arg<'a, 'a> {
Arg::with_name("flags")
.help("IMAP flags (see https://tools.ietf.org/html/rfc3501#page-11). Just write the flag name without the backslash. Example: --flags \"Seen Answered\"")

View file

@ -1,3 +1,7 @@
//! Module related to message template CLI.
//!
//! This module provides subcommands, arguments and a command matcher related to message template.
use anyhow::Result;
use clap::{self, App, Arg, ArgMatches, SubCommand};
use log::debug;
@ -7,18 +11,18 @@ use crate::domain::msg::{self, arg::uid_arg};
type Uid<'a> = &'a str;
type All = bool;
/// Enumeration of all possible matches.
pub enum Match<'a> {
/// Message template commands.
pub enum Command<'a> {
New,
Reply(Uid<'a>, All),
Forward(Uid<'a>),
}
/// Message template arg matcher.
pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
/// Message template command matcher.
pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Command<'a>>> {
if let Some(_) = m.subcommand_matches("new") {
debug!("new command matched");
return Ok(Some(Match::New));
return Ok(Some(Command::New));
}
if let Some(m) = m.subcommand_matches("reply") {
@ -27,14 +31,14 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
debug!("uid: {}", uid);
let all = m.is_present("reply-all");
debug!("reply all: {}", all);
return Ok(Some(Match::Reply(uid, all)));
return Ok(Some(Command::Reply(uid, all)));
}
if let Some(m) = m.subcommand_matches("forward") {
debug!("forward command matched");
let uid = m.value_of("uid").unwrap();
debug!("uid: {}", uid);
return Ok(Some(Match::Forward(uid)));
return Ok(Some(Command::Forward(uid)));
}
Ok(None)

View file

@ -58,7 +58,7 @@ fn main() -> Result<()> {
// Check completion match BEFORE any entity or service initialization.
// See https://github.com/soywod/himalaya/issues/115.
match compl::arg::matches(&m)? {
Some(compl::arg::Match::Generate(shell)) => {
Some(compl::arg::Command::Generate(shell)) => {
return compl::handler::generate(shell, create_app());
}
_ => (),
@ -73,10 +73,10 @@ fn main() -> Result<()> {
// Check IMAP matches.
match imap::arg::matches(&m)? {
Some(imap::arg::Match::Notify(keepalive)) => {
Some(imap::arg::Command::Notify(keepalive)) => {
return imap::handler::notify(keepalive, &config, &mut imap);
}
Some(imap::arg::Match::Watch(keepalive)) => {
Some(imap::arg::Command::Watch(keepalive)) => {
return imap::handler::watch(keepalive, &mut imap);
}
_ => (),
@ -84,7 +84,7 @@ fn main() -> Result<()> {
// Check mailbox matches.
match mbox::arg::matches(&m)? {
Some(mbox::arg::Match::List) => {
Some(mbox::arg::Commands::List) => {
return mbox::handler::list(&output, &mut imap);
}
_ => (),
@ -92,62 +92,62 @@ fn main() -> Result<()> {
// Check message matches.
match msg::arg::matches(&m)? {
Some(msg::arg::Match::Attachments(uid)) => {
Some(msg::arg::Command::Attachments(uid)) => {
return msg::handler::attachments(uid, &account, &output, &mut imap);
}
Some(msg::arg::Match::Copy(uid, mbox)) => {
Some(msg::arg::Command::Copy(uid, mbox)) => {
return msg::handler::copy(uid, mbox, &output, &mut imap);
}
Some(msg::arg::Match::Delete(uid)) => {
Some(msg::arg::Command::Delete(uid)) => {
return msg::handler::delete(uid, &output, &mut imap);
}
Some(msg::arg::Match::Forward(uid, paths)) => {
Some(msg::arg::Command::Forward(uid, paths)) => {
return msg::handler::forward(uid, paths, &account, &output, &mut imap, &mut smtp);
}
Some(msg::arg::Match::List(page_size, page)) => {
Some(msg::arg::Command::List(page_size, page)) => {
return msg::handler::list(page_size, page, &account, &output, &mut imap);
}
Some(msg::arg::Match::Move(uid, mbox)) => {
Some(msg::arg::Command::Move(uid, mbox)) => {
return msg::handler::move_(uid, mbox, &output, &mut imap);
}
Some(msg::arg::Match::Read(uid, mime, raw)) => {
Some(msg::arg::Command::Read(uid, mime, raw)) => {
return msg::handler::read(uid, mime, raw, &output, &mut imap);
}
Some(msg::arg::Match::Reply(uid, all, paths)) => {
Some(msg::arg::Command::Reply(uid, all, paths)) => {
return msg::handler::reply(uid, all, paths, &account, &output, &mut imap, &mut smtp);
}
Some(msg::arg::Match::Save(mbox, msg)) => {
Some(msg::arg::Command::Save(mbox, msg)) => {
return msg::handler::save(mbox, msg, &mut imap);
}
Some(msg::arg::Match::Search(query, page_size, page)) => {
Some(msg::arg::Command::Search(query, page_size, page)) => {
return msg::handler::search(page_size, page, query, &account, &output, &mut imap);
}
Some(msg::arg::Match::Send(msg)) => {
Some(msg::arg::Command::Send(msg)) => {
return msg::handler::send(msg, &output, &mut imap, &mut smtp);
}
Some(msg::arg::Match::Write(paths)) => {
Some(msg::arg::Command::Write(paths)) => {
return msg::handler::write(paths, &account, &output, &mut imap, &mut smtp);
}
Some(msg::arg::Match::Flag(m)) => match m {
msg::flag::arg::Match::Set(uid, flags) => {
Some(msg::arg::Command::Flag(m)) => match m {
msg::flag::arg::Command::Set(uid, flags) => {
return msg::flag::handler::set(uid, flags, &mut imap);
}
msg::flag::arg::Match::Add(uid, flags) => {
msg::flag::arg::Command::Add(uid, flags) => {
return msg::flag::handler::add(uid, flags, &mut imap);
}
msg::flag::arg::Match::Remove(uid, flags) => {
msg::flag::arg::Command::Remove(uid, flags) => {
return msg::flag::handler::remove(uid, flags, &mut imap);
}
},
Some(msg::arg::Match::Tpl(m)) => match m {
msg::tpl::arg::Match::New => {
Some(msg::arg::Command::Tpl(m)) => match m {
msg::tpl::arg::Command::New => {
return msg::tpl::handler::new(&account, &output, &mut imap);
}
msg::tpl::arg::Match::Reply(uid, all) => {
msg::tpl::arg::Command::Reply(uid, all) => {
return msg::tpl::handler::reply(uid, all, &account, &output, &mut imap);
}
msg::tpl::arg::Match::Forward(uid) => {
msg::tpl::arg::Command::Forward(uid) => {
return msg::tpl::handler::forward(uid, &account, &output, &mut imap);
}
},

View file

@ -1,3 +1,7 @@
//! Module related to output CLI.
//!
//! This module provides arguments related to output.
use clap::Arg;
/// Output arguments.