feat: implement unified settings system
Co-authored-by: aider (openai/andrew/openrouter/anthropic/claude-sonnet-4) <aider@aider.chat>
This commit is contained in:
110
src/config.rs
110
src/config.rs
@@ -3,15 +3,21 @@ use std::fs;
|
||||
use anyhow::{Result, Context};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use log::debug;
|
||||
use crate::args::{Args, KeyValue};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
|
||||
pub struct Config {
|
||||
pub dir: Option<PathBuf>,
|
||||
pub list_format: Option<String>,
|
||||
pub human_readable: Option<bool>,
|
||||
pub output_format: Option<String>,
|
||||
pub verbose: Option<u8>,
|
||||
pub quiet: Option<bool>,
|
||||
pub force: Option<bool>,
|
||||
pub server: Option<ServerConfig>,
|
||||
pub compression_plugin: Option<CompressionPluginConfig>,
|
||||
pub meta_plugins: Option<Vec<MetaPluginConfig>>,
|
||||
pub digest: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
@@ -31,6 +37,110 @@ pub struct MetaPluginConfig {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Unified settings that merges config file and CLI arguments
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Settings {
|
||||
pub dir: PathBuf,
|
||||
pub list_format: String,
|
||||
pub human_readable: bool,
|
||||
pub output_format: Option<String>,
|
||||
pub verbose: u8,
|
||||
pub quiet: bool,
|
||||
pub force: bool,
|
||||
pub server_password: Option<String>,
|
||||
pub compression: Option<String>,
|
||||
pub digest: Option<String>,
|
||||
pub meta_plugins: Vec<String>,
|
||||
pub meta: Vec<KeyValue>,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
/// Create unified settings from config and args with proper priority
|
||||
pub fn from_config_and_args(config: &Config, args: &Args, default_dir: PathBuf) -> Result<Self> {
|
||||
// Apply priority: CLI args > env vars > config file > defaults
|
||||
|
||||
let dir = args.options.dir.clone()
|
||||
.or_else(|| config.dir.clone())
|
||||
.unwrap_or(default_dir);
|
||||
|
||||
let list_format = if args.options.list_format != "id,time,size,tags,meta:hostname" {
|
||||
args.options.list_format.clone()
|
||||
} else {
|
||||
config.list_format.clone()
|
||||
.unwrap_or_else(|| "id,time,size,tags,meta:hostname".to_string())
|
||||
};
|
||||
|
||||
let human_readable = args.options.human_readable || config.human_readable.unwrap_or(false);
|
||||
|
||||
let output_format = args.options.output_format.clone()
|
||||
.or_else(|| config.output_format.clone());
|
||||
|
||||
let verbose = if args.options.verbose > 0 {
|
||||
args.options.verbose
|
||||
} else {
|
||||
config.verbose.unwrap_or(0)
|
||||
};
|
||||
|
||||
let quiet = args.options.quiet || config.quiet.unwrap_or(false);
|
||||
let force = args.options.force || config.force.unwrap_or(false);
|
||||
|
||||
let server_password = args.options.server_password.clone()
|
||||
.or_else(|| config.get_server_password().ok().flatten());
|
||||
|
||||
let compression = args.item.compression.clone()
|
||||
.or_else(|| config.compression_plugin.as_ref().map(|c| c.name.clone()));
|
||||
|
||||
let digest = args.item.digest.clone()
|
||||
.or_else(|| config.digest.clone());
|
||||
|
||||
let meta_plugins = if !args.item.meta_plugins.is_empty() {
|
||||
args.item.meta_plugins.clone()
|
||||
} else {
|
||||
config.meta_plugins.as_ref()
|
||||
.map(|plugins| plugins.iter().map(|p| p.name.clone()).collect())
|
||||
.unwrap_or_default()
|
||||
};
|
||||
|
||||
Ok(Settings {
|
||||
dir,
|
||||
list_format,
|
||||
human_readable,
|
||||
output_format,
|
||||
verbose,
|
||||
quiet,
|
||||
force,
|
||||
server_password,
|
||||
compression,
|
||||
digest,
|
||||
meta_plugins,
|
||||
meta: args.item.meta.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Get server address from args or config
|
||||
pub fn get_server_address(&self, args: &Args, config: &Config) -> Option<String> {
|
||||
// CLI args take priority
|
||||
if let Some(server_addr) = &args.mode.server {
|
||||
return Some(server_addr.clone());
|
||||
}
|
||||
|
||||
// Then config file
|
||||
if let Some(server_config) = &config.server {
|
||||
let mut addr = server_config.address.clone().unwrap_or_else(|| "127.0.0.1".to_string());
|
||||
if let Some(port) = server_config.port {
|
||||
if !addr.contains(':') {
|
||||
addr.push_str(&format!(":{}", port));
|
||||
}
|
||||
} else if !addr.contains(':') {
|
||||
addr.push_str(":8080");
|
||||
}
|
||||
return Some(addr);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Load configuration from a file
|
||||
pub fn from_file(path: &PathBuf) -> Result<Self> {
|
||||
|
||||
Reference in New Issue
Block a user