Use structopt for command line parsing
parent
a17f0b4fd4
commit
4bc8ff2ce9
|
@ -1,5 +1,14 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
dependencies = [
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "0.4.7"
|
||||
|
@ -27,6 +36,17 @@ version = "0.5.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.0"
|
||||
|
@ -119,6 +139,21 @@ dependencies = [
|
|||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
|
@ -489,6 +524,15 @@ dependencies = [
|
|||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.13"
|
||||
|
@ -784,6 +828,7 @@ dependencies = [
|
|||
"signal-hook",
|
||||
"signal-hook-registry",
|
||||
"smallvec",
|
||||
"structopt",
|
||||
"termion",
|
||||
"toml",
|
||||
"unicode-segmentation",
|
||||
|
@ -1170,6 +1215,32 @@ version = "0.2.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn-mid",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.18"
|
||||
|
@ -1542,6 +1613,36 @@ version = "0.3.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "structopt"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"lazy_static",
|
||||
"structopt-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "structopt-derive"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.30"
|
||||
|
@ -1553,6 +1654,17 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn-mid"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.1.0"
|
||||
|
@ -1586,6 +1698,15 @@ dependencies = [
|
|||
"melib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.0.1"
|
||||
|
@ -1701,6 +1822,12 @@ version = "1.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
|
@ -1734,6 +1861,12 @@ version = "0.2.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55d1e41d56121e07f1e223db0a4def204e45c85425f6a16d462fd07c8d10d74c"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.2"
|
||||
|
|
|
@ -49,6 +49,8 @@ rmp-serde = "^0.14.0"
|
|||
smallvec = { version = "1.1.0", features = ["serde", ] }
|
||||
bitflags = "1.0"
|
||||
pcre2 = { version = "0.2.3", optional = true }
|
||||
structopt = { version = "0.3.14" }
|
||||
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
|
18
meli.1
18
meli.1
|
@ -27,28 +27,26 @@
|
|||
.Nm
|
||||
.Op Fl -help | h
|
||||
.Op Fl -version | v
|
||||
.Op Fl -create-config Op Ar path
|
||||
.Op Fl -test-config Op Ar path
|
||||
.Op Fl -config Ar path
|
||||
.Op Fl -print-default-theme
|
||||
.Op Fl -print-loaded-themes
|
||||
.Bl -tag -width flag -offset indent
|
||||
.It Fl -help | h
|
||||
Show help message and exit.
|
||||
.It Fl -version | v
|
||||
Show version and exit.
|
||||
.It Fl -create-config Op Ar path
|
||||
.It Fl -config Ar path
|
||||
Start meli with given configuration file.
|
||||
.It Cm create-config Op Ar path
|
||||
Create configuration file in
|
||||
.Pa path
|
||||
if given, or at
|
||||
.Pa $XDG_CONFIG_HOME/meli/config.toml
|
||||
.It Fl -test-config Op Ar path
|
||||
.It Cm test-config Op Ar path
|
||||
Test a configuration file for syntax issues or missing options.
|
||||
.It Fl -config Ar path
|
||||
Start meli with given configuration file.
|
||||
.It Fl -print-default-theme
|
||||
.It Cm man Op Ar page
|
||||
Print documentation page and exit (Piping to a pager is recommended.)
|
||||
.It Cm print-default-theme
|
||||
Print default theme keys and values in TOML syntax, to be used as a blueprint.
|
||||
.It Fl -print-loaded-themes
|
||||
.It Cm print-loaded-themes
|
||||
Print all loaded themes in TOML syntax.
|
||||
.El
|
||||
.Sh DESCRIPTION
|
||||
|
|
295
src/bin.rs
295
src/bin.rs
|
@ -29,7 +29,7 @@
|
|||
|
||||
use std::alloc::System;
|
||||
use std::collections::VecDeque;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
extern crate notify_rust;
|
||||
extern crate xdg_utils;
|
||||
#[macro_use]
|
||||
|
@ -86,8 +86,6 @@ pub mod plugins;
|
|||
use nix;
|
||||
use std::os::raw::c_int;
|
||||
|
||||
use xdg;
|
||||
|
||||
fn notify(
|
||||
signals: &[c_int],
|
||||
sender: crossbeam::channel::Sender<ThreadEvent>,
|
||||
|
@ -143,29 +141,75 @@ fn notify(
|
|||
Ok(r)
|
||||
}
|
||||
|
||||
macro_rules! error_and_exit {
|
||||
($($err:expr),*) => {{
|
||||
return Err(MeliError::new(format!($($err),*)));
|
||||
}}
|
||||
fn parse_manpage(src: &str) -> Result<ManPages> {
|
||||
match src {
|
||||
"" | "meli" | "main" => Ok(ManPages::Main),
|
||||
"meli.conf" | "conf" | "config" | "configuration" => Ok(ManPages::Conf),
|
||||
"meli-themes" | "themes" | "theming" | "theme" => Ok(ManPages::Themes),
|
||||
_ => Err(MeliError::new(format!(
|
||||
"Invalid documentation page: {}",
|
||||
src
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Choose manpage
|
||||
enum ManPages {
|
||||
/// meli(1)
|
||||
Main = 0,
|
||||
/// meli.conf(5)
|
||||
Conf = 1,
|
||||
/// meli-themes(5)
|
||||
Themes = 2,
|
||||
}
|
||||
|
||||
struct CommandLineArguments {
|
||||
print_manpage: Option<ManPages>,
|
||||
create_config: Option<String>,
|
||||
test_config: Option<String>,
|
||||
config: Option<String>,
|
||||
help: bool,
|
||||
version: bool,
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(name = "meli", about = "terminal mail client", version_short = "v")]
|
||||
struct Opt {
|
||||
/// use specified configuration file
|
||||
#[structopt(short, long, parse(from_os_str))]
|
||||
config: Option<PathBuf>,
|
||||
|
||||
#[structopt(subcommand)]
|
||||
subcommand: Option<SubCommand>,
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
enum SubCommand {
|
||||
/// print default theme in full to stdout and exit.
|
||||
PrintDefaultTheme,
|
||||
/// print loaded themes in full to stdout and exit.
|
||||
PrintLoadedThemes,
|
||||
/// create 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.toml
|
||||
#[structopt(display_order = 1)]
|
||||
CreateConfig {
|
||||
#[structopt(value_name = "NEW_CONFIG_PATH", parse(from_os_str))]
|
||||
path: Option<PathBuf>,
|
||||
},
|
||||
/// test a configuration file for syntax issues or missing options.
|
||||
#[structopt(display_order = 2)]
|
||||
TestConfig {
|
||||
#[structopt(value_name = "CONFIG_PATH", parse(from_os_str))]
|
||||
path: Option<PathBuf>,
|
||||
},
|
||||
#[structopt(visible_alias="docs", aliases=&["docs", "manpage", "manpages"])]
|
||||
#[structopt(display_order = 3)]
|
||||
/// print documentation page and exit (Piping to a pager is recommended.).
|
||||
Man(ManOpt),
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
struct ManOpt {
|
||||
#[structopt(default_value = "meli", possible_values=&["meli", "conf", "themes"], value_name="PAGE", parse(try_from_str = parse_manpage))]
|
||||
page: ManPages,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
::std::process::exit(match run_app() {
|
||||
let opt = Opt::from_args();
|
||||
::std::process::exit(match run_app(opt) {
|
||||
Ok(()) => 0,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
|
@ -174,184 +218,39 @@ fn main() {
|
|||
});
|
||||
}
|
||||
|
||||
fn run_app() -> Result<()> {
|
||||
enum CommandLineFlags {
|
||||
PrintManPage,
|
||||
CreateConfig,
|
||||
TestConfig,
|
||||
Config,
|
||||
fn run_app(opt: Opt) -> Result<()> {
|
||||
if let Some(config_location) = opt.config.as_ref() {
|
||||
std::env::set_var("MELI_CONFIG", config_location);
|
||||
}
|
||||
use CommandLineFlags::*;
|
||||
let mut prev: Option<CommandLineFlags> = None;
|
||||
let mut args = CommandLineArguments {
|
||||
print_manpage: None,
|
||||
create_config: None,
|
||||
test_config: None,
|
||||
config: None,
|
||||
help: false,
|
||||
version: false,
|
||||
};
|
||||
|
||||
for i in std::env::args().skip(1) {
|
||||
match i.as_str() {
|
||||
"--test-config" => match prev {
|
||||
None => prev = Some(TestConfig),
|
||||
Some(CreateConfig) => error_and_exit!("invalid value for flag `--create-config`"),
|
||||
Some(Config) => error_and_exit!("invalid value for flag `--config`"),
|
||||
Some(TestConfig) => error_and_exit!("invalid value for flag `--test-config`"),
|
||||
Some(PrintManPage) => {
|
||||
error_and_exit!("invalid value for flag `--print-documentation`")
|
||||
}
|
||||
},
|
||||
"--create-config" => match prev {
|
||||
None => prev = Some(CreateConfig),
|
||||
Some(CreateConfig) => error_and_exit!("invalid value for flag `--create-config`"),
|
||||
Some(TestConfig) => error_and_exit!("invalid value for flag `--test-config`"),
|
||||
Some(Config) => error_and_exit!("invalid value for flag `--config`"),
|
||||
Some(PrintManPage) => {
|
||||
error_and_exit!("invalid value for flag `--print-documentation`")
|
||||
}
|
||||
},
|
||||
"--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!("invalid value for flag `--create-config`"),
|
||||
Some(Config) => error_and_exit!("invalid value for flag `--config`"),
|
||||
Some(TestConfig) => error_and_exit!("invalid value for flag `--test-config`"),
|
||||
Some(PrintManPage) => {
|
||||
error_and_exit!("invalid value for flag `--print-documentation`")
|
||||
}
|
||||
},
|
||||
"--help" | "-h" => {
|
||||
args.help = true;
|
||||
}
|
||||
"--version" | "-v" => {
|
||||
args.version = true;
|
||||
}
|
||||
"--print-loaded-themes" => {
|
||||
let s = conf::FileSettings::new()?;
|
||||
print!("{}", s.terminal.themes.to_string());
|
||||
return Ok(());
|
||||
}
|
||||
"--print-default-theme" => {
|
||||
print!("{}", conf::Themes::default().key_to_string("dark", false));
|
||||
return Ok(());
|
||||
}
|
||||
"--print-documentation" => {
|
||||
if args.print_manpage.is_some() {
|
||||
error_and_exit!("Multiple invocations of --print-documentation");
|
||||
}
|
||||
prev = Some(PrintManPage);
|
||||
args.print_manpage = Some(ManPages::Main);
|
||||
}
|
||||
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(TestConfig) if args.test_config.is_none() => {
|
||||
args.test_config = Some(i);
|
||||
prev = None;
|
||||
}
|
||||
Some(PrintManPage) => {
|
||||
match e {
|
||||
"meli" | "main" => { /* This is the default */ }
|
||||
"meli.conf" | "conf" | "config" | "configuration" => {
|
||||
args.print_manpage = Some(ManPages::Conf);
|
||||
}
|
||||
"meli-themes" | "themes" | "theming" | "theme" => {
|
||||
args.print_manpage = Some(ManPages::Themes);
|
||||
}
|
||||
_ => error_and_exit!("Invalid documentation page: {}", e),
|
||||
}
|
||||
}
|
||||
Some(TestConfig) => error_and_exit!("Duplicate value for flag `--test-config`"),
|
||||
Some(CreateConfig) => error_and_exit!("Duplicate value for flag `--create-config`"),
|
||||
Some(Config) => error_and_exit!("Duplicate value for flag `--config`"),
|
||||
},
|
||||
match opt.subcommand {
|
||||
Some(SubCommand::TestConfig { path }) => {
|
||||
let config_path = if let Some(path) = path {
|
||||
path
|
||||
} else {
|
||||
crate::conf::get_config_file()?
|
||||
};
|
||||
conf::FileSettings::validate(config_path)?;
|
||||
return Ok(());
|
||||
}
|
||||
Some(SubCommand::CreateConfig { path }) => {
|
||||
let config_path = if let Some(path) = path {
|
||||
path
|
||||
} else {
|
||||
crate::conf::get_config_file()?
|
||||
};
|
||||
if config_path.exists() {
|
||||
return Err(MeliError::new(format!(
|
||||
"File `{}` already exists.\nMaybe you meant to specify another path?",
|
||||
config_path.display()
|
||||
)));
|
||||
}
|
||||
conf::create_config_file(&config_path)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
if args.help {
|
||||
println!("usage:\tmeli [--config PATH|-c PATH]");
|
||||
println!("\tmeli --help");
|
||||
println!("\tmeli --version");
|
||||
println!("");
|
||||
println!("Other options:");
|
||||
println!("\t--help, -h\t\tshow this message and exit");
|
||||
println!("\t--version, -v\t\tprint version 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.toml");
|
||||
println!(
|
||||
"\t--test-config PATH\ttest a configuration file for syntax issues or missing options."
|
||||
);
|
||||
println!("\t--config PATH, -c PATH\tuse specified configuration file");
|
||||
println!("\t--print-loaded-themes\tprint loaded themes in full to stdout and exit.");
|
||||
println!("\t--print-default-theme\tprint default theme in full to stdout and exit.");
|
||||
#[cfg(feature = "cli-docs")]
|
||||
{
|
||||
println!("\t--print-documentation [meli conf themes]\n\t\t\t\tprint documentation page and exit (Piping to a pager is recommended.).");
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if args.version {
|
||||
println!("meli {}", option_env!("CARGO_PKG_VERSION").unwrap_or("0.0"));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
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`"),
|
||||
Some(TestConfig) => error_and_exit!("error: flag without value: `--test-config`"),
|
||||
Some(PrintManPage) => {}
|
||||
};
|
||||
|
||||
if (args.print_manpage.is_some()
|
||||
^ args.test_config.is_some()
|
||||
^ args.create_config.is_some()
|
||||
^ args.config.is_some())
|
||||
&& !(args.print_manpage.is_some()
|
||||
|| args.test_config.is_some()
|
||||
|| args.create_config.is_some()
|
||||
|| args.config.is_some())
|
||||
{
|
||||
error_and_exit!("error: illegal command-line flag combination");
|
||||
}
|
||||
|
||||
if let Some(config_path) = args.test_config.as_ref() {
|
||||
conf::FileSettings::validate(config_path)?;
|
||||
return Ok(());
|
||||
} else 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.toml").map_err(|e| {
|
||||
MeliError::new(format!(
|
||||
"Cannot create configuration directory in {}:\n{}",
|
||||
xdg_dirs.get_config_home().display(),
|
||||
e
|
||||
))
|
||||
})?
|
||||
} else {
|
||||
Path::new(config_path).to_path_buf()
|
||||
};
|
||||
if config_path.exists() {
|
||||
return Err(MeliError::new(format!("File `{}` already exists.\nMaybe you meant to specify another path with --create-config=PATH", config_path.display())));
|
||||
}
|
||||
conf::create_config_file(&config_path)?;
|
||||
return Ok(());
|
||||
} else if let Some(_page) = args.print_manpage {
|
||||
#[cfg(feature = "cli-docs")]
|
||||
{
|
||||
Some(SubCommand::Man(manopt)) => {
|
||||
let _page = manopt.page;
|
||||
const MANPAGES: [&'static str; 3] = [
|
||||
include_str!(concat!(env!("OUT_DIR"), "/meli.txt")),
|
||||
include_str!(concat!(env!("OUT_DIR"), "/meli.conf.txt")),
|
||||
|
@ -361,13 +260,19 @@ fn run_app() -> Result<()> {
|
|||
return Ok(());
|
||||
}
|
||||
#[cfg(not(feature = "cli-docs"))]
|
||||
{
|
||||
error_and_exit!("error: this version of meli was not build with embedded documentation. You might have it installed as manpages (eg `man meli`), otherwise check https://meli.delivery");
|
||||
Some(SubCommand::Man(_manopt)) => {
|
||||
return Err(MeliError::new("error: this version of meli was not build with embedded documentation. You might have it installed as manpages (eg `man meli`), otherwise check https://meli.delivery"));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(config_location) = args.config.as_ref() {
|
||||
std::env::set_var("MELI_CONFIG", config_location);
|
||||
Some(SubCommand::PrintLoadedThemes) => {
|
||||
let s = conf::FileSettings::new()?;
|
||||
print!("{}", s.terminal.themes.to_string());
|
||||
return Ok(());
|
||||
}
|
||||
Some(SubCommand::PrintDefaultTheme) => {
|
||||
print!("{}", conf::Themes::default().key_to_string("dark", false));
|
||||
return Ok(());
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
/* Create a channel to communicate with other threads. The main process is the sole receiver.
|
||||
|
|
42
src/conf.rs
42
src/conf.rs
|
@ -313,17 +313,30 @@ pub struct Settings {
|
|||
pub log: LogSettings,
|
||||
}
|
||||
|
||||
pub fn get_config_file() -> Result<PathBuf> {
|
||||
let xdg_dirs = xdg::BaseDirectories::with_prefix("meli").map_err(|err| {
|
||||
MeliError::new(format!(
|
||||
"Could not detect XDG directories for user: {}",
|
||||
err
|
||||
))
|
||||
.set_source(Some(std::sync::Arc::new(Box::new(err))))
|
||||
})?;
|
||||
match env::var("MELI_CONFIG") {
|
||||
Ok(path) => Ok(PathBuf::from(path)),
|
||||
Err(_) => Ok(xdg_dirs
|
||||
.place_config_file("config.toml")
|
||||
.chain_err_summary(|| {
|
||||
format!(
|
||||
"Cannot create configuration directory in {}",
|
||||
xdg_dirs.get_config_home().display()
|
||||
)
|
||||
})?),
|
||||
}
|
||||
}
|
||||
|
||||
impl FileSettings {
|
||||
pub fn new() -> Result<FileSettings> {
|
||||
let xdg_dirs = xdg::BaseDirectories::with_prefix("meli");
|
||||
let config_path = match env::var("MELI_CONFIG") {
|
||||
Ok(path) => PathBuf::from(path),
|
||||
Err(_) => xdg_dirs
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.place_config_file("config.toml")
|
||||
.expect("cannot create configuration directory"),
|
||||
};
|
||||
let config_path = get_config_file()?;
|
||||
if !config_path.exists() {
|
||||
println!(
|
||||
"No configuration found. Would you like to generate one in {}? [Y/n]",
|
||||
|
@ -359,18 +372,15 @@ impl FileSettings {
|
|||
}
|
||||
}
|
||||
|
||||
let path = config_path
|
||||
.to_str()
|
||||
.expect("Configuration file path was not valid UTF-8");
|
||||
FileSettings::validate(path)
|
||||
FileSettings::validate(config_path)
|
||||
}
|
||||
|
||||
pub fn validate(path: &str) -> Result<Self> {
|
||||
let s = pp::pp(path)?;
|
||||
pub fn validate(path: PathBuf) -> Result<Self> {
|
||||
let s = pp::pp(&path)?;
|
||||
let mut s: FileSettings = toml::from_str(&s).map_err(|e| {
|
||||
MeliError::new(format!(
|
||||
"{}:\nConfig file contains errors: {}",
|
||||
path,
|
||||
path.display(),
|
||||
e.to_string()
|
||||
))
|
||||
})?;
|
||||
|
|
Loading…
Reference in New Issue