mirror of
https://github.com/soywod/himalaya.git
synced 2024-11-22 11:00:19 +00:00
improve imap and mbox arg/handler
This commit is contained in:
parent
248240f52d
commit
bc5f9045ce
15 changed files with 198 additions and 118 deletions
|
@ -1,21 +1,12 @@
|
|||
//! Module related to completion arguments.
|
||||
//!
|
||||
//! This module provides subcommands and an argument matcher for the completion command.
|
||||
//! This module provides subcommands and an argument matcher related to completion.
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::{self, App, Arg, ArgMatches, Shell, SubCommand};
|
||||
use log::debug;
|
||||
|
||||
/// Subcommands related to the completion generation.
|
||||
pub fn subcmds<'a>() -> Vec<App<'a, 'a>> {
|
||||
vec![SubCommand::with_name("completion")
|
||||
.about("Generates the completion script for the given shell")
|
||||
.args(&[Arg::with_name("shell")
|
||||
.possible_values(&Shell::variants()[..])
|
||||
.required(true)])]
|
||||
}
|
||||
|
||||
/// Enumeration of all possible completion matches.
|
||||
/// Enumeration of all possible matches.
|
||||
pub enum Match<'a> {
|
||||
/// Generate completion script for the given shell slice.
|
||||
Generate(&'a str),
|
||||
|
@ -32,3 +23,12 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Match<'a>>> {
|
|||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Completion subcommands.
|
||||
pub fn subcmds<'a>() -> Vec<App<'a, 'a>> {
|
||||
vec![SubCommand::with_name("completion")
|
||||
.about("Generates the completion script for the given shell")
|
||||
.args(&[Arg::with_name("shell")
|
||||
.possible_values(&Shell::variants()[..])
|
||||
.required(true)])]
|
||||
}
|
||||
|
|
|
@ -1,10 +1,41 @@
|
|||
//! Module related to IMAP arguments.
|
||||
//!
|
||||
//! This module provides subcommands and an argument matcher related to IMAP.
|
||||
|
||||
use anyhow::Result;
|
||||
use clap;
|
||||
use clap::{App, ArgMatches};
|
||||
use log::debug;
|
||||
|
||||
use crate::domain::{config::entity::Config, imap::service::ImapServiceInterface};
|
||||
/// Enumeration of all possible matches.
|
||||
pub enum Match {
|
||||
/// Start the IMAP notify mode with the give keepalive duration.
|
||||
Notify(u64),
|
||||
|
||||
pub fn subcmds<'a>() -> Vec<clap::App<'a, 'a>> {
|
||||
/// Start the IMAP watch mode with the give keepalive duration.
|
||||
Watch(u64),
|
||||
}
|
||||
|
||||
/// IMAP arg matcher.
|
||||
pub fn matches(m: &ArgMatches) -> Result<Option<Match>> {
|
||||
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)));
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// IMAP subcommands.
|
||||
pub fn subcmds<'a>() -> Vec<App<'a, 'a>> {
|
||||
vec![
|
||||
clap::SubCommand::with_name("notify")
|
||||
.about("Notifies when new messages arrive in the given mailbox")
|
||||
|
@ -29,34 +60,3 @@ pub fn subcmds<'a>() -> Vec<clap::App<'a, 'a>> {
|
|||
),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn matches<ImapService: ImapServiceInterface>(
|
||||
arg_matches: &clap::ArgMatches,
|
||||
config: &Config,
|
||||
imap: &mut ImapService,
|
||||
) -> Result<bool> {
|
||||
if let Some(matches) = arg_matches.subcommand_matches("notify") {
|
||||
debug!("notify command matched");
|
||||
|
||||
let keepalive = clap::value_t_or_exit!(matches.value_of("keepalive"), u64);
|
||||
debug!("keepalive: {}", &keepalive);
|
||||
|
||||
imap.notify(&config, keepalive)?;
|
||||
imap.logout()?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
if let Some(matches) = arg_matches.subcommand_matches("watch") {
|
||||
debug!("watch command matched");
|
||||
|
||||
let keepalive = clap::value_t_or_exit!(matches.value_of("keepalive"), u64);
|
||||
debug!("keepalive: {}", &keepalive);
|
||||
|
||||
imap.watch(keepalive)?;
|
||||
imap.logout()?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
debug!("nothing matched");
|
||||
Ok(false)
|
||||
}
|
28
src/domain/imap/handler.rs
Normal file
28
src/domain/imap/handler.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
//! Module related to IMAP handling.
|
||||
//!
|
||||
//! This module gathers all IMAP handlers triggered by the CLI.
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::domain::{config::entity::Config, imap::service::ImapServiceInterface};
|
||||
|
||||
/// Notify handler.
|
||||
pub fn notify<ImapService: ImapServiceInterface>(
|
||||
keepalive: u64,
|
||||
config: &Config,
|
||||
imap: &mut ImapService,
|
||||
) -> Result<()> {
|
||||
imap.notify(&config, keepalive)?;
|
||||
imap.logout()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Watch handler.
|
||||
pub fn watch<ImapService: ImapServiceInterface>(
|
||||
keepalive: u64,
|
||||
imap: &mut ImapService,
|
||||
) -> Result<()> {
|
||||
imap.watch(keepalive)?;
|
||||
imap.logout()?;
|
||||
Ok(())
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
//! Modules related to IMAP.
|
||||
//! Module related to IMAP.
|
||||
|
||||
pub mod cli;
|
||||
pub mod arg;
|
||||
pub mod handler;
|
||||
pub mod service;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
//! Module related to IMAP servicing.
|
||||
//!
|
||||
//! This module exposes a service that can interact with IMAP servers.
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use imap;
|
||||
use log::{debug, trace};
|
||||
|
|
47
src/domain/mbox/arg.rs
Normal file
47
src/domain/mbox/arg.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
//! Module related to mailboxes arguments.
|
||||
//!
|
||||
//! This module provides subcommands and an argument matcher related to mailboxes.
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use log::debug;
|
||||
|
||||
/// Enumeration of all possible matches.
|
||||
pub enum Match {
|
||||
/// List all available mailboxes.
|
||||
List,
|
||||
}
|
||||
|
||||
/// Mailboxes arg matcher.
|
||||
pub fn matches(m: &ArgMatches) -> Result<Option<Match>> {
|
||||
if let Some(_) = m.subcommand_matches("mailboxes") {
|
||||
debug!("mailboxes command matched");
|
||||
return Ok(Some(Match::List));
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Mailboxes 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.
|
||||
pub fn source_arg<'a>() -> Arg<'a, 'a> {
|
||||
Arg::with_name("mailbox")
|
||||
.short("m")
|
||||
.long("mailbox")
|
||||
.help("Selects a specific mailbox")
|
||||
.value_name("MAILBOX")
|
||||
.default_value("INBOX")
|
||||
}
|
||||
|
||||
/// Target mailbox arg.
|
||||
pub fn target_arg<'a>() -> Arg<'a, 'a> {
|
||||
Arg::with_name("target")
|
||||
.help("Specifies the targetted mailbox")
|
||||
.value_name("TARGET")
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use clap;
|
||||
use log::{debug, trace};
|
||||
|
||||
use crate::{
|
||||
domain::{imap::service::ImapServiceInterface, mbox::entity::Mboxes},
|
||||
output::service::{OutputService, OutputServiceInterface},
|
||||
};
|
||||
|
||||
pub fn subcmds<'a>() -> Vec<clap::App<'a, 'a>> {
|
||||
vec![clap::SubCommand::with_name("mailboxes")
|
||||
.aliases(&["mailbox", "mboxes", "mbox", "m"])
|
||||
.about("Lists all mailboxes")]
|
||||
}
|
||||
|
||||
pub fn matches<ImapService: ImapServiceInterface>(
|
||||
arg_matches: &clap::ArgMatches,
|
||||
output: &OutputService,
|
||||
imap: &mut ImapService,
|
||||
) -> Result<bool> {
|
||||
if let Some(_) = arg_matches.subcommand_matches("mailboxes") {
|
||||
debug!("mailboxes command matched");
|
||||
let names = imap.list_mboxes()?;
|
||||
let mboxes = Mboxes::from(&names);
|
||||
debug!("mboxes len: {}", mboxes.0.len());
|
||||
trace!("{:#?}", mboxes);
|
||||
output.print(mboxes)?;
|
||||
imap.logout()?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
pub fn source_arg<'a>() -> clap::Arg<'a, 'a> {
|
||||
clap::Arg::with_name("mailbox")
|
||||
.short("m")
|
||||
.long("mailbox")
|
||||
.help("Selects a specific mailbox")
|
||||
.value_name("MAILBOX")
|
||||
.default_value("INBOX")
|
||||
}
|
||||
|
||||
pub fn mbox_target_arg<'a>() -> clap::Arg<'a, 'a> {
|
||||
clap::Arg::with_name("target")
|
||||
.help("Specifies the targetted mailbox")
|
||||
.value_name("TARGET")
|
||||
}
|
25
src/domain/mbox/handler.rs
Normal file
25
src/domain/mbox/handler.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
//! Module related to mailboxes handling.
|
||||
//!
|
||||
//! This module gathers all mailboxes actions triggered by the CLI.
|
||||
|
||||
use anyhow::Result;
|
||||
use log::{debug, trace};
|
||||
|
||||
use crate::{
|
||||
domain::{imap::service::ImapServiceInterface, mbox::entity::Mboxes},
|
||||
output::service::{OutputService, OutputServiceInterface},
|
||||
};
|
||||
|
||||
/// List mailboxes.
|
||||
pub fn list<ImapService: ImapServiceInterface>(
|
||||
output: &OutputService,
|
||||
imap: &mut ImapService,
|
||||
) -> Result<()> {
|
||||
let names = imap.list_mboxes()?;
|
||||
let mboxes = Mboxes::from(&names);
|
||||
debug!("mailboxes len: {}", mboxes.0.len());
|
||||
trace!("mailboxes: {:#?}", mboxes);
|
||||
output.print(mboxes)?;
|
||||
imap.logout()?;
|
||||
Ok(())
|
||||
}
|
|
@ -1,2 +1,5 @@
|
|||
pub mod cli;
|
||||
//! Module related to mailboxes.
|
||||
|
||||
pub mod arg;
|
||||
pub mod entity;
|
||||
pub mod handler;
|
||||
|
|
|
@ -22,7 +22,7 @@ use crate::{
|
|||
domain::{
|
||||
account::entity::Account,
|
||||
imap::service::ImapServiceInterface,
|
||||
mbox::{cli::mbox_target_arg, entity::Mbox},
|
||||
mbox::{arg::target_arg, entity::Mbox},
|
||||
smtp::service::SmtpServiceInterface,
|
||||
},
|
||||
flag::model::Flags,
|
||||
|
@ -93,12 +93,12 @@ pub fn subcmds<'a>() -> Vec<clap::App<'a, 'a>> {
|
|||
.aliases(&["cp"])
|
||||
.about("Copies a message to the targetted mailbox")
|
||||
.arg(uid_arg())
|
||||
.arg(mbox_target_arg()),
|
||||
.arg(target_arg()),
|
||||
clap::SubCommand::with_name("move")
|
||||
.aliases(&["mv"])
|
||||
.about("Moves a message to the targetted mailbox")
|
||||
.arg(uid_arg())
|
||||
.arg(mbox_target_arg()),
|
||||
.arg(target_arg()),
|
||||
clap::SubCommand::with_name("delete")
|
||||
.aliases(&["remove", "rm"])
|
||||
.about("Deletes a message")
|
|
@ -18,7 +18,7 @@
|
|||
///
|
||||
/// Execute `himalaya help <cmd>` where `<cmd>` is one entry of this list above
|
||||
/// to get more information about them.
|
||||
pub mod cli;
|
||||
pub mod arg;
|
||||
|
||||
/// Here are the two **main structs** of this module: `Msg` and `Msgs` which
|
||||
/// represent a *Mail* or *multiple Mails* in this crate.
|
||||
|
|
|
@ -3,7 +3,7 @@ use clap;
|
|||
use log::debug;
|
||||
|
||||
use crate::{
|
||||
domain::{imap::service::ImapServiceInterface, msg::cli::uid_arg},
|
||||
domain::{imap::service::ImapServiceInterface, msg::arg::uid_arg},
|
||||
flag::model::Flags,
|
||||
};
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
pub mod cli;
|
||||
pub mod arg;
|
||||
pub mod model;
|
||||
|
|
46
src/main.rs
46
src/main.rs
|
@ -23,14 +23,13 @@ fn create_app<'a>() -> clap::App<'a, 'a> {
|
|||
.version(env!("CARGO_PKG_VERSION"))
|
||||
.about(env!("CARGO_PKG_DESCRIPTION"))
|
||||
.author(env!("CARGO_PKG_AUTHORS"))
|
||||
.setting(clap::AppSettings::InferSubcommands)
|
||||
.args(&output_args())
|
||||
.args(&config_args())
|
||||
.arg(mbox::cli::source_arg())
|
||||
.subcommands(flag::cli::subcmds())
|
||||
.subcommands(imap::cli::subcmds())
|
||||
.subcommands(mbox::cli::subcmds())
|
||||
.subcommands(msg::cli::subcmds())
|
||||
.arg(mbox::arg::source_arg())
|
||||
.subcommands(flag::arg::subcmds())
|
||||
.subcommands(imap::arg::subcmds())
|
||||
.subcommands(mbox::arg::subcmds())
|
||||
.subcommands(msg::arg::subcmds())
|
||||
.subcommands(compl::arg::subcmds())
|
||||
}
|
||||
|
||||
|
@ -57,9 +56,13 @@ fn main() -> Result<()> {
|
|||
let app = create_app();
|
||||
let m = app.get_matches();
|
||||
|
||||
// Check shell completion BEFORE any entity or service initialization.
|
||||
if let Some(compl::arg::Match::Generate(shell)) = compl::arg::matches(&m)? {
|
||||
return compl::handler::generate(shell, create_app());
|
||||
// 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)) => {
|
||||
return compl::handler::generate(shell, create_app());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let mbox = Mbox::try_from(m.value_of("mailbox"))?;
|
||||
|
@ -69,11 +72,28 @@ fn main() -> Result<()> {
|
|||
let mut imap = ImapService::from((&account, &mbox));
|
||||
let mut smtp = SmtpService::from(&account);
|
||||
|
||||
// Check IMAP matches.
|
||||
match imap::arg::matches(&m)? {
|
||||
Some(imap::arg::Match::Notify(keepalive)) => {
|
||||
return imap::handler::notify(keepalive, &config, &mut imap);
|
||||
}
|
||||
Some(imap::arg::Match::Watch(keepalive)) => {
|
||||
return imap::handler::watch(keepalive, &mut imap);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
// Check mailbox matches.
|
||||
match mbox::arg::matches(&m)? {
|
||||
Some(mbox::arg::Match::List) => {
|
||||
return mbox::handler::list(&output, &mut imap);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
// TODO: use same system as compl
|
||||
let _matched = mbox::cli::matches(&m, &output, &mut imap)?
|
||||
|| flag::cli::matches(&m, &mut imap)?
|
||||
|| imap::cli::matches(&m, &config, &mut imap)?
|
||||
|| msg::cli::matches(&m, &mbox, &account, &output, &mut imap, &mut smtp)?;
|
||||
let _matched = flag::arg::matches(&m, &mut imap)?
|
||||
|| msg::arg::matches(&m, &mbox, &account, &output, &mut imap, &mut smtp)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//!
|
||||
//! [builder design pattern]: https://refactoring.guru/design-patterns/builder
|
||||
|
||||
use log::{debug, trace};
|
||||
use log::trace;
|
||||
use std::fmt;
|
||||
use terminal_size;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
@ -228,12 +228,12 @@ where
|
|||
table
|
||||
.iter_mut()
|
||||
.map(|row| {
|
||||
debug!("processing row: {:?}", row);
|
||||
trace!("processing row: {:?}", row);
|
||||
row.0
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.map(|(i, cell)| {
|
||||
debug!("processing cell: {:?}", cell);
|
||||
trace!("processing cell: {:?}", cell);
|
||||
trace!("table_width: {}", table_width);
|
||||
trace!("max_width: {}", Self::max_width());
|
||||
|
||||
|
|
Loading…
Reference in a new issue