use clap::{
ArgAction,
Parser,
ValueEnum,
};
use git_cliff_core::DEFAULT_CONFIG;
use glob::Pattern;
use std::path::PathBuf;
#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum Strip {
Header,
Footer,
All,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum Sort {
Oldest,
Newest,
}
#[derive(Debug, Parser)]
#[command(
version,
author = clap::crate_authors!("\n"),
about,
rename_all_env = "screaming-snake",
help_template = "\
{before-help}{name} {version}
{author-with-newline}{about-with-newline}
{usage-heading}
{usage}
{all-args}{after-help}
",
override_usage = "git-cliff [FLAGS] [OPTIONS] [--] [RANGE]",
next_help_heading = Some("OPTIONS"),
disable_help_flag = true,
disable_version_flag = true,
)]
pub struct Opt {
#[arg(
short,
long,
action = ArgAction::Help,
global = true,
help = "Prints help information",
help_heading = "FLAGS"
)]
pub help: Option<bool>,
#[arg(
short = 'V',
long,
action = ArgAction::Version,
global = true,
help = "Prints version information",
help_heading = "FLAGS"
)]
pub version: Option<bool>,
#[arg(short, long, action = ArgAction::Count, alias = "debug", help_heading = Some("FLAGS"))]
pub verbose: u8,
#[arg(
short,
long,
env = "GIT_CLIFF_CONFIG",
value_name = "PATH",
default_value = DEFAULT_CONFIG,
value_parser = Opt::parse_dir
)]
pub config: PathBuf,
#[arg(
short,
long,
env = "GIT_CLIFF_WORKDIR",
value_name = "PATH",
value_parser = Opt::parse_dir
)]
pub workdir: Option<PathBuf>,
#[arg(
short,
long,
env = "GIT_CLIFF_REPOSITORY",
value_name = "PATH",
num_args(1..),
value_parser = Opt::parse_dir
)]
pub repository: Option<Vec<PathBuf>>,
#[arg(
long,
env = "GIT_CLIFF_INCLUDE_PATH",
value_name = "PATTERN",
num_args(1..)
)]
pub include_path: Option<Vec<Pattern>>,
#[arg(
long,
env = "GIT_CLIFF_EXCLUDE_PATH",
value_name = "PATTERN",
num_args(1..)
)]
pub exclude_path: Option<Vec<Pattern>>,
#[arg(
long,
env = "GIT_CLIFF_WITH_COMMIT",
value_name = "MSG",
num_args(1..)
)]
pub with_commit: Option<Vec<String>>,
#[arg(
short,
long,
env = "GIT_CLIFF_PREPEND",
value_name = "PATH",
value_parser = Opt::parse_dir
)]
pub prepend: Option<PathBuf>,
#[arg(
short,
long,
env = "GIT_CLIFF_OUTPUT",
value_name = "PATH",
value_parser = Opt::parse_dir
)]
pub output: Option<PathBuf>,
#[arg(
short,
long,
env = "GIT_CLIFF_TAG",
value_name = "TAG",
allow_hyphen_values = true
)]
pub tag: Option<String>,
#[arg(long, help_heading = Some("FLAGS"))]
pub bump: bool,
#[arg(
short,
long,
env = "GIT_CLIFF_TEMPLATE",
value_name = "TEMPLATE",
allow_hyphen_values = true
)]
pub body: Option<String>,
#[arg(short, long, help_heading = Some("FLAGS"))]
pub init: bool,
#[arg(short, long, help_heading = Some("FLAGS"))]
pub latest: bool,
#[arg(long, help_heading = Some("FLAGS"))]
pub current: bool,
#[arg(short, long, help_heading = Some("FLAGS"))]
pub unreleased: bool,
#[arg(long, help_heading = Some("FLAGS"))]
pub topo_order: bool,
#[arg(long, help_heading = Some("FLAGS"))]
pub context: bool,
#[arg(short, long, value_name = "PART", value_enum)]
pub strip: Option<Strip>,
#[arg(
long,
value_enum,
default_value_t = Sort::Oldest
)]
pub sort: Sort,
#[arg(value_name = "RANGE", help_heading = Some("ARGS"))]
pub range: Option<String>,
}
impl Opt {
fn parse_dir(dir: &str) -> Result<PathBuf, String> {
Ok(PathBuf::from(shellexpand::tilde(dir).to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
use clap::CommandFactory;
#[test]
fn verify_cli() {
Opt::command().debug_assert()
}
#[test]
fn path_tilde_expansion() {
let home_dir =
dirs_next::home_dir().expect("cannot retrieve home directory");
let dir = Opt::parse_dir("~/").expect("cannot expand tilde");
assert_eq!(home_dir, dir);
}
}