From f467afa4f5f89e66f198fc8765cbfed702a5dd62 Mon Sep 17 00:00:00 2001 From: Cole Mei Date: Tue, 18 Aug 2026 17:38:38 +0800 Subject: [PATCH] fix: restore --help on every subcommand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `disable_help_flag` on the root Cli propagates to subcommands, and the manual -h/--help field put the flag back only at the root. Every `openwith --help` therefore failed with "unexpected argument", while `openwith --help` kept working — which is why it went unnoticed. Drop both and set the logo help_template on the root command only; subcommands fall back to clap's generated help, which lists their real flags. Adds a test that fails on the old definition. --- crates/openwith-cli/src/cli.rs | 44 +++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/crates/openwith-cli/src/cli.rs b/crates/openwith-cli/src/cli.rs index 0631106..807ce2c 100644 --- a/crates/openwith-cli/src/cli.rs +++ b/crates/openwith-cli/src/cli.rs @@ -41,18 +41,13 @@ FLAGS name = "openwith", about = "Manage macOS file extension associations", version, - disable_version_flag = true, - disable_help_flag = true + disable_version_flag = true )] pub struct Cli { /// Print version #[arg(short = 'v', long = "version", action = clap::ArgAction::Version)] pub version: (), - /// Print help - #[arg(short = 'h', long = "help", action = clap::ArgAction::HelpLong)] - pub help: (), - #[command(subcommand)] pub command: Option, } @@ -61,6 +56,11 @@ impl Cli { pub fn parse_with_help() -> Self { use clap::CommandFactory; let mut cmd = Self::command(); + // Only the root gets the hand-written logo template; subcommands keep + // clap's generated help, which lists their actual flags. `-h`/`--help` + // stay enabled everywhere — disabling them at the root propagated to + // every subcommand, leaving `openwith set --help` an "unexpected + // argument" error. cmd = cmd.help_template(help_template()); let matches = cmd.get_matches(); Self::from_arg_matches(&matches).expect("failed to parse CLI arguments") @@ -146,3 +146,35 @@ pub enum Commands { #[command(hide = true)] Mangen, } + +#[cfg(test)] +mod tests { + use super::*; + use clap::CommandFactory; + + #[test] + fn cli_definition_is_valid() { + Cli::command().debug_assert(); + } + + /// `disable_help_flag` on the root propagates to subcommands, which once + /// left every `openwith --help` failing as an unexpected argument + /// while the root's own help still worked — so the breakage was invisible + /// unless a subcommand was tried directly. + #[test] + fn every_subcommand_accepts_help() { + let mut cmd = Cli::command(); + cmd.build(); + for sub in cmd.get_subcommands() { + // clap's own `openwith help ` command takes no flags itself. + if sub.get_name() == "help" { + continue; + } + assert!( + sub.get_arguments().any(|a| a.get_id() == "help"), + "`openwith {}` has no --help flag", + sub.get_name() + ); + } + } +}