add custom config path (#86)

This commit is contained in:
Clément DOUIN 2021-04-17 23:19:34 +02:00
parent 3e0d1f704d
commit 95b99c25da
No known key found for this signature in database
GPG key ID: 69C9B9CFFDEE2DEF
10 changed files with 44 additions and 32 deletions

View file

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Default page size to config [#96] - Default page size to config [#96]
- Custom config path [#86]
## [0.2.6] - 2021-04-17 ## [0.2.6] - 2021-04-17
@ -182,6 +183,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#79]: https://github.com/soywod/himalaya/issues/79 [#79]: https://github.com/soywod/himalaya/issues/79
[#83]: https://github.com/soywod/himalaya/issues/83 [#83]: https://github.com/soywod/himalaya/issues/83
[#84]: https://github.com/soywod/himalaya/issues/84 [#84]: https://github.com/soywod/himalaya/issues/84
[#86]: https://github.com/soywod/himalaya/issues/86
[#87]: https://github.com/soywod/himalaya/issues/87 [#87]: https://github.com/soywod/himalaya/issues/87
[#89]: https://github.com/soywod/himalaya/issues/89 [#89]: https://github.com/soywod/himalaya/issues/89
[#96]: https://github.com/soywod/himalaya/issues/96 [#96]: https://github.com/soywod/himalaya/issues/96

View file

@ -5,7 +5,7 @@ use std::io;
error_chain! {} error_chain! {}
pub fn completion_subcmds<'c>() -> Vec<App<'c, 'c>> { pub fn comp_subcmds<'s>() -> Vec<App<'s, 's>> {
vec![SubCommand::with_name("completion") vec![SubCommand::with_name("completion")
.about("Generates the completion script for the given shell") .about("Generates the completion script for the given shell")
.args(&[Arg::with_name("shell") .args(&[Arg::with_name("shell")
@ -13,19 +13,19 @@ pub fn completion_subcmds<'c>() -> Vec<App<'c, 'c>> {
.required(true)])] .required(true)])]
} }
pub fn completion_matches(mut app: App, matches: &ArgMatches) -> Result<bool> { pub fn comp_matches(mut app: App, matches: &ArgMatches) -> Result<bool> {
if let Some(matches) = matches.subcommand_matches("completion") { if let Some(matches) = matches.subcommand_matches("completion") {
debug!("[completion::cli::matches] completion command matched"); debug!("[comp::cli::matches] completion command matched");
let shell = match matches.value_of("shell").unwrap() { let shell = match matches.value_of("shell").unwrap() {
"fish" => Shell::Fish, "fish" => Shell::Fish,
"zsh" => Shell::Zsh, "zsh" => Shell::Zsh,
"bash" | _ => Shell::Bash, "bash" | _ => Shell::Bash,
}; };
debug!("[completion::cli::matches] shell: {}", shell); debug!("[comp::cli::matches] shell: {}", shell);
app.gen_completions_to("himalaya", shell, &mut io::stdout()); app.gen_completions_to("himalaya", shell, &mut io::stdout());
return Ok(true); return Ok(true);
}; };
debug!("[completion::cli::matches] nothing matched"); debug!("[comp::cli::matches] nothing matched");
Ok(false) Ok(false)
} }

View file

@ -1,9 +1,16 @@
use clap::Arg; use clap::Arg;
pub fn account_arg<'a>() -> Arg<'a, 'a> { pub fn config_args<'a>() -> Vec<Arg<'a, 'a>> {
vec![
Arg::with_name("config")
.long("config")
.short("c")
.help("Forces a specific config path")
.value_name("PATH"),
Arg::with_name("account") Arg::with_name("account")
.long("account") .long("account")
.short("a") .short("a")
.help("Selects a specific account") .help("Selects a specific account")
.value_name("STRING") .value_name("NAME"),
]
} }

View file

@ -132,15 +132,16 @@ impl Config {
Ok(path) Ok(path)
} }
pub fn new_from_file() -> Result<Self> { pub fn new(path: Option<PathBuf>) -> Result<Self> {
let mut file = File::open( let path = match path {
Self::path_from_xdg() Some(path) => path,
None => Self::path_from_xdg()
.or_else(|_| Self::path_from_xdg_alt()) .or_else(|_| Self::path_from_xdg_alt())
.or_else(|_| Self::path_from_home()) .or_else(|_| Self::path_from_home())
.chain_err(|| "Cannot find config path")?, .chain_err(|| "Cannot find config path")?,
) };
.chain_err(|| "Cannot open config file")?;
let mut file = File::open(path).chain_err(|| "Cannot open config file")?;
let mut content = vec![]; let mut content = vec![];
file.read_to_end(&mut content) file.read_to_end(&mut content)
.chain_err(|| "Cannot read config file")?; .chain_err(|| "Cannot read config file")?;

View file

@ -11,7 +11,7 @@ error_chain! {
} }
} }
fn flags_arg<'f>() -> Arg<'f, 'f> { fn flags_arg<'a>() -> Arg<'a, 'a> {
Arg::with_name("flags") Arg::with_name("flags")
.help("IMAP flags (see https://tools.ietf.org/html/rfc3501#page-11)") .help("IMAP flags (see https://tools.ietf.org/html/rfc3501#page-11)")
.value_name("FLAGS…") .value_name("FLAGS…")
@ -19,7 +19,7 @@ fn flags_arg<'f>() -> Arg<'f, 'f> {
.required(true) .required(true)
} }
pub fn flag_subcmds<'f>() -> Vec<App<'f, 'f>> { pub fn flag_subcmds<'s>() -> Vec<App<'s, 's>> {
vec![SubCommand::with_name("flags") vec![SubCommand::with_name("flags")
.aliases(&["flag"]) .aliases(&["flag"])
.about("Handles flags") .about("Handles flags")

View file

@ -14,7 +14,7 @@ error_chain! {
} }
} }
pub fn imap_subcmds<'a>() -> Vec<App<'a, 'a>> { pub fn imap_subcmds<'s>() -> Vec<App<'s, 's>> {
vec![SubCommand::with_name("idle").about("Spawns a blocking idle daemon")] vec![SubCommand::with_name("idle").about("Spawns a blocking idle daemon")]
} }

View file

@ -1,7 +1,7 @@
use clap; use clap;
use error_chain::error_chain; use error_chain::error_chain;
use log::{debug, error, trace}; use log::{debug, error, trace};
use std::env; use std::{env, path::PathBuf};
mod input; mod input;
mod smtp; mod smtp;
@ -32,13 +32,13 @@ mod mbox {
pub(crate) mod cli; pub(crate) mod cli;
pub(crate) mod model; pub(crate) mod model;
} }
mod completion { mod comp {
pub(crate) mod cli; pub(crate) mod cli;
} }
use crate::{ use crate::{
completion::cli::{completion_matches, completion_subcmds}, comp::cli::{comp_matches, comp_subcmds},
config::{cli::account_arg, model::Config}, config::{cli::config_args, model::Config},
flag::cli::{flag_matches, flag_subcmds}, flag::cli::{flag_matches, flag_subcmds},
imap::cli::{imap_matches, imap_subcmds}, imap::cli::{imap_matches, imap_subcmds},
mbox::cli::{mbox_matches, mbox_source_arg, mbox_subcmds}, mbox::cli::{mbox_matches, mbox_source_arg, mbox_subcmds},
@ -52,7 +52,7 @@ use crate::{
error_chain! { error_chain! {
links { links {
CompletionCli(crate::completion::cli::Error, crate::completion::cli::ErrorKind); CompletionCli(crate::comp::cli::Error, crate::comp::cli::ErrorKind);
Config(crate::config::model::Error, crate::config::model::ErrorKind); Config(crate::config::model::Error, crate::config::model::ErrorKind);
FlagCli(crate::flag::cli::Error, crate::flag::cli::ErrorKind); FlagCli(crate::flag::cli::Error, crate::flag::cli::ErrorKind);
ImapCli(crate::imap::cli::Error, crate::imap::cli::ErrorKind); ImapCli(crate::imap::cli::Error, crate::imap::cli::ErrorKind);
@ -68,13 +68,13 @@ fn build_app<'a>() -> clap::App<'a, 'a> {
.about(env!("CARGO_PKG_DESCRIPTION")) .about(env!("CARGO_PKG_DESCRIPTION"))
.author(env!("CARGO_PKG_AUTHORS")) .author(env!("CARGO_PKG_AUTHORS"))
.args(&output_args()) .args(&output_args())
.arg(account_arg()) .args(&config_args())
.arg(mbox_source_arg()) .arg(mbox_source_arg())
.subcommands(flag_subcmds()) .subcommands(flag_subcmds())
.subcommands(imap_subcmds()) .subcommands(imap_subcmds())
.subcommands(mbox_subcmds()) .subcommands(mbox_subcmds())
.subcommands(msg_subcmds()) .subcommands(msg_subcmds())
.subcommands(completion_subcmds()) .subcommands(comp_subcmds())
} }
fn run() -> Result<()> { fn run() -> Result<()> {
@ -83,12 +83,14 @@ fn run() -> Result<()> {
let output_fmt: OutputFmt = matches.value_of("output").unwrap().into(); let output_fmt: OutputFmt = matches.value_of("output").unwrap().into();
let log_level: LogLevel = matches.value_of("log").unwrap().into(); let log_level: LogLevel = matches.value_of("log").unwrap().into();
let custom_config: Option<PathBuf> = matches.value_of("config").map(|s| s.into());
init_logger(&output_fmt, &log_level)?; init_logger(&output_fmt, &log_level)?;
debug!("[main] output format: {}", output_fmt); debug!("[main] output format: {}", output_fmt);
debug!("[main] log level: {}", log_level); debug!("[main] log level: {}", log_level);
debug!("[main] custom config path: {:?}", custom_config);
debug!("[main] init config"); debug!("[main] init config");
let config = Config::new_from_file()?; let config = Config::new(custom_config)?;
trace!("[main] {:#?}", config); trace!("[main] {:#?}", config);
let account_name = matches.value_of("account"); let account_name = matches.value_of("account");
@ -97,13 +99,13 @@ fn run() -> Result<()> {
trace!("[main] {:#?}", account); trace!("[main] {:#?}", account);
let mbox = matches.value_of("mailbox").unwrap(); let mbox = matches.value_of("mailbox").unwrap();
debug!("[msg::cli::matches] mailbox: {}", mbox); debug!("[main] mailbox: {}", mbox);
debug!("[main] begin matching"); debug!("[main] begin matching");
let _matched = mbox_matches(&account, &matches)? let _matched = mbox_matches(&account, &matches)?
|| flag_matches(&account, &mbox, &matches)? || flag_matches(&account, &mbox, &matches)?
|| imap_matches(&config, &account, &mbox, &matches)? || imap_matches(&config, &account, &mbox, &matches)?
|| completion_matches(build_app(), &matches)? || comp_matches(build_app(), &matches)?
|| msg_matches(&config, &account, &mbox, &matches)?; || msg_matches(&config, &account, &mbox, &matches)?;
Ok(()) Ok(())

View file

@ -28,7 +28,7 @@ pub fn mbox_target_arg<'a>() -> Arg<'a, 'a> {
.value_name("TARGET") .value_name("TARGET")
} }
pub fn mbox_subcmds<'a>() -> Vec<App<'a, 'a>> { pub fn mbox_subcmds<'s>() -> Vec<App<'s, 's>> {
vec![SubCommand::with_name("mailboxes") vec![SubCommand::with_name("mailboxes")
.aliases(&["mailbox", "mboxes", "mbox", "m"]) .aliases(&["mailbox", "mboxes", "mbox", "m"])
.about("Lists all mailboxes")] .about("Lists all mailboxes")]

View file

@ -67,7 +67,7 @@ fn attachment_arg<'a>() -> Arg<'a, 'a> {
.takes_value(true) .takes_value(true)
} }
pub fn msg_subcmds<'a>() -> Vec<App<'a, 'a>> { pub fn msg_subcmds<'s>() -> Vec<App<'s, 's>> {
vec![ vec![
SubCommand::with_name("list") SubCommand::with_name("list")
.aliases(&["lst", "l"]) .aliases(&["lst", "l"])

2
wiki

@ -1 +1 @@
Subproject commit b5f3d7ad36c5a77e37dff9c343b82dcb42d484be Subproject commit fb38ee9b4ae679a01f73dd7d77f369a83dd888e5