From e1d44d9834168c0d1cf694bd3f3a7cdff67d8c8d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 21 Oct 2024 14:53:20 +0100 Subject: [PATCH] cli: optionally show hidden options in usage Callers may wish to show all the options, even hidden ones, when showing usage. In particular, showing generic help for the CLI should show global options (those that are generally "hidden"). But showing help for a particular command should keep them hidden. Instrument a mechanism to deal with this. --- src/cli/cmd_blame.c | 2 +- src/cli/cmd_cat_file.c | 2 +- src/cli/cmd_clone.c | 2 +- src/cli/cmd_config.c | 2 +- src/cli/cmd_hash_object.c | 2 +- src/cli/cmd_help.c | 4 ++-- src/cli/cmd_index_pack.c | 2 +- src/cli/main.c | 2 +- src/cli/opt_usage.c | 38 +++++++++++++++++++++++++++++--------- src/cli/opt_usage.h | 7 ++++++- 10 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/cli/cmd_blame.c b/src/cli/cmd_blame.c index 3e2f5744c..6b720f350 100644 --- a/src/cli/cmd_blame.c +++ b/src/cli/cmd_blame.c @@ -40,7 +40,7 @@ static const cli_opt_spec opts[] = { static void print_help(void) { - cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts); + cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts, 0); printf("\n"); printf("Show the origin of each line of a file.\n"); diff --git a/src/cli/cmd_cat_file.c b/src/cli/cmd_cat_file.c index 90ee6033e..4d648d775 100644 --- a/src/cli/cmd_cat_file.c +++ b/src/cli/cmd_cat_file.c @@ -43,7 +43,7 @@ static const cli_opt_spec opts[] = { static void print_help(void) { - cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts); + cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts, 0); printf("\n"); printf("Display the content for the given object in the repository.\n"); diff --git a/src/cli/cmd_clone.c b/src/cli/cmd_clone.c index 7d9736fc7..afa71eee1 100644 --- a/src/cli/cmd_clone.c +++ b/src/cli/cmd_clone.c @@ -46,7 +46,7 @@ static const cli_opt_spec opts[] = { static void print_help(void) { - cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts); + cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts, 0); printf("\n"); printf("Clone a repository into a new directory.\n"); diff --git a/src/cli/cmd_config.c b/src/cli/cmd_config.c index 6b9d373ce..2d9ec93a2 100644 --- a/src/cli/cmd_config.c +++ b/src/cli/cmd_config.c @@ -68,7 +68,7 @@ static const cli_opt_spec opts[] = { static void print_help(void) { - cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts); + cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts, 0); printf("\n"); printf("Query and set configuration options.\n"); diff --git a/src/cli/cmd_hash_object.c b/src/cli/cmd_hash_object.c index 741debbeb..1eee001f7 100644 --- a/src/cli/cmd_hash_object.c +++ b/src/cli/cmd_hash_object.c @@ -36,7 +36,7 @@ static const cli_opt_spec opts[] = { static void print_help(void) { - cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts); + cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts, 0); printf("\n"); printf("Compute the object ID for a given file and optionally write that file\nto the object database.\n"); diff --git a/src/cli/cmd_help.c b/src/cli/cmd_help.c index 5e877e06d..ce3565970 100644 --- a/src/cli/cmd_help.c +++ b/src/cli/cmd_help.c @@ -25,7 +25,7 @@ static const cli_opt_spec opts[] = { static int print_help(void) { - cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts); + cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts, CLI_OPT_USAGE_SHOW_HIDDEN); printf("\n"); printf("Display help information about %s. If a command is specified, help\n", PROGRAM_NAME); @@ -39,7 +39,7 @@ static int print_commands(void) { const cli_cmd_spec *cmd; - cli_opt_usage_fprint(stdout, PROGRAM_NAME, NULL, cli_common_opts); + cli_opt_usage_fprint(stdout, PROGRAM_NAME, NULL, cli_common_opts, CLI_OPT_USAGE_SHOW_HIDDEN); printf("\n"); printf("These are the %s commands available:\n\n", PROGRAM_NAME); diff --git a/src/cli/cmd_index_pack.c b/src/cli/cmd_index_pack.c index 09685c5d4..c72dd4dcc 100644 --- a/src/cli/cmd_index_pack.c +++ b/src/cli/cmd_index_pack.c @@ -38,7 +38,7 @@ static const cli_opt_spec opts[] = { static void print_help(void) { - cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts); + cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts, 0); printf("\n"); printf("Indexes a packfile and writes the index to disk.\n"); diff --git a/src/cli/main.c b/src/cli/main.c index 715feab89..b51660481 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -82,7 +82,7 @@ int main(int argc, char **argv) while (cli_opt_parser_next(&opt, &optparser)) { if (!opt.spec) { cli_opt_status_fprint(stderr, PROGRAM_NAME, &opt); - cli_opt_usage_fprint(stderr, PROGRAM_NAME, NULL, cli_common_opts); + cli_opt_usage_fprint(stderr, PROGRAM_NAME, NULL, cli_common_opts, CLI_OPT_USAGE_SHOW_HIDDEN); ret = CLI_EXIT_USAGE; goto done; } diff --git a/src/cli/opt_usage.c b/src/cli/opt_usage.c index 8374f5151..ecb4f1461 100644 --- a/src/cli/opt_usage.c +++ b/src/cli/opt_usage.c @@ -46,7 +46,8 @@ int cli_opt_usage_fprint( FILE *file, const char *command, const char *subcommand, - const cli_opt_spec specs[]) + const cli_opt_spec specs[], + unsigned int print_flags) { git_str usage = GIT_BUF_INIT, opt = GIT_BUF_INIT; const cli_opt_spec *spec; @@ -73,7 +74,8 @@ int cli_opt_usage_fprint( next_choice = !!((spec + 1)->usage & CLI_OPT_USAGE_CHOICE); - if (spec->usage & CLI_OPT_USAGE_HIDDEN) + if ((spec->usage & CLI_OPT_USAGE_HIDDEN) && + !(print_flags & CLI_OPT_USAGE_SHOW_HIDDEN)) continue; if (choice) @@ -140,7 +142,7 @@ int cli_opt_usage_error( const cli_opt *invalid_opt) { cli_opt_status_fprint(stderr, PROGRAM_NAME, invalid_opt); - cli_opt_usage_fprint(stderr, PROGRAM_NAME, subcommand, specs); + cli_opt_usage_fprint(stderr, PROGRAM_NAME, subcommand, specs, 0); return CLI_EXIT_USAGE; } @@ -150,12 +152,19 @@ int cli_opt_help_fprint( { git_str help = GIT_BUF_INIT; const cli_opt_spec *spec; + bool required; int error = 0; /* Display required arguments first */ for (spec = specs; spec->type; ++spec) { - if (! (spec->usage & CLI_OPT_USAGE_REQUIRED) || - (spec->usage & CLI_OPT_USAGE_HIDDEN)) + if ((spec->usage & CLI_OPT_USAGE_HIDDEN) || + (spec->type == CLI_OPT_TYPE_LITERAL)) + continue; + + required = ((spec->usage & CLI_OPT_USAGE_REQUIRED) || + ((spec->usage & CLI_OPT_USAGE_CHOICE) && required)); + + if (!required) continue; git_str_printf(&help, " "); @@ -163,13 +172,22 @@ int cli_opt_help_fprint( if ((error = print_spec_name(&help, spec)) < 0) goto done; - git_str_printf(&help, ": %s\n", spec->help); + if (spec->help) + git_str_printf(&help, ": %s", spec->help); + + git_str_printf(&help, "\n"); } /* Display the remaining arguments */ for (spec = specs; spec->type; ++spec) { - if ((spec->usage & CLI_OPT_USAGE_REQUIRED) || - (spec->usage & CLI_OPT_USAGE_HIDDEN)) + if ((spec->usage & CLI_OPT_USAGE_HIDDEN) || + (spec->type == CLI_OPT_TYPE_LITERAL)) + continue; + + required = ((spec->usage & CLI_OPT_USAGE_REQUIRED) || + ((spec->usage & CLI_OPT_USAGE_CHOICE) && required)); + + if (required) continue; git_str_printf(&help, " "); @@ -177,8 +195,10 @@ int cli_opt_help_fprint( if ((error = print_spec_name(&help, spec)) < 0) goto done; - git_str_printf(&help, ": %s\n", spec->help); + if (spec->help) + git_str_printf(&help, ": %s", spec->help); + git_str_printf(&help, "\n"); } if (git_str_oom(&help) || diff --git a/src/cli/opt_usage.h b/src/cli/opt_usage.h index c752494e1..b9b75b84b 100644 --- a/src/cli/opt_usage.h +++ b/src/cli/opt_usage.h @@ -8,6 +8,10 @@ #ifndef CLI_opt_usage_h__ #define CLI_opt_usage_h__ +typedef enum { + CLI_OPT_USAGE_SHOW_HIDDEN = (1 << 0), +} cli_opt_usage_flags; + /** * Prints usage information to the given file handle. * @@ -21,7 +25,8 @@ int cli_opt_usage_fprint( FILE *file, const char *command, const char *subcommand, - const cli_opt_spec specs[]); + const cli_opt_spec specs[], + unsigned int print_flags); int cli_opt_usage_error( const char *subcommand,