use clap::{Parser, Subcommand};
use std::path::PathBuf;
mod commands;
mod config;
mod error;
mod generators;
use commands::CommandHandler;
use error::ZackstrapError;
#[derive(Parser)]
#[command(
name = "zackstrap",
about = "Bootstrap project configuration files",
version,
long_about = "A CLI tool to quickly generate common project configuration files like .editorconfig, .prettierrc, and more."
)]
struct Cli {
#[command(subcommand)]
command: Commands,
#[arg(short, long, value_name = "DIR")]
target: Option<PathBuf>,
#[arg(short, long)]
force: bool,
#[arg(short = 'e', long)]
fail_on_exists: bool,
#[arg(long)]
dry_run: bool,
#[arg(long)]
hooks: bool,
}
#[derive(Subcommand)]
enum Commands {
Basic {
#[arg(short, long)]
template: Option<String>,
},
Ruby {
#[arg(short, long)]
template: Option<String>,
},
Python {
#[arg(short, long)]
template: Option<String>,
},
Node {
#[arg(short, long)]
template: Option<String>,
},
Go {
#[arg(short, long)]
template: Option<String>,
},
Rust {
#[arg(short, long)]
template: Option<String>,
},
Bash {
#[arg(short, long)]
template: Option<String>,
},
Auto,
Interactive,
List,
}
#[tokio::main]
async fn main() -> Result<(), ZackstrapError> {
let cli = Cli::parse();
let target_dir = cli
.target
.unwrap_or_else(|| std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")));
if !target_dir.exists() {
return Err(ZackstrapError::DirectoryNotFound(target_dir));
}
if !target_dir.is_dir() {
return Err(ZackstrapError::NotADirectory(target_dir));
}
let handler = CommandHandler::new(
target_dir,
cli.force,
cli.fail_on_exists,
cli.dry_run,
cli.hooks,
);
match cli.command {
Commands::Basic { template } => handler.handle_basic(template).await?,
Commands::Ruby { template } => handler.handle_ruby(template).await?,
Commands::Python { template } => handler.handle_python(template).await?,
Commands::Node { template } => handler.handle_node(template).await?,
Commands::Go { template } => handler.handle_go(template).await?,
Commands::Rust { template } => handler.handle_rust(template).await?,
Commands::Bash { template } => handler.handle_bash(template).await?,
Commands::Auto => handler.handle_auto().await?,
Commands::Interactive => handler.handle_interactive().await?,
Commands::List => handler.handle_list(),
}
Ok(())
}