#[cfg(feature = "cli")]
use clap::{Parser, Subcommand};
#[cfg(feature = "cli")]
use confers::commands::{
completions::CompletionsCommand,
diff::{DiffCommand, DiffFormat, DiffOptions},
encrypt::EncryptCommand,
generate::GenerateCommand,
key::KeyCommand,
validate::{ValidateCommand, ValidateLevel},
wizard::ConfigWizard,
};
use confers::ConfigError;
#[cfg(feature = "cli")]
use std::str::FromStr;
#[cfg(feature = "cli")]
#[derive(Parser)]
#[command(name = "confers")]
#[command(about = "Configuration management tool", long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[cfg(feature = "cli")]
#[derive(Subcommand)]
enum Commands {
Generate {
#[arg(short, long)]
output: Option<String>,
#[arg(short, long, default_value = "full")]
level: String,
#[arg(short, long)]
r#struct: Option<String>,
#[arg(short, long, default_value = "toml")]
format: String,
},
Validate {
config: String,
#[arg(short, long, default_value = "full")]
level: String,
},
Diff {
file1: String,
file2: String,
#[arg(short, long, alias = "style")]
format: Option<String>,
#[arg(short, long)]
output: Option<String>,
},
Completions {
shell: String,
},
Encrypt {
value: String,
#[arg(short, long)]
key: Option<String>,
#[arg(short, long)]
output: Option<String>,
},
Wizard {
#[arg(long)]
non_interactive: bool,
},
#[command(subcommand)]
Key(#[command(subcommand)] confers::commands::key::KeySubcommand),
}
#[cfg(feature = "cli")]
fn main() -> Result<(), ConfigError> {
let cli = Cli::parse();
match &cli.command {
Commands::Generate {
output,
level,
r#struct,
format,
} => {
GenerateCommand::execute_placeholder(
output.as_ref(),
level,
r#struct.as_ref(),
format,
)?;
}
Commands::Validate { config, level } => {
let validate_level = ValidateLevel::parse(level);
ValidateCommand::execute_generic(config, validate_level)?;
}
Commands::Diff {
file1,
file2,
format,
output,
} => {
let diff_format = if let Some(s) = format {
DiffFormat::from_str(s).map_err(ConfigError::Other)?
} else {
DiffFormat::Unified
};
let options = DiffOptions {
format: diff_format,
output: output.clone(),
..Default::default()
};
DiffCommand::execute(file1, file2, options)?;
}
Commands::Completions { shell } => {
CompletionsCommand::execute::<Cli>(shell)?;
}
Commands::Encrypt { value, key, output } => {
EncryptCommand::execute(value, key.as_ref(), output.as_ref())?;
}
Commands::Wizard { non_interactive } => {
let wizard = ConfigWizard::new();
if *non_interactive {
let values = &["", "", "", "", "", "", ""];
let config = wizard.run_with_values(values)?;
config.save()?;
} else {
let config = wizard.run()?;
config.save()?;
}
}
Commands::Key(subcommand) => {
KeyCommand::execute(subcommand, None, None)?;
}
}
Ok(())
}
#[cfg(not(feature = "cli"))]
fn main() -> Result<(), ConfigError> {
eprintln!("❌ Error: CLI feature is not enabled.");
eprintln!();
eprintln!("The confers CLI tool requires the 'cli' feature to be enabled.");
eprintln!();
eprintln!("To build the CLI tool, use one of the following commands:");
eprintln!(" cargo build --features cli");
eprintln!(" cargo build --features dev");
eprintln!(" cargo build --features full");
eprintln!();
eprintln!("For library-only usage, you can use:");
eprintln!(" cargo build --features minimal");
eprintln!(" cargo build --features recommended");
eprintln!();
eprintln!("See the documentation for more information on feature presets.");
std::process::exit(1);
}