use clap::error::ErrorKind;
use clap::{Parser, Subcommand, ValueEnum, ValueHint};
use clap_complete::Shell;
use std::path::PathBuf;
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Default)]
pub enum ValidationStrictness {
Lenient,
#[default]
Normal,
Paranoid,
}
#[derive(Parser)]
#[command(name = "fontlift")]
#[command(about = "Install, uninstall, list, and remove fonts cross-platform", long_about = None)]
#[command(version = env!("GIT_VERSION"))]
pub struct Cli {
#[arg(
global = true,
long,
help = "Print intended actions without mutating fonts"
)]
pub dry_run: bool,
#[arg(
global = true,
short = 'q',
long,
help = "Silence routine status output",
conflicts_with = "verbose"
)]
pub quiet: bool,
#[arg(
global = true,
short = 'v',
long,
help = "Show verbose status messages",
conflicts_with = "quiet"
)]
pub verbose: bool,
#[arg(global = true, short = 'j', long, help = "Output results as JSON")]
pub json: bool,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
#[command(alias = "l")]
List {
#[arg(short, long, help = "Show font file paths")]
path: bool,
#[arg(short, long, help = "Show internal font names")]
name: bool,
#[arg(short, long, help = "Remove duplicates; output is always sorted")]
sorted: bool,
},
#[command(alias = "i")]
Install {
#[arg(
value_name = "FONT|DIR",
num_args = 1..,
value_hint = ValueHint::AnyPath,
help = "Font file(s) or directory/ies to install; directories are scanned for font files"
)]
font_inputs: Vec<PathBuf>,
#[arg(
short,
long,
help = "Install at system level (all users, requires admin)"
)]
admin: bool,
#[arg(short = 'V', long, help = "Skip out-of-process font validation")]
no_validate: bool,
#[arg(
long,
value_enum,
default_value = "normal",
help = "Validation strictness preset"
)]
validation_strictness: ValidationStrictness,
#[arg(
short = 'c',
long,
help = "Copy the font file to the fonts folder and install (default)",
conflicts_with = "inplace"
)]
copy: bool,
#[arg(
short = 'i',
long,
help = "Keep the font file in place but install it",
conflicts_with = "copy"
)]
inplace: bool,
},
#[command(alias = "u")]
Uninstall {
#[arg(short, long, help = "Font name to uninstall")]
name: Option<String>,
#[arg(
value_name = "FONT|DIR",
num_args = 0..,
value_hint = ValueHint::AnyPath,
help = "Font file(s) or directory/ies to uninstall; directories are scanned for font files"
)]
font_inputs: Vec<PathBuf>,
#[arg(
short,
long,
help = "Uninstall at system level (all users, requires admin)"
)]
admin: bool,
},
#[command(alias = "rm")]
Remove {
#[arg(short, long, help = "Font name to remove")]
name: Option<String>,
#[arg(
value_name = "FONT|DIR",
num_args = 0..,
value_hint = ValueHint::AnyPath,
help = "Font file(s) or directory/ies to remove; directories are scanned for font files"
)]
font_inputs: Vec<PathBuf>,
#[arg(
short,
long,
help = "Remove at system level (all users, requires admin)"
)]
admin: bool,
},
#[command(alias = "c")]
Cleanup {
#[arg(short, long, help = "Include system-wide cleanup (requires admin)")]
admin: bool,
#[arg(
short = 'p',
long,
help = "Only prune stale registrations; skip cache clearing",
conflicts_with = "cache_only"
)]
prune_only: bool,
#[arg(
short = 'C',
long,
help = "Only clear caches; skip pruning stale registrations",
conflicts_with = "prune_only"
)]
cache_only: bool,
},
Completions {
#[arg(value_enum, help = "Shell to generate completions for")]
shell: Shell,
},
#[command(alias = "d")]
Doctor {
#[arg(short = 'P', long, help = "Preview recovery actions without executing")]
preview: bool,
},
}
pub fn exit_code_for_clap_error(kind: ErrorKind) -> i32 {
match kind {
ErrorKind::DisplayHelp | ErrorKind::DisplayVersion => 0,
_ => 1,
}
}