use clap::Parser;
use clap_fmt::FmtArgs;
use serde::Serialize;
#[derive(Parser, Debug, Serialize)]
struct CliWithPositions {
#[arg(index = 1)]
first: String,
#[arg(index = 2)]
second: String,
#[arg(long)]
flag: bool,
#[arg(index = 3, num_args = 1..)]
rest: Vec<String>,
}
#[test]
fn test_positional_ordering() {
let cli = CliWithPositions {
first: "one".to_string(),
second: "two".to_string(),
flag: true,
rest: vec!["three".to_string(), "four".to_string()],
};
let result = cli.to_args();
assert_eq!(result, vec!["one", "two", "--flag", "three", "four"]);
}
#[derive(Parser, Debug, Serialize)]
struct CliWithShortLong {
#[arg(short)]
short_only: bool,
#[arg(long)]
long_only: bool,
#[arg(short = 'x')]
custom_short: bool,
#[arg(long = "custom-long")]
custom_long: bool,
#[arg(short, long)]
both: bool,
}
#[test]
fn test_short_long_flags() {
let cli = CliWithShortLong {
short_only: true,
long_only: true,
custom_short: true,
custom_long: true,
both: true,
};
let result = cli.to_args();
assert_eq!(result, vec!["-s", "--long-only", "-x", "--custom-long", "--both"]);
}
#[derive(Parser, Debug, Serialize)]
struct CliWithEnv {
#[arg(long, env = "MY_CONFIG")]
config: Option<String>,
#[arg(long, hide = true)]
hidden: bool,
#[arg(long, alias = "colour")]
color: bool,
}
#[test]
fn test_env_and_special() {
let cli = CliWithEnv {
config: Some("app.conf".to_string()),
hidden: true,
color: true,
};
let result = cli.to_args();
assert_eq!(result, vec!["--config", "app.conf", "--hidden", "--color"]);
}
#[derive(Parser, Debug, Serialize)]
struct CliWithConflicts {
#[arg(long, conflicts_with = "json")]
xml: bool,
#[arg(long, conflicts_with = "xml")]
json: bool,
#[arg(long, required_unless_present = "input")]
output: Option<String>,
#[arg(long, required_unless_present = "output")]
input: Option<String>,
}
#[test]
fn test_conflicts() {
let cli = CliWithConflicts {
xml: true,
json: false,
output: Some("out.txt".to_string()),
input: None,
};
let result = cli.to_args();
assert_eq!(result, vec!["--xml", "--output", "out.txt"]);
}
#[derive(Parser, Debug, Serialize)]
struct CliWithMetadata {
#[arg(short, long, value_name = "FILE", help = "Input file to process")]
input: String,
#[arg(
short,
long,
value_name = "DIR",
long_help = "Output directory for results"
)]
output: String,
}
#[test]
fn test_metadata_doesnt_break() {
let cli = CliWithMetadata {
input: "in.txt".to_string(),
output: "out/".to_string(),
};
let result = cli.to_args();
assert_eq!(result, vec!["--input", "in.txt", "--output", "out/"]);
}