cmd: improve command usage strings

the command usage strings now use the actual argument values provided by the user, in particular for the names of relevant commands
This commit is contained in:
2025-08-09 19:36:46 +01:00
parent fae8ffe4f8
commit bcbd85372e
4 changed files with 52 additions and 25 deletions

View File

@@ -229,6 +229,8 @@ static b_status parse_arg(struct argv_parser *parser)
= b_command_get_subcommand_with_name(parser->cmd, value);
if (subcmd) {
move_to_subcommand(parser, subcmd);
parser->arglist->list_argv_last_command
= parser->index + 1;
advance(parser);
continue;
}
@@ -309,13 +311,15 @@ static b_status parse_short_opt(struct argv_parser *parser)
if (subcmd) {
move_to_subcommand(parser, subcmd);
parser->arglist->list_argv_last_command
= parser->index + 1;
flags++;
continue;
}
if (!opt) {
struct b_string *usage = z__b_command_default_usage_string(
parser->cmd, NULL);
parser->cmd, NULL, parser->arglist);
b_err("unrecognised argument '" F_YELLOW "-%c" F_RESET
"'\n\n",
flag, b_string_ptr(usage));
@@ -452,8 +456,8 @@ static b_status parse_long_opt(struct argv_parser *parser)
}
if (!opt && !subcmd) {
struct b_string *usage
= z__b_command_default_usage_string(parser->cmd, NULL);
struct b_string *usage = z__b_command_default_usage_string(
parser->cmd, NULL, parser->arglist);
b_err("unrecognised argument '" F_YELLOW "--%s" F_RESET
"'\n\nusage: %s\n\nfor more information, use '" F_YELLOW
"--help" F_RESET "'\n",
@@ -466,7 +470,8 @@ static b_status parse_long_opt(struct argv_parser *parser)
advance(parser);
if (subcmd) {
parser->cmd = subcmd;
move_to_subcommand(parser, subcmd);
parser->arglist->list_argv_last_command = parser->index + 1;
return B_SUCCESS;
}
@@ -591,8 +596,11 @@ static bool should_show_help(struct b_command *cmd, struct b_arglist *args)
b_status b_arglist_parse(
struct b_arglist *args, struct b_command **cmd, int argc, const char **argv)
{
struct argv_parser parser
= {.arglist = args, .argc = argc - 1, .argv = argv + 1};
struct argv_parser parser = {
.arglist = args,
.argc = argc - 1,
.argv = argv + 1,
};
move_to_subcommand(&parser, *cmd);

View File

@@ -352,8 +352,17 @@ static void prepend_command_name(struct b_command *cmd, b_string *out)
}
}
static void get_qualified_command_name(struct b_command *cmd, b_string *out)
static void get_qualified_command_name(
struct b_command *cmd, const struct b_arglist *args, b_string *out)
{
for (unsigned int i = 0; i <= args->list_argv_last_command; i++) {
if (i > 0) {
b_string_append_cstr(out, " ");
}
b_string_append_cstr(out, args->list_argv[i]);
}
#if 0
prepend_command_name(cmd, out);
cmd = cmd->b_parent;
@@ -362,12 +371,14 @@ static void get_qualified_command_name(struct b_command *cmd, b_string *out)
prepend_command_name(cmd, out);
cmd = cmd->b_parent;
}
#endif
}
static void get_usage_string(
struct b_command *cmd, struct b_command_usage *usage, b_string *out)
struct b_command *cmd, struct b_arglist *args,
struct b_command_usage *usage, b_string *out)
{
get_qualified_command_name(cmd, out);
get_qualified_command_name(cmd, args, out);
struct b_string *cmd_name = b_string_create();
@@ -421,10 +432,11 @@ static void get_usage_string(
}
b_string *z__b_command_default_usage_string(
struct b_command *cmd, struct b_command_option *with_opt)
struct b_command *cmd, struct b_command_option *with_opt,
const struct b_arglist *args)
{
b_string *str = b_string_create();
get_qualified_command_name(cmd, str);
get_qualified_command_name(cmd, args, str);
if (with_opt) {
b_string_append_cstr(str, " ");
@@ -848,7 +860,7 @@ struct b_command_arg *b_command_get_arg_with_id(
return NULL;
}
static void print_usage(struct b_command *cmd)
static void print_usage(struct b_command *cmd, struct b_arglist *args)
{
b_paragraph_format format = {0};
format.p_left_margin = format.p_right_margin = 4;
@@ -856,7 +868,8 @@ static void print_usage(struct b_command *cmd)
b_tty_puts(OUTPUT_STREAM, 0, F_YELLOW "USAGE:" F_RESET "\n");
if (b_queue_empty(&cmd->b_usage)) {
b_string *usage = z__b_command_default_usage_string(cmd, NULL);
b_string *usage
= z__b_command_default_usage_string(cmd, NULL, args);
b_print_paragraph(b_string_ptr(usage), OUTPUT_STREAM, &format);
b_string_release(usage);
return;
@@ -872,14 +885,14 @@ static void print_usage(struct b_command *cmd)
}
b_string_clear(str);
get_usage_string(cmd, usage, str);
get_usage_string(cmd, args, usage, str);
b_print_paragraph(b_string_ptr(str), OUTPUT_STREAM, &format);
}
b_string_release(str);
}
static void print_help(struct b_command *cmd)
static void print_help(struct b_command *cmd, struct b_arglist *args)
{
b_paragraph_format format = {0};
@@ -894,7 +907,7 @@ static void print_help(struct b_command *cmd)
b_tty_putc(OUTPUT_STREAM, 0, '\n');
print_usage(cmd);
print_usage(cmd, args);
if (!b_queue_empty(&cmd->b_opt)) {
print_options_list(cmd);
@@ -921,12 +934,12 @@ static int execute_command(struct b_command *cmd, struct b_arglist *args)
args, B_COMMAND_OPTION_HELP, B_COMMAND_INVALID_ID);
if ((cmd->b_flags & B_COMMAND_SHOW_HELP_BY_DEFAULT) && nr_items == 0) {
print_help(cmd);
print_help(cmd, args);
return 0;
}
if (nr_help > 0) {
print_help(cmd);
print_help(cmd, args);
return 0;
}
@@ -978,6 +991,8 @@ int b_command_dispatch(unsigned int cmd_id, int argc, const char **argv)
}
struct b_arglist *args = b_arglist_create();
args->list_argc = argc;
args->list_argv = argv;
args->list_command = cmd;
b_status status = b_arglist_parse(args, &cmd, argc, argv);

View File

@@ -98,6 +98,9 @@ struct b_arglist_option {
};
struct b_arglist {
size_t list_argc;
const char **list_argv;
unsigned int list_argv_last_command;
struct b_command *list_command;
struct b_btree list_options;
};
@@ -134,7 +137,8 @@ BLUE_API b_status b_arglist_parse(
BLUE_API void b_arglist_destroy(struct b_arglist *args);
BLUE_API struct b_string *z__b_command_default_usage_string(
struct b_command *cmd, struct b_command_option *with_opt);
struct b_command *cmd, struct b_command_option *with_opt,
const struct b_arglist *args);
BLUE_API void z__b_get_arg_usage_string(
struct b_command_arg *arg, bool colour, struct b_string *out);

View File

@@ -57,8 +57,8 @@ enum b_status b_arglist_report_missing_option(
enum b_status b_arglist_report_unexpected_arg(
const b_arglist *args, const char *value)
{
struct b_string *usage
= z__b_command_default_usage_string(args->list_command, NULL);
struct b_string *usage = z__b_command_default_usage_string(
args->list_command, NULL, args);
b_err("unexpected argument '" F_YELLOW "%s" F_RESET "' found.", value);
b_i("usage: %s", b_string_ptr(usage));
@@ -83,8 +83,8 @@ enum b_status b_arglist_report_invalid_arg_value(
: b_command_get_arg_with_id(args->list_command, arg_id);
}
struct b_string *usage
= z__b_command_default_usage_string(args->list_command, opt);
struct b_string *usage = z__b_command_default_usage_string(
args->list_command, opt, args);
struct b_string *opt_string = b_string_create();
if (opt) {
@@ -139,8 +139,8 @@ enum b_status b_arglist_report_missing_args(
: b_command_get_arg_with_id(args->list_command, arg_id);
}
struct b_string *usage
= z__b_command_default_usage_string(args->list_command, opt);
struct b_string *usage = z__b_command_default_usage_string(
args->list_command, opt, args);
struct b_string *opt_string = b_string_create();
if (opt) {