summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2019-07-11 11:45:09 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2019-07-29 20:22:34 +0300
commitdf5559023d48bf5e0b92bbb1f1b81f106d0d8dd1 (patch)
treecfc6db6577ec27522743915933e4f8ebde7ccc09
parent38da6c83b9e8e9b0b2e27020e61e6cb086bacc22 (diff)
add --help, --config, --create-config arguments
-rw-r--r--Cargo.toml1
-rw-r--r--src/bin.rs116
2 files changed, 110 insertions, 7 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 7060d7f6..308882dd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,6 +9,7 @@ name = "meli"
path = "src/bin.rs"
[dependencies]
+xdg = "2.1.0"
chan = "0.1.21"
chan-signal = "0.3.1"
nix = "*"
diff --git a/src/bin.rs b/src/bin.rs
index e94f6901..ebbe5a75 100644
--- a/src/bin.rs
+++ b/src/bin.rs
@@ -25,6 +25,8 @@ The mail handling stuff is done in the `melib` crate which includes all backend
*/
use std::alloc::System;
+use std::io::Write;
+use std::path::{Path, PathBuf};
#[global_allocator]
static GLOBAL: System = System;
@@ -41,15 +43,115 @@ use chan_signal;
use chan_signal::Signal;
use nix;
+use xdg;
+
+macro_rules! error_and_exit {
+ ($($err:expr),*) => {{
+ println!($($err),*);
+ std::process::exit(1);
+ }}
+}
+
+#[derive(Debug)]
+struct CommandLineArguments {
+ create_config: Option<String>,
+ config: Option<String>,
+ help: bool,
+}
fn main() {
- /* Lock all stdio outs */
- //let _stdout = stdout();
- //let mut _stdout = _stdout.lock();
- /*
- let _stderr = stderr();
- let mut _stderr = _stderr.lock();
- */
+ enum CommandLineFlags {
+ CreateConfig,
+ Config,
+ }
+ use CommandLineFlags::*;
+ let mut prev: Option<CommandLineFlags> = None;
+ let mut args = CommandLineArguments {
+ create_config: None,
+ config: None,
+ help: false,
+ };
+
+ for i in std::env::args().skip(1) {
+ match i.as_str() {
+ "--create-config" => match prev {
+ None => prev = Some(CreateConfig),
+ Some(CreateConfig) => error_and_exit!("invalid value for flag `--create-config`"),
+ Some(Config) => error_and_exit!("invalid value for flag `--config`"),
+ },
+ "--config" | "-c" => match prev {
+ None => prev = Some(Config),
+ Some(CreateConfig) if args.create_config.is_none() => {
+ args.config = Some(String::new());
+ prev = Some(Config);
+ }
+ Some(CreateConfig) => error_and_exit!("Duplicate value for flag `--create-config`"),
+ Some(Config) => error_and_exit!("invalid value for flag `--config`"),
+ },
+ "--help" | "-h" => match prev {
+ Some(_) => {}
+ None => args.help = true,
+ },
+ e => match prev {
+ None => error_and_exit!("error: value without command {}", e),
+ Some(CreateConfig) if args.create_config.is_none() => {
+ args.create_config = Some(i);
+ prev = None;
+ }
+ Some(Config) if args.config.is_none() => {
+ args.config = Some(i);
+ prev = None;
+ }
+ Some(CreateConfig) => error_and_exit!("Duplicate value for flag `--create-config`"),
+ Some(Config) => error_and_exit!("Duplicate value for flag `--config`"),
+ },
+ }
+ }
+
+ if args.help {
+ println!("usage:\tmeli [--create-config[ PATH]] [--config[ PATH]|-c[ PATH]]");
+ println!("\tmeli --help");
+ println!("");
+ println!("\t--help\t\t\tshow this message and exit");
+ println!("\t--create-config[ PATH]\tCreate a sample configuration file with available configuration options. If PATH is not specified, meli will try to create it in $XDG_CONFIG_HOME/meli/config");
+ println!("\t--config PATH, -c PATH\tUse specified configuration file");
+ std::process::exit(0);
+ }
+
+ match prev {
+ None => {}
+ Some(CreateConfig) if args.create_config.is_none() => args.create_config = Some("".into()),
+ Some(CreateConfig) => error_and_exit!("Duplicate value for flag `--create-config`"),
+ Some(Config) => error_and_exit!("error: flag without value: --config"),
+ };
+
+ if let Some(config_path) = args.create_config.as_mut() {
+ let config_path: PathBuf = if config_path.is_empty() {
+ let xdg_dirs = xdg::BaseDirectories::with_prefix("meli").unwrap();
+ xdg_dirs.place_config_file("config").unwrap_or_else(|e| {
+ error_and_exit!("Cannot create configuration directory:\n{}", e)
+ })
+ } else {
+ Path::new(config_path).to_path_buf()
+ };
+ if config_path.exists() {
+ println!("File `{}` already exists.\nMaybe you meant to specify another path with --create-config=PATH", config_path.display());
+ std::process::exit(1);
+ }
+ let mut file = std::fs::OpenOptions::new()
+ .write(true)
+ .create_new(true)
+ .open(config_path.as_path())
+ .unwrap_or_else(|e| error_and_exit!("Could not create config file:\n{}", e));
+ file.write_all(include_bytes!("../sample-config"))
+ .unwrap_or_else(|e| error_and_exit!("Could not write to config file:\n{}", e));
+ println!("Written example configuration to {}", config_path.display());
+ std::process::exit(0);
+ }
+
+ if let Some(config_location) = args.config.as_ref() {
+ std::env::set_var("MELI_CONFIG", config_location);
+ }
/* Catch SIGWINCH to handle terminal resizing */
let signal = chan_signal::notify(&[Signal::WINCH]);