use clap::{CommandFactory, Parser, Subcommand, builder::PossibleValuesParser};
use clap_complete::{Generator, Shell, generate};
use std::error::Error;
use std::io;
mod cli;
mod config;
mod media;
mod project;
mod templates;
#[cfg(feature = "player")]
mod player;
#[derive(Parser)]
#[command(name = "zim")]
#[command(about = "Terminal-based audio project scaffold and metadata system")]
#[command(version)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Init,
Config {
#[command(subcommand)]
action: ConfigAction,
},
Completions {
#[arg(value_enum)]
shell: Shell,
},
New {
name: Option<String>,
#[arg(short, long)]
path: Option<String>,
#[arg(long)]
zimignore_template: Option<String>,
#[arg(long)]
no_zimignore: bool,
#[arg(short, long)]
interactive: bool,
},
Update {
#[arg(default_value = ".")]
path: String,
},
Lint {
#[arg(default_value = ".")]
path: String,
},
Play {
files: Vec<String>,
#[arg(
short,
long,
value_delimiter = ',',
value_name = "GAIN1,GAIN2,GAIN3",
help = "Gain levels for each file (0.0-2.0 range)",
long_help = "Comma-separated gain values for each file (0.0-2.0 range).\nExample: --gains 0.8,1.2,0.6\nDefaults to 1.0 for all files if not specified."
)]
gains: Option<Vec<f32>>,
#[arg(short, long)]
interactive: bool,
},
}
#[derive(Subcommand)]
enum ConfigAction {
View,
Set {
#[arg(value_parser = PossibleValuesParser::new(["root_dir", "default_artist", "normalize_project_names"]))]
key: String,
value: String,
},
Edit,
}
fn print_completions<G: Generator>(generator: G, cmd: &mut clap::Command) {
generate(
generator,
cmd,
cmd.get_name().to_string(),
&mut io::stdout(),
);
}
fn main() -> Result<(), Box<dyn Error>> {
let cli = Cli::parse();
match cli.command {
Commands::Init => {
cli::init::handle_init()?;
}
Commands::Config { action } => match action {
ConfigAction::View => {
cli::config::handle_config_view()?;
}
ConfigAction::Set { key, value } => {
cli::config::handle_config_set(&key, &value)?;
}
ConfigAction::Edit => {
cli::config::handle_config_edit()?;
}
},
Commands::Completions { shell } => {
let mut cmd = Cli::command();
print_completions(shell, &mut cmd);
}
Commands::New {
name,
path,
zimignore_template,
no_zimignore,
interactive,
} => {
cli::new::handle_new(
name.as_deref(),
path.as_deref(),
zimignore_template.as_deref(),
no_zimignore,
interactive,
)?;
}
Commands::Update { path } => {
cli::update::handle_update(&path)?;
}
Commands::Lint { path } => {
cli::lint::handle_lint(&path)?;
}
Commands::Play {
files,
gains,
interactive,
} => {
cli::play::handle_play(files, gains, interactive)?;
}
}
Ok(())
}