use clap::Parser;
use dotcfg::DotCfg;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
struct AppConfig {
host: String,
port: u16,
log_level: String,
}
impl Default for AppConfig {
fn default() -> Self {
Self {
host: "127.0.0.1".into(),
port: 8080,
log_level: "info".into(),
}
}
}
#[derive(Parser, Debug)]
#[command(name = "mycli", about = "CLI with dotcfg + clap precedence")]
struct Cli {
#[arg(short = 'H', long)]
host: Option<String>,
#[arg(short, long)]
port: Option<u16>,
#[arg(short, long)]
log_level: Option<String>,
#[arg(long)]
save_default: bool,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Cli::parse();
let cfg_handle = DotCfg::new("mycli");
let saved: AppConfig = cfg_handle.load()?.unwrap_or_default();
let active_config = AppConfig {
host: args.host.unwrap_or(saved.host),
port: args.port.unwrap_or(saved.port),
log_level: args.log_level.unwrap_or(saved.log_level),
};
println!("Active configuration: {active_config:#?}");
println!("Config file location: {:?}", cfg_handle.file_path()?);
if args.save_default {
cfg_handle.save(&active_config)?;
println!(
"Saved active configuration to {:?}",
cfg_handle.file_path()?
);
}
Ok(())
}