use clap::Parser;
use color_eyre::eyre::Result;
#[derive(Parser)]
#[command(
name = "typstify",
version,
about = "A high-performance static site generator"
)]
struct Cli {
#[arg(short, long, default_value = "config.toml")]
config: std::path::PathBuf,
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8,
#[command(subcommand)]
command: Commands,
}
#[derive(clap::Subcommand)]
enum Commands {
Build {
#[arg(short, long, default_value = "public")]
output: std::path::PathBuf,
#[arg(long)]
drafts: bool,
},
Watch {
#[arg(short, long, default_value_t = 3000)]
port: u16,
#[arg(long)]
open: bool,
},
New {
path: std::path::PathBuf,
#[arg(short, long, default_value = "post")]
template: String,
},
Check {
#[arg(long)]
strict: bool,
},
}
#[tokio::main]
async fn main() -> Result<()> {
color_eyre::install()?;
let cli = Cli::parse();
typstify::init_tracing(cli.verbose);
match cli.command {
Commands::Build { output, drafts } => {
typstify::cmd::build::run(&cli.config, &output, drafts)?;
}
Commands::Watch { port, open } => {
typstify::cmd::watch::run(&cli.config, port, open).await?;
}
Commands::New { path, template } => {
typstify::cmd::new::run(&path, &template)?;
}
Commands::Check { strict } => {
typstify::cmd::check::run(&cli.config, strict)?;
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use clap::Parser;
use super::*;
#[test]
fn test_cli_build_command_parsing() {
let args = ["typstify", "build", "--output", "dist"];
let cli = Cli::parse_from(args);
assert_eq!(cli.config, std::path::PathBuf::from("config.toml"));
assert_eq!(cli.verbose, 0);
match cli.command {
Commands::Build { output, drafts } => {
assert_eq!(output, std::path::PathBuf::from("dist"));
assert!(!drafts);
}
_ => panic!("Expected Build command"),
}
}
#[test]
fn test_cli_build_with_drafts() {
let args = ["typstify", "build", "--drafts"];
let cli = Cli::parse_from(args);
match cli.command {
Commands::Build { drafts, .. } => {
assert!(drafts);
}
_ => panic!("Expected Build command"),
}
}
#[test]
fn test_cli_watch_command_parsing() {
let args = ["typstify", "watch", "--port", "8080", "--open"];
let cli = Cli::parse_from(args);
match cli.command {
Commands::Watch { port, open } => {
assert_eq!(port, 8080);
assert!(open);
}
_ => panic!("Expected Watch command"),
}
}
#[test]
fn test_cli_new_command_parsing() {
let args = ["typstify", "new", "posts/my-article", "--template", "typst"];
let cli = Cli::parse_from(args);
match cli.command {
Commands::New { path, template } => {
assert_eq!(path, std::path::PathBuf::from("posts/my-article"));
assert_eq!(template, "typst");
}
_ => panic!("Expected New command"),
}
}
#[test]
fn test_cli_check_command_parsing() {
let args = ["typstify", "check", "--strict"];
let cli = Cli::parse_from(args);
match cli.command {
Commands::Check { strict } => {
assert!(strict);
}
_ => panic!("Expected Check command"),
}
}
#[test]
fn test_cli_verbosity_flags() {
let args = ["typstify", "-vvv", "build"];
let cli = Cli::parse_from(args);
assert_eq!(cli.verbose, 3);
}
#[test]
fn test_cli_custom_config_path() {
let args = ["typstify", "--config", "site.toml", "build"];
let cli = Cli::parse_from(args);
assert_eq!(cli.config, std::path::PathBuf::from("site.toml"));
}
}