use facet::Facet;
use facet_args as args;
#[derive(Facet, Debug)]
#[allow(dead_code)]
struct GitArgs {
#[facet(args::named)]
version: bool,
#[facet(args::subcommand)]
command: GitCommand,
}
#[derive(Facet, Debug)]
#[repr(u8)]
#[allow(dead_code)]
enum GitCommand {
Clone {
#[facet(args::positional)]
url: String,
#[facet(default, args::positional)]
directory: Option<String>,
},
Log {
#[facet(args::named, args::short = 'n')]
count: Option<usize>,
#[facet(args::named)]
oneline: bool,
},
Remote {
#[facet(args::subcommand)]
action: RemoteAction,
},
}
#[derive(Facet, Debug)]
#[repr(u8)]
#[allow(dead_code)]
enum RemoteAction {
Add {
#[facet(args::positional)]
name: String,
#[facet(args::positional)]
url: String,
},
#[facet(rename = "rm")]
Remove {
#[facet(args::positional)]
name: String,
},
#[facet(rename = "ls")]
List {
#[facet(args::named, args::short = 'v')]
verbose: bool,
},
}
fn main() {
let scenarios = [
("Top-level help", vec!["--help"]),
("Missing required subcommand", vec![]),
("Unknown subcommand", vec!["notacommand"]),
("Subcommand help", vec!["clone", "--help"]),
("Nested subcommand help", vec!["remote", "add", "--help"]),
];
for (description, args_vec) in &scenarios {
println!("\n{}", "=".repeat(80));
println!("SCENARIO: {}", description);
println!("Args: {:?}", args_vec);
println!("{}", "=".repeat(80));
let result = args::from_slice::<GitArgs>(args_vec);
match result {
Ok(_) => println!("✓ Successfully parsed arguments"),
Err(e) => {
let is_help = e.is_help_request();
println!(
"\n{} {}",
if is_help {
"ℹ️ Help requested"
} else {
"❌ Error"
},
if is_help {
"(exit code: 0)"
} else {
"(exit code: 1)"
}
);
println!("\n{e}\n");
}
}
}
println!("\n{}", "=".repeat(80));
println!("Summary:");
println!(" • Help requests exit with code 0 and show colored help");
println!(" • Errors exit with code 1 and show diagnostic with suggestions");
println!(" • Subcommand help works with: <subcommand> --help");
println!("{}", "=".repeat(80));
}