refactor envelope with clap derive api

This commit is contained in:
Clément DOUIN
2023-12-06 23:12:06 +01:00
parent 4a77253c1d
commit 2c33dd2f9f
14 changed files with 304 additions and 642 deletions
-91
View File
@@ -1,91 +0,0 @@
//! Email CLI module.
//!
//! This module contains the command matcher, the subcommands and the
//! arguments related to the email domain.
use anyhow::Result;
use clap::{Arg, ArgMatches, Command};
use crate::ui::table;
const ARG_PAGE: &str = "page";
const ARG_PAGE_SIZE: &str = "page-size";
const CMD_LIST: &str = "list";
const CMD_ENVELOPE: &str = "envelope";
pub type Page = usize;
pub type PageSize = usize;
/// Represents the email commands.
#[derive(Debug, PartialEq, Eq)]
pub enum Cmd {
List(table::args::MaxTableWidth, Option<PageSize>, Page),
}
/// Email command matcher.
pub fn matches(m: &ArgMatches) -> Result<Option<Cmd>> {
let cmd = if let Some(m) = m.subcommand_matches(CMD_ENVELOPE) {
if let Some(m) = m.subcommand_matches(CMD_LIST) {
let max_table_width = table::args::parse_max_width(m);
let page_size = parse_page_size_arg(m);
let page = parse_page_arg(m);
Some(Cmd::List(max_table_width, page_size, page))
} else {
Some(Cmd::List(None, None, 0))
}
} else {
None
};
Ok(cmd)
}
/// Represents the envelope subcommand.
pub fn subcmd() -> Command {
Command::new(CMD_ENVELOPE)
.about("Subcommand to manage envelopes")
.long_about("Subcommand to manage envelopes like list")
.subcommands([Command::new(CMD_LIST)
.alias("lst")
.about("List envelopes")
.arg(page_size_arg())
.arg(page_arg())
.arg(table::args::max_width())])
}
/// Represents the page size argument.
fn page_size_arg() -> Arg {
Arg::new(ARG_PAGE_SIZE)
.help("Page size")
.long("page-size")
.short('s')
.value_name("INT")
}
/// Represents the page size argument parser.
fn parse_page_size_arg(matches: &ArgMatches) -> Option<usize> {
matches
.get_one::<String>(ARG_PAGE_SIZE)
.and_then(|s| s.parse().ok())
}
/// Represents the page argument.
fn page_arg() -> Arg {
Arg::new(ARG_PAGE)
.help("Page number")
.short('p')
.long("page")
.value_name("INT")
.default_value("1")
}
/// Represents the page argument parser.
fn parse_page_arg(matches: &ArgMatches) -> usize {
matches
.get_one::<String>(ARG_PAGE)
.unwrap()
.parse()
.ok()
.map(|page| 1.max(page) - 1)
.unwrap_or_default()
}
+68
View File
@@ -0,0 +1,68 @@
use anyhow::Result;
use clap::Parser;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
cache::arg::disable::DisableCacheFlag,
config::TomlConfig,
folder::arg::name::FolderNameOptionalArg,
printer::{PrintTableOpts, Printer},
ui::arg::max_width::MaxTableWidthFlag,
};
/// List all envelopes from a folder
#[derive(Debug, Parser)]
pub struct EnvelopeListCommand {
#[command(flatten)]
pub folder: FolderNameOptionalArg,
/// The page number
#[arg(long, short, value_name = "NUMBER", default_value = "1")]
pub page: usize,
/// The page size
#[arg(long, short = 's', value_name = "NUMBER")]
pub page_size: Option<usize>,
#[command(flatten)]
pub table: MaxTableWidthFlag,
#[command(flatten)]
pub account: AccountNameFlag,
#[command(flatten)]
pub cache: DisableCacheFlag,
}
impl EnvelopeListCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing envelope list command");
let folder = &self.folder.name;
let some_account_name = self.account.name.as_ref().map(String::as_str);
let (toml_account_config, account_config) = config
.clone()
.into_account_configs(some_account_name, self.cache.disable)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let page_size = self
.page_size
.unwrap_or(account_config.email_listing_page_size());
let page = 1.max(self.page) - 1;
let envelopes = backend.list_envelopes(folder, page_size, page).await?;
printer.print_table(
Box::new(envelopes),
PrintTableOpts {
format: &account_config.email_reading_format,
max_width: self.table.max_width,
},
)?;
Ok(())
}
}
+24
View File
@@ -0,0 +1,24 @@
pub mod list;
use anyhow::Result;
use clap::Subcommand;
use crate::{config::TomlConfig, printer::Printer};
use self::list::EnvelopeListCommand;
/// Subcommand to manage envelopes
#[derive(Debug, Subcommand)]
pub enum EnvelopeSubcommand {
/// List all envelopes from a folder
#[command(alias = "lst")]
List(EnvelopeListCommand),
}
impl EnvelopeSubcommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
match self {
Self::List(cmd) => cmd.execute(printer, config).await,
}
}
}
-32
View File
@@ -1,32 +0,0 @@
use anyhow::Result;
use email::account::config::AccountConfig;
use log::{debug, trace};
use crate::{
backend::Backend,
printer::{PrintTableOpts, Printer},
};
pub async fn list<P: Printer>(
config: &AccountConfig,
printer: &mut P,
backend: &Backend,
folder: &str,
max_width: Option<usize>,
page_size: Option<usize>,
page: usize,
) -> Result<()> {
let page_size = page_size.unwrap_or(config.email_listing_page_size());
debug!("page size: {}", page_size);
let envelopes = backend.list_envelopes(&folder, page_size, page).await?;
trace!("envelopes: {:?}", envelopes);
printer.print_table(
Box::new(envelopes),
PrintTableOpts {
format: &config.email_reading_format,
max_width,
},
)
}
+1 -2
View File
@@ -1,7 +1,6 @@
pub mod args;
pub mod command;
pub mod config;
pub mod flag;
pub mod handlers;
use anyhow::Result;
use email::account::config::AccountConfig;
+5 -5
View File
@@ -6,7 +6,7 @@
use anyhow::Result;
use clap::{Arg, ArgAction, ArgMatches, Command};
use crate::{folder, template};
use crate::template;
const ARG_CRITERIA: &str = "criterion";
const ARG_HEADERS: &str = "headers";
@@ -71,7 +71,7 @@ pub fn matches(m: &ArgMatches) -> Result<Option<Cmd>> {
Some(Cmd::Attachments(ids))
} else if let Some(m) = m.subcommand_matches(CMD_COPY) {
let ids = parse_ids_arg(m);
let folder = folder::args::parse_target_arg(m);
let folder = "INBOX";
Some(Cmd::Copy(ids, folder))
} else if let Some(m) = m.subcommand_matches(CMD_DELETE) {
let ids = parse_ids_arg(m);
@@ -83,7 +83,7 @@ pub fn matches(m: &ArgMatches) -> Result<Option<Cmd>> {
Some(Cmd::Forward(id, headers, body))
} else if let Some(m) = m.subcommand_matches(CMD_MOVE) {
let ids = parse_ids_arg(m);
let folder = folder::args::parse_target_arg(m);
let folder = "INBOX";
Some(Cmd::Move(ids, folder))
} else if let Some(m) = m.subcommand_matches(CMD_READ) {
let ids = parse_ids_arg(m);
@@ -158,12 +158,12 @@ pub fn subcmd() -> Command {
Command::new(CMD_COPY)
.alias("cp")
.about("Copy emails to the given folder")
.arg(folder::args::target_arg())
// .arg(folder::args::target_arg())
.arg(ids_arg()),
Command::new(CMD_MOVE)
.alias("mv")
.about("Move emails to the given folder")
.arg(folder::args::target_arg())
// .arg(folder::args::target_arg())
.arg(ids_arg()),
Command::new(CMD_DELETE)
.aliases(["remove", "rm"])