start working on a cli app #7
5 changed files with 94 additions and 74 deletions
|
@ -1,74 +1,24 @@
|
||||||
use std::{
|
use clap::Parser;
|
||||||
fs,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
process,
|
|
||||||
};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use self::{cli::Args, config_file::Configs};
|
||||||
|
|
||||||
use crate::error_reporting::{report_serde_json_err, report_serde_ron_err};
|
mod cli;
|
||||||
|
mod config_file;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
/// this struct may hold all configuration
|
||||||
pub struct Configs {
|
pub struct Config {
|
||||||
#[serde(default = "default_example_value")]
|
pub startup_msg: bool,
|
||||||
pub example_value: i32,
|
|
||||||
#[serde(default = "default_no_startup_msg")]
|
|
||||||
pub no_startup_message: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// what the fuck serde why do i need this
|
impl Config {
|
||||||
fn default_example_value() -> i32 {
|
pub fn read() -> Self {
|
||||||
43
|
let args = Args::parse();
|
||||||
}
|
let cfg = Configs::read(args.config_file);
|
||||||
fn default_no_startup_msg() -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Configs {
|
Self {
|
||||||
pub fn read(custom_path: Option<PathBuf>) -> Self {
|
// this is negated because to an outward api, the negative is more intuitive,
|
||||||
use owo_colors::OwoColorize;
|
// while in the source the other way around is more intuitive
|
||||||
let p = match custom_path {
|
startup_msg: !(args.no_startup_message || cfg.no_startup_message),
|
||||||
Some(p) => p,
|
|
||||||
None => {
|
|
||||||
let config_path = dirs::config_dir().expect("config dir should exist");
|
|
||||||
|
|
||||||
let ron_path = config_path.with_file_name("config.ron");
|
|
||||||
let json_path = config_path.with_file_name("config.json");
|
|
||||||
|
|
||||||
if Path::new(&ron_path).exists() {
|
|
||||||
ron_path
|
|
||||||
} else if Path::new(&json_path).exists() {
|
|
||||||
json_path
|
|
||||||
} else {
|
|
||||||
eprintln!("{}: couldn't find config file", "Fatal error".red());
|
|
||||||
process::exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match p.extension().map(|v| v.to_str().unwrap()) {
|
|
||||||
Some("ron") => Self::read_json(&fs::read_to_string(p).unwrap()),
|
|
||||||
Some("json") => Self::read_ron(&fs::read_to_string(p).unwrap()),
|
|
||||||
None | Some(_) => {
|
|
||||||
eprintln!(
|
|
||||||
"{}: couldn't determine config file type",
|
|
||||||
"Fatal error".red()
|
|
||||||
);
|
|
||||||
process::exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn read_json(config_text: &str) -> Configs {
|
|
||||||
match serde_json::from_str(config_text) {
|
|
||||||
Ok(c) => c,
|
|
||||||
Err(e) => report_serde_json_err(config_text, e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_ron(config_text: &str) -> Configs {
|
|
||||||
match ron::from_str(config_text) {
|
|
||||||
Ok(c) => c,
|
|
||||||
Err(e) => report_serde_ron_err(config_text, e),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
75
crates/app/src/config/config_file.rs
Normal file
75
crates/app/src/config/config_file.rs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
use std::{
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
process,
|
||||||
|
};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::error_reporting::{report_serde_json_err, report_serde_ron_err};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Configs {
|
||||||
|
#[serde(default = "default_example_value")]
|
||||||
|
pub example_value: i32,
|
||||||
schrottkatze marked this conversation as resolved
Outdated
|
|||||||
|
#[serde(default = "default_no_startup_msg")]
|
||||||
|
pub no_startup_message: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// what the fuck serde why do i need this
|
||||||
|
pub(crate) fn default_example_value() -> i32 {
|
||||||
|
43
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn default_no_startup_msg() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Configs {
|
||||||
|
pub fn read(custom_path: Option<PathBuf>) -> Self {
|
||||||
|
use owo_colors::OwoColorize;
|
||||||
|
let p = match custom_path {
|
||||||
|
Some(p) => p,
|
||||||
|
None => {
|
||||||
|
let config_path = dirs::config_dir().expect("config dir should exist");
|
||||||
|
|
||||||
|
let ron_path = config_path.with_file_name("config.ron");
|
||||||
|
let json_path = config_path.with_file_name("config.json");
|
||||||
|
|
||||||
|
if Path::new(&ron_path).exists() {
|
||||||
|
ron_path
|
||||||
|
} else if Path::new(&json_path).exists() {
|
||||||
|
json_path
|
||||||
|
} else {
|
||||||
|
eprintln!("{}: couldn't find config file", "Fatal error".red());
|
||||||
|
process::exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match p.extension().map(|v| v.to_str().unwrap()) {
|
||||||
|
Some("ron") => Self::read_json(&fs::read_to_string(p).unwrap()),
|
||||||
|
Some("json") => Self::read_ron(&fs::read_to_string(p).unwrap()),
|
||||||
|
None | Some(_) => {
|
||||||
|
eprintln!(
|
||||||
|
"{}: couldn't determine config file type",
|
||||||
|
"Fatal error".red()
|
||||||
|
);
|
||||||
|
process::exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn read_json(config_text: &str) -> Configs {
|
||||||
|
match serde_json::from_str(config_text) {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(e) => report_serde_json_err(config_text, e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_ron(config_text: &str) -> Configs {
|
||||||
|
match ron::from_str(config_text) {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(e) => report_serde_ron_err(config_text, e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +1,14 @@
|
||||||
use clap::Parser;
|
use config::Config;
|
||||||
use cli::Args;
|
|
||||||
use welcome_msg::print_startup_msg;
|
use welcome_msg::print_startup_msg;
|
||||||
|
|
||||||
use crate::config::Configs;
|
|
||||||
|
|
||||||
mod cli;
|
|
||||||
mod config;
|
mod config;
|
||||||
mod error_reporting;
|
mod error_reporting;
|
||||||
mod welcome_msg;
|
mod welcome_msg;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = Args::parse();
|
let cfg = Config::read();
|
||||||
let cfg = Configs::read(args.config_file);
|
|
||||||
|
|
||||||
if !(args.no_startup_message || cfg.no_startup_message) {
|
if cfg.startup_msg {
|
||||||
print_startup_msg();
|
print_startup_msg();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
multisamplednight marked this conversation as resolved
Outdated
multisamplednight
commented
Might want to streamline those two, in order to avoid accidentally checking only one of them in future. The Might want to streamline those two, in order to avoid accidentally checking only one of them in future.
The `figment` crate might be worth looking at in that case.
schrottkatze
commented
i'd prefer to try at least to some degree reduce dependencies, but i'll work on something like that then i'd prefer to try at least to some degree reduce dependencies, but i'll work on something like that then
multisamplednight
commented
You don't need to use You don't _need_ to use `figment`. Custom merge logic works fine, too.
|
|||||||
|
|
|
@ -7,4 +7,4 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { workspace = true, features = [ "derive" ] }
|
serde = { workspace = true, features = [ "derive" ] }
|
||||||
ron = { workspace = true }
|
ron = "0.8"
|
||||||
|
|
Loading…
Reference in a new issue
Since the default is
false
which is also returned by `bool::default, the extra function is not necessary:If you do desire to keep the functions to allow more detailed behavior in future, I suggest renaming
default_no_startup_msg
to to justbool_false
and creating abool_true
counterpart once necessary.