diff --git a/CHANGELOG.md b/CHANGELOG.md index d2cd52d..f0c0861 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Default page size to config [#96] + ## [0.2.6] - 2021-04-17 ### Added @@ -180,4 +184,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#84]: https://github.com/soywod/himalaya/issues/84 [#87]: https://github.com/soywod/himalaya/issues/87 [#89]: https://github.com/soywod/himalaya/issues/89 +[#96]: https://github.com/soywod/himalaya/issues/96 [#100]: https://github.com/soywod/himalaya/issues/100 diff --git a/src/completion/cli.rs b/src/completion/cli.rs index 5a38279..0679b67 100644 --- a/src/completion/cli.rs +++ b/src/completion/cli.rs @@ -1,10 +1,11 @@ use clap::{self, App, Arg, ArgMatches, Shell, SubCommand}; use error_chain::error_chain; +use log::debug; use std::io; error_chain! {} -pub fn completion_subcmds<'a>() -> Vec> { +pub fn completion_subcmds<'c>() -> Vec> { vec![SubCommand::with_name("completion") .about("Generates the completion script for the given shell") .args(&[Arg::with_name("shell") @@ -14,14 +15,17 @@ pub fn completion_subcmds<'a>() -> Vec> { pub fn completion_matches(mut app: App, matches: &ArgMatches) -> Result { if let Some(matches) = matches.subcommand_matches("completion") { + debug!("[completion::cli::matches] completion command matched"); let shell = match matches.value_of("shell").unwrap() { "fish" => Shell::Fish, "zsh" => Shell::Zsh, "bash" | _ => Shell::Bash, }; + debug!("[completion::cli::matches] shell: {}", shell); app.gen_completions_to("himalaya", shell, &mut io::stdout()); return Ok(true); }; + debug!("[completion::cli::matches] nothing matched"); Ok(false) } diff --git a/src/config/model.rs b/src/config/model.rs index 1ce46ae..0843a5b 100644 --- a/src/config/model.rs +++ b/src/config/model.rs @@ -8,6 +8,8 @@ use crate::output::utils::run_cmd; error_chain! {} +const DEFAULT_PAGE_SIZE: usize = 10; + // Account #[derive(Debug, Deserialize)] @@ -17,6 +19,7 @@ pub struct Account { pub name: Option, pub downloads_dir: Option, pub signature: Option, + pub default_page_size: Option, // Specific pub default: Option, @@ -94,6 +97,7 @@ pub struct Config { pub downloads_dir: Option, pub notify_cmd: Option, pub signature: Option, + pub default_page_size: Option, #[serde(flatten)] pub accounts: HashMap, @@ -193,4 +197,14 @@ impl Config { .or_else(|| self.signature.as_ref()) .map(|sig| sig.to_owned()) } + + pub fn default_page_size(&self, account: &Account) -> usize { + account + .default_page_size + .as_ref() + .or_else(|| self.default_page_size.as_ref()) + .or(Some(&DEFAULT_PAGE_SIZE)) + .unwrap() + .to_owned() + } } diff --git a/src/flag/cli.rs b/src/flag/cli.rs index 60a4970..543e56b 100644 --- a/src/flag/cli.rs +++ b/src/flag/cli.rs @@ -1,8 +1,8 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use error_chain::error_chain; +use log::debug; -use crate::msg::cli::uid_arg; -use crate::{config::model::Config, imap::model::ImapConnector}; +use crate::{config::model::Account, imap::model::ImapConnector, msg::cli::uid_arg}; error_chain! { links { @@ -11,7 +11,7 @@ error_chain! { } } -fn flags_arg<'a, 'b>() -> Arg<'a, 'b> { +fn flags_arg<'f>() -> Arg<'f, 'f> { Arg::with_name("flags") .help("IMAP flags (see https://tools.ietf.org/html/rfc3501#page-11)") .value_name("FLAGS…") @@ -19,7 +19,7 @@ fn flags_arg<'a, 'b>() -> Arg<'a, 'b> { .required(true) } -pub fn flag_subcmds<'a>() -> Vec> { +pub fn flag_subcmds<'f>() -> Vec> { vec![SubCommand::with_name("flags") .aliases(&["flag"]) .about("Handles flags") @@ -46,37 +46,55 @@ pub fn flag_subcmds<'a>() -> Vec> { )] } -pub fn flag_matches(matches: &ArgMatches) -> Result { - let config = Config::new_from_file()?; - let account = config.find_account_by_name(matches.value_of("account"))?; - let mbox = matches.value_of("mailbox").unwrap(); - +pub fn flag_matches(account: &Account, mbox: &str, matches: &ArgMatches) -> Result { if let Some(matches) = matches.subcommand_matches("set") { - let mut imap_conn = ImapConnector::new(&account)?; + debug!("[flag::cli::matches] set command matched"); + let uid = matches.value_of("uid").unwrap(); + debug!("[flag::cli::matches] uid: {}", uid); + let flags = matches.value_of("flags").unwrap(); + debug!("[flag::cli::matches] flags: {}", flags); + + let mut imap_conn = ImapConnector::new(&account)?; imap_conn.set_flags(mbox, uid, flags)?; + imap_conn.logout(); return Ok(true); } if let Some(matches) = matches.subcommand_matches("add") { - let mut imap_conn = ImapConnector::new(&account)?; + debug!("[flag::cli::matches] add command matched"); + let uid = matches.value_of("uid").unwrap(); + debug!("[flag::cli::matches] uid: {}", uid); + let flags = matches.value_of("flags").unwrap(); + debug!("[flag::cli::matches] flags: {}", flags); + + let mut imap_conn = ImapConnector::new(&account)?; imap_conn.add_flags(mbox, uid, flags)?; + imap_conn.logout(); return Ok(true); } if let Some(matches) = matches.subcommand_matches("remove") { - let mut imap_conn = ImapConnector::new(&account)?; + debug!("[flag::cli::matches] remove command matched"); + let uid = matches.value_of("uid").unwrap(); + debug!("[flag::cli::matches] uid: {}", uid); + let flags = matches.value_of("flags").unwrap(); + debug!("[flag::cli::matches] flags: {}", flags); + + let mut imap_conn = ImapConnector::new(&account)?; imap_conn.remove_flags(mbox, uid, flags)?; + imap_conn.logout(); return Ok(true); } + debug!("[flag::cli::matches] nothing matched"); Ok(false) } diff --git a/src/imap/cli.rs b/src/imap/cli.rs index 85ef1d2..0f675ea 100644 --- a/src/imap/cli.rs +++ b/src/imap/cli.rs @@ -2,7 +2,10 @@ use clap::{self, App, ArgMatches, SubCommand}; use error_chain::error_chain; use log::debug; -use crate::{config::model::Config, imap::model::ImapConnector}; +use crate::{ + config::model::{Account, Config}, + imap::model::ImapConnector, +}; error_chain! { links { @@ -15,18 +18,20 @@ pub fn imap_subcmds<'a>() -> Vec> { vec![SubCommand::with_name("idle").about("Spawns a blocking idle daemon")] } -pub fn imap_matches(matches: &ArgMatches) -> Result { - let config = Config::new_from_file()?; - let account = config.find_account_by_name(matches.value_of("account"))?; - let mbox = matches.value_of("mailbox").unwrap(); - +pub fn imap_matches( + config: &Config, + account: &Account, + mbox: &str, + matches: &ArgMatches, +) -> Result { if let Some(_) = matches.subcommand_matches("idle") { - debug!("[imap::cli] idle command matched"); + debug!("[imap::cli::matches] idle command matched"); let mut imap_conn = ImapConnector::new(&account)?; imap_conn.idle(&config, &mbox)?; imap_conn.logout(); return Ok(true); } + debug!("[imap::cli::matches] nothing matched"); Ok(false) } diff --git a/src/imap/model.rs b/src/imap/model.rs index 1cb9b30..0392ff7 100644 --- a/src/imap/model.rs +++ b/src/imap/model.rs @@ -197,10 +197,14 @@ impl<'ic> ImapConnector<'ic> { } // TODO: add tests, improve error management when empty page - let cursor = (page * page_size) as i64; - let begin = 1.max(last_seq - cursor); - let end = begin - begin.min(*page_size as i64) + 1; - let range = format!("{}:{}", begin, end); + let range = if page_size > &0 { + let cursor = (page * page_size) as i64; + let begin = 1.max(last_seq - cursor); + let end = begin - begin.min(*page_size as i64) + 1; + format!("{}:{}", begin, end) + } else { + String::from("1:*") + }; let fetches = self .sess diff --git a/src/main.rs b/src/main.rs index ec2b4a4..cfdb9d7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,8 @@ +use clap; +use error_chain::error_chain; +use log::{debug, error, trace}; +use std::env; + mod input; mod smtp; mod table; @@ -31,14 +36,9 @@ mod completion { pub(crate) mod cli; } -use clap::{self, App}; -use error_chain::error_chain; -use log::{debug, error}; -use std::env; - use crate::{ completion::cli::{completion_matches, completion_subcmds}, - config::cli::account_arg, + config::{cli::account_arg, model::Config}, flag::cli::{flag_matches, flag_subcmds}, imap::cli::{imap_matches, imap_subcmds}, mbox::cli::{mbox_matches, mbox_source_arg, mbox_subcmds}, @@ -52,16 +52,17 @@ use crate::{ error_chain! { links { + CompletionCli(crate::completion::cli::Error, crate::completion::cli::ErrorKind); + Config(crate::config::model::Error, crate::config::model::ErrorKind); FlagCli(crate::flag::cli::Error, crate::flag::cli::ErrorKind); ImapCli(crate::imap::cli::Error, crate::imap::cli::ErrorKind); MboxCli(crate::mbox::cli::Error, crate::mbox::cli::ErrorKind); MsgCli(crate::msg::cli::Error, crate::msg::cli::ErrorKind); - CompletionCli(crate::completion::cli::Error, crate::completion::cli::ErrorKind); OutputLog(crate::output::log::Error, crate::output::log::ErrorKind); } } -fn build_cli() -> App<'static, 'static> { +fn build_app<'a>() -> clap::App<'a, 'a> { clap::App::new(env!("CARGO_PKG_NAME")) .version(env!("CARGO_PKG_VERSION")) .about(env!("CARGO_PKG_DESCRIPTION")) @@ -77,36 +78,33 @@ fn build_cli() -> App<'static, 'static> { } fn run() -> Result<()> { - let matches = build_cli().get_matches(); + let app = build_app(); + let matches = app.get_matches(); + let output_fmt: OutputFmt = matches.value_of("output").unwrap().into(); let log_level: LogLevel = matches.value_of("log").unwrap().into(); init_logger(&output_fmt, &log_level)?; + debug!("[main] output format: {}", output_fmt); + debug!("[main] log level: {}", log_level); - debug!("[main] begin"); - debug!("[main] output format: {}", &output_fmt); - debug!("[main] log level: {}", &log_level); - debug!("[main] browse matches"); + debug!("[main] init config"); + let config = Config::new_from_file()?; + trace!("[main] {:#?}", config); - loop { - if mbox_matches(&matches)? { - break; - } + let account_name = matches.value_of("account"); + debug!("[main] find {} account", account_name.unwrap_or("default")); + let account = config.find_account_by_name(account_name)?; + trace!("[main] {:#?}", account); - if flag_matches(&matches)? { - break; - } + let mbox = matches.value_of("mailbox").unwrap(); + debug!("[msg::cli::matches] mailbox: {}", mbox); - if imap_matches(&matches)? { - break; - } - - if completion_matches(build_cli(), &matches)? { - break; - } - - msg_matches(&matches)?; - break; - } + debug!("[main] begin matching"); + let _matched = mbox_matches(&account, &matches)? + || flag_matches(&account, &mbox, &matches)? + || imap_matches(&config, &account, &mbox, &matches)? + || completion_matches(build_app(), &matches)? + || msg_matches(&config, &account, &mbox, &matches)?; Ok(()) } diff --git a/src/mbox/cli.rs b/src/mbox/cli.rs index 0925d46..04cdd11 100644 --- a/src/mbox/cli.rs +++ b/src/mbox/cli.rs @@ -1,8 +1,8 @@ use clap::{self, App, Arg, ArgMatches, SubCommand}; use error_chain::error_chain; -use log::debug; +use log::{debug, trace}; -use crate::{config::model::Config, imap::model::ImapConnector, info}; +use crate::{config::model::Account, imap::model::ImapConnector, info}; error_chain! { links { @@ -34,20 +34,19 @@ pub fn mbox_subcmds<'a>() -> Vec> { .about("Lists all mailboxes")] } -pub fn mbox_matches(matches: &ArgMatches) -> Result { - let config = Config::new_from_file()?; - let account = config.find_account_by_name(matches.value_of("account"))?; - +pub fn mbox_matches(account: &Account, matches: &ArgMatches) -> Result { if let Some(_) = matches.subcommand_matches("mailboxes") { - debug!("Subcommand matched: mailboxes"); + debug!("[mbox::cli::matches] mailboxes command matched"); let mut imap_conn = ImapConnector::new(&account)?; let mboxes = imap_conn.list_mboxes()?; info!(&mboxes); + trace!("[mbox::cli::matches] {:#?}", mboxes); imap_conn.logout(); return Ok(true); } + debug!("[mbox::cli::matches] nothing matched"); Ok(false) } diff --git a/src/msg/cli.rs b/src/msg/cli.rs index 63ded1b..d14e642 100644 --- a/src/msg/cli.rs +++ b/src/msg/cli.rs @@ -1,10 +1,10 @@ use clap::{self, App, Arg, ArgMatches, SubCommand}; use error_chain::error_chain; -use log::{debug, error}; +use log::{debug, error, trace}; use std::{fs, ops::Deref}; use crate::{ - config::model::Config, + config::model::{Account, Config}, flag::model::Flag, imap::model::ImapConnector, info, input, @@ -46,7 +46,6 @@ fn page_size_arg<'a>() -> Arg<'a, 'a> { .short("s") .long("size") .value_name("INT") - .default_value("10") } fn page_arg<'a>() -> Arg<'a, 'a> { @@ -167,36 +166,52 @@ pub fn msg_subcmds<'a>() -> Vec> { ] } -pub fn msg_matches(matches: &ArgMatches) -> Result<()> { - let config = Config::new_from_file()?; - let account = config.find_account_by_name(matches.value_of("account"))?; - let mbox = matches.value_of("mailbox").unwrap(); - +pub fn msg_matches( + config: &Config, + account: &Account, + mbox: &str, + matches: &ArgMatches, +) -> Result { if let Some(matches) = matches.subcommand_matches("list") { - debug!("Subcommand matched: list"); + debug!("[msg::cli::matches] list command matched"); + + let page_size: usize = matches + .value_of("page-size") + .and_then(|s| s.parse().ok()) + .unwrap_or(config.default_page_size(&account)); + debug!("[msg::cli::matches] page size: {}", &page_size); + let page: usize = matches + .value_of("page") + .unwrap() + .parse() + .unwrap_or_default(); + debug!("[msg::cli::matches] page: {}", &page); let mut imap_conn = ImapConnector::new(&account)?; - let page_size: usize = matches.value_of("page-size").unwrap().parse().unwrap(); - debug!("Page size: {}", &page_size); - let page: usize = matches.value_of("page").unwrap().parse().unwrap(); - debug!("Page: {}", &page); - let msgs = imap_conn.list_msgs(&mbox, &page_size, &page)?; let msgs = Msgs::from(&msgs); info!(&msgs); + trace!("[msg::cli::matches] {:#?}", msgs); imap_conn.logout(); - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("search") { - debug!("Subcommand matched: search"); + debug!("[msg::cli::matches] search command matched"); + + let page_size: usize = matches + .value_of("page-size") + .and_then(|s| s.parse().ok()) + .unwrap_or(config.default_page_size(&account)); + debug!("[msg::cli::matches] page size: {}", &page_size); + let page: usize = matches + .value_of("page") + .unwrap() + .parse() + .unwrap_or_default(); + debug!("[msg::cli::matches] page: {}", &page); - let mut imap_conn = ImapConnector::new(&account)?; - let page_size: usize = matches.value_of("page-size").unwrap().parse().unwrap(); - debug!("Page size: {}", &page_size); - let page: usize = matches.value_of("page").unwrap().parse().unwrap(); - debug!("Page: {}", &page); let query = matches .values_of("query") .unwrap_or_default() @@ -221,27 +236,29 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { }) .1 .join(" "); - debug!("Query: {}", &query); + debug!("[msg::cli::matches] query: {}", &page); + let mut imap_conn = ImapConnector::new(&account)?; let msgs = imap_conn.search_msgs(&mbox, &query, &page_size, &page)?; let msgs = Msgs::from(&msgs); info!(&msgs); + trace!("[msg::cli::matches] {:#?}", msgs); imap_conn.logout(); - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("read") { - debug!("Subcommand matched: read"); + debug!("[msg::cli::matches] read command matched"); + + let uid = matches.value_of("uid").unwrap(); + debug!("[msg::cli::matches] uid: {}", uid); + let mime = format!("text/{}", matches.value_of("mime-type").unwrap()); + debug!("[msg::cli::matches] mime: {}", mime); + let raw = matches.is_present("raw"); + debug!("[msg::cli::matches] raw: {}", raw); let mut imap_conn = ImapConnector::new(&account)?; - let uid = matches.value_of("uid").unwrap(); - debug!("UID: {}", &uid); - let mime = format!("text/{}", matches.value_of("mime-type").unwrap()); - debug!("MIME: {}", &mime); - let raw = matches.is_present("raw"); - debug!("Raw: {}", &raw); - let msg = imap_conn.read_msg(&mbox, &uid)?; if raw { let msg = String::from_utf8(msg) @@ -254,26 +271,26 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { } imap_conn.logout(); - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("attachments") { - debug!("[msg::cli] subcommand matched: attachments"); + debug!("[msg::cli::matches] attachments command matched"); + + let uid = matches.value_of("uid").unwrap(); + debug!("[msg::cli::matches] uid: {}", &uid); let mut imap_conn = ImapConnector::new(&account)?; - let uid = matches.value_of("uid").unwrap(); - debug!("[msg::cli] uid: {}", &uid); - let msg = imap_conn.read_msg(&mbox, &uid)?; let attachments = Attachments::from_bytes(&msg)?; debug!( - "[msg::cli] {} attachment(s) found for message {}", + "[msg::cli::matches] {} attachment(s) found for message {}", &attachments.0.len(), &uid ); for attachment in attachments.0.iter() { let filepath = config.downloads_filepath(&account, &attachment.filename); - debug!("[msg::cli] downloading {}…", &attachment.filename); + debug!("[msg::cli::matches] downloading {}…", &attachment.filename); fs::write(&filepath, &attachment.raw) .chain_err(|| format!("Could not save attachment {:?}", filepath))?; } @@ -283,11 +300,11 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { )); imap_conn.logout(); - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("write") { - debug!("Subcommand matched: write"); + debug!("[msg::cli::matches] write command matched"); let mut imap_conn = ImapConnector::new(&account)?; let attachments = matches @@ -304,7 +321,7 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { match input::post_edit_choice() { Ok(choice) => match choice { input::PostEditChoice::Send => { - debug!("Sending message…"); + debug!("[msg::cli::matches] sending message…"); let msg = msg.to_sendable_msg()?; smtp::send(&account, &msg)?; imap_conn.append_msg("Sent", &msg.formatted(), &[Flag::Seen])?; @@ -318,7 +335,7 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { } input::PostEditChoice::LocalDraft => break, input::PostEditChoice::RemoteDraft => { - debug!("Saving to draft…"); + debug!("[msg::cli::matches] saving to draft…"); imap_conn.append_msg("Drafts", &msg.to_vec()?, &[Flag::Seen])?; input::remove_draft()?; info!("Message successfully saved to Drafts"); @@ -333,26 +350,26 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { } } imap_conn.logout(); - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("template") { - debug!("Subcommand matched: template"); + debug!("[msg::cli::matches] template command matched"); if let Some(_) = matches.subcommand_matches("new") { - debug!("Subcommand matched: new"); - + debug!("[msg::cli::matches] new command matched"); let tpl = Msg::build_new_tpl(&config, &account)?; info!(&tpl); + trace!("[msg::cli::matches] tpl: {:#?}", tpl); } if let Some(matches) = matches.subcommand_matches("reply") { - debug!("Subcommand matched: reply"); + debug!("[msg::cli::matches] reply command matched"); + + let uid = matches.value_of("uid").unwrap(); + debug!("[msg::cli::matches] uid: {}", uid); let mut imap_conn = ImapConnector::new(&account)?; - let uid = matches.value_of("uid").unwrap(); - debug!("UID: {}", &uid); - let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?); let tpl = if matches.is_present("reply-all") { msg.build_reply_all_tpl(&config, &account)? @@ -360,39 +377,46 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { msg.build_reply_tpl(&config, &account)? }; info!(&tpl); + trace!("[msg::cli::matches] tpl: {:#?}", tpl); imap_conn.logout(); } if let Some(matches) = matches.subcommand_matches("forward") { - debug!("Subcommand matched: forward"); + debug!("[msg::cli::matches] forward command matched"); + + let uid = matches.value_of("uid").unwrap(); + debug!("[msg::cli::matches] uid: {}", uid); let mut imap_conn = ImapConnector::new(&account)?; - let uid = matches.value_of("uid").unwrap(); - debug!("UID: {}", &uid); - let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?); let tpl = msg.build_forward_tpl(&config, &account)?; info!(&tpl); + trace!("[msg::cli::matches] tpl: {:#?}", tpl); imap_conn.logout(); } - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("reply") { - debug!("Subcommand matched: reply"); + debug!("[msg::cli::matches] reply command matched"); - let mut imap_conn = ImapConnector::new(&account)?; + let uid = matches.value_of("uid").unwrap(); + debug!("[msg::cli::matches] uid: {}", uid); let attachments = matches .values_of("attachments") .unwrap_or_default() .map(String::from) .collect::>(); - let uid = matches.value_of("uid").unwrap(); - debug!("UID: {}", &uid); + debug!( + "[msg::cli::matches] found {} attachments", + attachments.len() + ); + trace!("[msg::cli::matches] {:#?}", attachments); + let mut imap_conn = ImapConnector::new(&account)?; let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?); let tpl = if matches.is_present("reply-all") { msg.build_reply_all_tpl(&config, &account)? @@ -408,11 +432,11 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { match input::post_edit_choice() { Ok(choice) => match choice { input::PostEditChoice::Send => { - debug!("Sending message…"); + debug!("[msg::cli::matches] sending message…"); let msg = msg.to_sendable_msg()?; smtp::send(&account, &msg)?; imap_conn.append_msg("Sent", &msg.formatted(), &[Flag::Seen])?; - imap_conn.add_flags(mbox, uid, "\\Answered")?; + imap_conn.add_flags(&mbox, uid, "\\Answered")?; input::remove_draft()?; info!("Message successfully sent"); break; @@ -423,7 +447,7 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { } input::PostEditChoice::LocalDraft => break, input::PostEditChoice::RemoteDraft => { - debug!("Saving to draft…"); + debug!("[msg::cli::matches] saving to draft…"); imap_conn.append_msg("Drafts", &msg.to_vec()?, &[Flag::Seen])?; input::remove_draft()?; info!("Message successfully saved to Drafts"); @@ -439,21 +463,26 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { } imap_conn.logout(); - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("forward") { - debug!("Subcommand matched: forward"); + debug!("[msg::cli::matches] forward command matched"); - let mut imap_conn = ImapConnector::new(&account)?; + let uid = matches.value_of("uid").unwrap(); + debug!("[msg::cli::matches] uid: {}", uid); let attachments = matches .values_of("attachments") .unwrap_or_default() .map(String::from) .collect::>(); - let uid = matches.value_of("uid").unwrap(); - debug!("UID: {}", &uid); + debug!( + "[msg::cli::matches] found {} attachments", + attachments.len() + ); + trace!("[msg::cli::matches] {:#?}", attachments); + let mut imap_conn = ImapConnector::new(&account)?; let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?); let tpl = msg.build_forward_tpl(&config, &account)?; let content = input::open_editor_with_tpl(&tpl.to_string().as_bytes())?; @@ -464,7 +493,7 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { match input::post_edit_choice() { Ok(choice) => match choice { input::PostEditChoice::Send => { - debug!("Sending message…"); + debug!("[msg::cli::matches] sending message…"); let msg = msg.to_sendable_msg()?; smtp::send(&account, &msg)?; imap_conn.append_msg("Sent", &msg.formatted(), &[Flag::Seen])?; @@ -478,7 +507,7 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { } input::PostEditChoice::LocalDraft => break, input::PostEditChoice::RemoteDraft => { - debug!("Saving to draft…"); + debug!("[msg::cli::matches] saving to draft…"); imap_conn.append_msg("Drafts", &msg.to_vec()?, &[Flag::Seen])?; input::remove_draft()?; info!("Message successfully saved to Drafts"); @@ -494,18 +523,18 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { } imap_conn.logout(); - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("copy") { - debug!("Subcommand matched: copy"); + debug!("[msg::cli::matches] copy command matched"); + + let uid = matches.value_of("uid").unwrap(); + debug!("[msg::cli::matches] uid: {}", &uid); + let target = matches.value_of("target").unwrap(); + debug!("[msg::cli::matches] target: {}", &target); let mut imap_conn = ImapConnector::new(&account)?; - let uid = matches.value_of("uid").unwrap(); - debug!("UID: {}", &uid); - let target = matches.value_of("target").unwrap(); - debug!("Target: {}", &target); - let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?); let mut flags = msg.flags.deref().to_vec(); flags.push(Flag::Seen); @@ -516,50 +545,50 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { )); imap_conn.logout(); - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("move") { - debug!("Subcommand matched: move"); + debug!("[msg::cli::matches] move command matched"); + + let uid = matches.value_of("uid").unwrap(); + debug!("[msg::cli::matches] uid: {}", &uid); + let target = matches.value_of("target").unwrap(); + debug!("[msg::cli::matches] target: {}", &target); let mut imap_conn = ImapConnector::new(&account)?; - let uid = matches.value_of("uid").unwrap(); - debug!("UID: {}", &uid); - let target = matches.value_of("target").unwrap(); - debug!("Target: {}", &target); - let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?); let mut flags = msg.flags.deref().to_vec(); flags.push(Flag::Seen); imap_conn.append_msg(target, &msg.raw, msg.flags.deref())?; - imap_conn.add_flags(mbox, uid, "\\Seen \\Deleted")?; + imap_conn.add_flags(&mbox, uid, "\\Seen \\Deleted")?; info!(&format!( "Message {} successfully moved to folder `{}`", &uid, &target )); - imap_conn.expunge(mbox)?; + imap_conn.expunge(&mbox)?; imap_conn.logout(); - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("delete") { - debug!("Subcommand matched: delete"); + debug!("[msg::cli::matches] delete command matched"); + + let uid = matches.value_of("uid").unwrap(); + debug!("[msg::cli::matches] uid: {}", &uid); let mut imap_conn = ImapConnector::new(&account)?; - let uid = matches.value_of("uid").unwrap(); - debug!("UID: {}", &uid); - - imap_conn.add_flags(mbox, uid, "\\Seen \\Deleted")?; + imap_conn.add_flags(&mbox, uid, "\\Seen \\Deleted")?; info!(&format!("Message {} successfully deleted", &uid)); - imap_conn.expunge(mbox)?; + imap_conn.expunge(&mbox)?; imap_conn.logout(); - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("send") { - debug!("Subcommand matched: send"); + debug!("[msg::cli::matches] send command matched"); let mut imap_conn = ImapConnector::new(&account)?; let msg = matches.value_of("message").unwrap(); @@ -567,28 +596,32 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> { let msg = msg.to_sendable_msg()?; smtp::send(&account, &msg)?; imap_conn.append_msg("Sent", &msg.formatted(), &[Flag::Seen])?; + imap_conn.logout(); - return Ok(()); + return Ok(true); } if let Some(matches) = matches.subcommand_matches("save") { - debug!("Subcommand matched: save"); + debug!("[msg::cli::matches] save command matched"); let mut imap_conn = ImapConnector::new(&account)?; let msg = matches.value_of("message").unwrap(); let msg = Msg::from(msg.to_string()); - imap_conn.append_msg(mbox, &msg.to_vec()?, &[Flag::Seen])?; + imap_conn.append_msg(&mbox, &msg.to_vec()?, &[Flag::Seen])?; + imap_conn.logout(); - return Ok(()); + return Ok(true); } - debug!("Default subcommand matched: list"); + { + debug!("[msg::cli::matches] default list command matched"); - let mut imap_conn = ImapConnector::new(&account)?; - let msgs = imap_conn.list_msgs(&mbox, &10, &0)?; - let msgs = Msgs::from(&msgs); - info!(&msgs); + let mut imap_conn = ImapConnector::new(&account)?; + let msgs = imap_conn.list_msgs(&mbox, &config.default_page_size(&account), &0)?; + let msgs = Msgs::from(&msgs); + info!(&msgs); - imap_conn.logout(); - Ok(()) + imap_conn.logout(); + Ok(true) + } } diff --git a/wiki b/wiki index d4e2b28..b5f3d7a 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit d4e2b281658e1710168f18659955326f950e672c +Subproject commit b5f3d7ad36c5a77e37dff9c343b82dcb42d484be