refactor: move cli argument parsing to main
Command line arguments are part of the OS process and should be under main.
This commit is contained in:
committed by
Henrik Friedrichsen
parent
ae090b6073
commit
abffb3c2a9
@@ -1,7 +1,6 @@
|
|||||||
use crate::{command, ipc, mpris, queue, spotify};
|
use crate::{command, ipc, mpris, queue, spotify};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use cursive::event::EventTrigger;
|
use cursive::event::EventTrigger;
|
||||||
@@ -11,7 +10,6 @@ use librespot_core::authentication::Credentials;
|
|||||||
use librespot_core::cache::Cache;
|
use librespot_core::cache::Cache;
|
||||||
use log::{error, info, trace};
|
use log::{error, info, trace};
|
||||||
|
|
||||||
use ncspot::program_arguments;
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use signal_hook::{consts::SIGHUP, consts::SIGTERM, iterator::Signals};
|
use signal_hook::{consts::SIGHUP, consts::SIGTERM, iterator::Signals};
|
||||||
|
|
||||||
@@ -90,27 +88,33 @@ pub struct Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Application {
|
impl Application {
|
||||||
pub fn new() -> Result<Self, String> {
|
/// Create a new ncspot application.
|
||||||
let matches = program_arguments().get_matches();
|
///
|
||||||
|
/// # Arguments
|
||||||
if let Some(filename) = matches.get_one::<String>("debug") {
|
///
|
||||||
setup_logging(filename).expect("can't setup logging");
|
/// * `debug_log_path` - Path where an optional debug log should be written to
|
||||||
|
/// * `configuration_base_path` - Path to the configuration directory
|
||||||
|
/// * `configuration_file_path` - Relative path to the configuration file inside the base path
|
||||||
|
pub fn new(
|
||||||
|
debug_log_path: Option<PathBuf>,
|
||||||
|
configuration_base_path: Option<PathBuf>,
|
||||||
|
configuration_file_path: Option<PathBuf>,
|
||||||
|
) -> Result<Self, String> {
|
||||||
|
if let Some(filename) = debug_log_path {
|
||||||
|
setup_logging(&filename.to_string_lossy()).expect("can't setup logging");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(basepath) = matches.get_one::<String>("basepath") {
|
if let Some(basepath) = configuration_base_path {
|
||||||
let path = PathBuf::from_str(basepath).expect("invalid path");
|
if !basepath.exists() {
|
||||||
if !path.exists() {
|
fs::create_dir_all(&basepath).expect("could not create basepath directory");
|
||||||
fs::create_dir_all(&path).expect("could not create basepath directory");
|
|
||||||
}
|
}
|
||||||
*config::BASE_PATH.write().unwrap() = Some(path);
|
*config::BASE_PATH.write().unwrap() = Some(basepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Things here may cause the process to abort; we must do them before creating curses windows
|
// Things here may cause the process to abort; we must do them before creating curses windows
|
||||||
// otherwise the error message will not be seen by a user
|
// otherwise the error message will not be seen by a user
|
||||||
let config: Arc<crate::config::Config> = Arc::new(Config::new(
|
let config: Arc<crate::config::Config> = Arc::new(Config::new(
|
||||||
matches
|
configuration_file_path.unwrap_or("config.toml".into()),
|
||||||
.get_one::<String>("config")
|
|
||||||
.unwrap_or(&"config.toml".to_string()),
|
|
||||||
));
|
));
|
||||||
let mut credentials = {
|
let mut credentials = {
|
||||||
let cache = Cache::new(Some(config::cache_path("librespot")), None, None, None)
|
let cache = Cache::new(Some(config::cache_path("librespot")), None, None, None)
|
||||||
|
|||||||
@@ -169,14 +169,14 @@ lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
filename: String,
|
filename: PathBuf,
|
||||||
values: RwLock<ConfigValues>,
|
values: RwLock<ConfigValues>,
|
||||||
state: RwLock<UserState>,
|
state: RwLock<UserState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new(filename: &str) -> Self {
|
pub fn new(filename: PathBuf) -> Self {
|
||||||
let values = load(filename).unwrap_or_else(|e| {
|
let values = load(&filename.to_string_lossy()).unwrap_or_else(|e| {
|
||||||
eprintln!("could not load config: {e}");
|
eprintln!("could not load config: {e}");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
});
|
});
|
||||||
@@ -200,7 +200,7 @@ impl Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
filename: filename.to_string(),
|
filename,
|
||||||
values: RwLock::new(values),
|
values: RwLock::new(values),
|
||||||
state: RwLock::new(userstate),
|
state: RwLock::new(userstate),
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ impl Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn reload(&self) {
|
pub fn reload(&self) {
|
||||||
let cfg = load(&self.filename).expect("could not reload config");
|
let cfg = load(&self.filename.to_string_lossy()).expect("could not reload config");
|
||||||
*self.values.write().expect("can't writelock config values") = cfg
|
*self.values.write().expect("can't writelock config values") = cfg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use clap::builder::PathBufValueParser;
|
||||||
use librespot_playback::audio_backend;
|
use librespot_playback::audio_backend;
|
||||||
|
|
||||||
pub const AUTHOR: &str = "Henrik Friedrichsen <henrik@affekt.org> and contributors";
|
pub const AUTHOR: &str = "Henrik Friedrichsen <henrik@affekt.org> and contributors";
|
||||||
@@ -22,6 +23,7 @@ pub fn program_arguments() -> clap::Command {
|
|||||||
.short('d')
|
.short('d')
|
||||||
.long("debug")
|
.long("debug")
|
||||||
.value_name("FILE")
|
.value_name("FILE")
|
||||||
|
.value_parser(PathBufValueParser::new())
|
||||||
.help("Enable debug logging to the specified file"),
|
.help("Enable debug logging to the specified file"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@@ -29,6 +31,7 @@ pub fn program_arguments() -> clap::Command {
|
|||||||
.short('b')
|
.short('b')
|
||||||
.long("basepath")
|
.long("basepath")
|
||||||
.value_name("PATH")
|
.value_name("PATH")
|
||||||
|
.value_parser(PathBufValueParser::new())
|
||||||
.help("custom basepath to config/cache files"),
|
.help("custom basepath to config/cache files"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@@ -36,6 +39,7 @@ pub fn program_arguments() -> clap::Command {
|
|||||||
.short('c')
|
.short('c')
|
||||||
.long("config")
|
.long("config")
|
||||||
.value_name("FILE")
|
.value_name("FILE")
|
||||||
|
.value_parser(PathBufValueParser::new())
|
||||||
.help("Filename of config file in basepath")
|
.help("Filename of config file in basepath")
|
||||||
.default_value("config.toml"),
|
.default_value("config.toml"),
|
||||||
)
|
)
|
||||||
|
|||||||
14
src/main.rs
14
src/main.rs
@@ -8,6 +8,10 @@ extern crate serde;
|
|||||||
use std::backtrace;
|
use std::backtrace;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use application::Application;
|
||||||
|
use ncspot::program_arguments;
|
||||||
|
|
||||||
mod application;
|
mod application;
|
||||||
mod authentication;
|
mod authentication;
|
||||||
@@ -36,8 +40,6 @@ mod ipc;
|
|||||||
#[cfg(feature = "mpris")]
|
#[cfg(feature = "mpris")]
|
||||||
mod mpris;
|
mod mpris;
|
||||||
|
|
||||||
use crate::application::Application;
|
|
||||||
|
|
||||||
/// Register a custom panic handler to write the backtrace to a file since stdout is in use by the
|
/// Register a custom panic handler to write the backtrace to a file since stdout is in use by the
|
||||||
/// Cursive TUI library during most of the application.
|
/// Cursive TUI library during most of the application.
|
||||||
fn register_backtrace_panic_handler() {
|
fn register_backtrace_panic_handler() {
|
||||||
@@ -64,7 +66,13 @@ fn register_backtrace_panic_handler() {
|
|||||||
fn main() -> Result<(), String> {
|
fn main() -> Result<(), String> {
|
||||||
register_backtrace_panic_handler();
|
register_backtrace_panic_handler();
|
||||||
|
|
||||||
let mut application = Application::new()?;
|
let matches = program_arguments().get_matches();
|
||||||
|
|
||||||
|
let mut application = Application::new(
|
||||||
|
matches.get_one::<PathBuf>("debug").cloned(),
|
||||||
|
matches.get_one::<PathBuf>("basepath").cloned(),
|
||||||
|
matches.get_one::<PathBuf>("config").cloned(),
|
||||||
|
)?;
|
||||||
|
|
||||||
application.run()
|
application.run()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user