From fde3d979ace97bd109fce443b49cbbfa5a9307a2 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 31 Dec 2022 16:53:39 +0000 Subject: cli: Improve help output for enum arguments --- test/cli.c | 96 +++++++++++++++++++++++++++++++++++++++++++++----------------- test/cli.h | 13 +++++---- 2 files changed, 78 insertions(+), 31 deletions(-) diff --git a/test/cli.c b/test/cli.c index e1d1a8b..8f32228 100644 --- a/test/cli.c +++ b/test/cli.c @@ -641,46 +641,90 @@ static size_t cli__terminal_width(void) } /** - * Print an entry's description, with a given indent. + * Print a wrapped string, with a given indent. * * The indent is assumed to already be applied for the first line of the * output by the caller. - * - * \param[in] entry The entry to print the description for. + * + * \param[in] str The string to print. * \param[in] indent The number of spaces to pad the left margin with. */ -static void cli__print_description(const struct cli_table_entry *entry, - size_t indent) +static void cli__print_wrapping_string(const char *str, size_t indent) { size_t terminal_width = cli__terminal_width(); size_t avail = (indent > terminal_width) ? 0 : terminal_width - indent; size_t space = avail; - const char *desc = entry->d; - - if (desc != NULL) { - while (*desc != '\0') { - size_t word_len = strcspn(desc, " \n\t"); - if (word_len <= space || space == avail) { - fprintf(stderr, "%*.*s", - (int)word_len, - (int)word_len, desc); - desc += word_len; - if (word_len <= space) { - space -= word_len; - } - if (space > 0) { - fprintf(stderr, " "); - space--; - } - } else { - fprintf(stderr, "\n%*s", (int)indent, ""); - space = avail; + + while (*str != '\0') { + size_t word_len = strcspn(str, " \n\t"); + if (word_len <= space || space == avail) { + fprintf(stderr, "%*.*s", + (int)word_len, + (int)word_len, str); + str += word_len; + if (word_len <= space) { + space -= word_len; + } + if (space > 0) { + fprintf(stderr, " "); + space--; } - desc += strspn(desc, " \n\t"); + } else { + fprintf(stderr, "\n%*s", (int)indent, ""); + space = avail; } + str += strspn(str, " \n\t"); + } +} + +/** + * Print an entry's description, with a given indent. + * + * The indent is assumed to already be applied for the first line of the + * output by the caller. + * + * \param[in] entry The entry to print the description for. + * \param[in] indent The number of spaces to pad the left margin with. + */ +static void cli__print_description(const struct cli_table_entry *entry, + size_t indent) +{ + if (entry->d != NULL) { + cli__print_wrapping_string(entry->d, indent); } fprintf(stderr, "\n"); + + if (entry->t == CLI_ENUM) { + size_t max_len = 0; + + for (const struct cli_str_val *e = entry->v.e.desc; + e->str != NULL; e++) { + size_t len = strlen(e->str); + if (max_len < len) { + max_len = len; + } + } + + fprintf(stderr, "\n"); + + for (const struct cli_str_val *e = entry->v.e.desc; + e->str != NULL; e++) { + fprintf(stderr, " "); + + if (e->d == NULL || e->d[0] == '\0') { + fprintf(stderr, "%s\n", + e->str); + } else { + fprintf(stderr, "%-*s - ", + (int)(max_len), + e->str); + cli__print_wrapping_string(e->d, + 8 + max_len + 3); + fprintf(stderr, "\n"); + } + } + } } /* Documented in cli.h */ diff --git a/test/cli.h b/test/cli.h index ec14d1e..d7493e4 100644 --- a/test/cli.h +++ b/test/cli.h @@ -34,13 +34,16 @@ enum cli_arg_type { CLI_STRING, /**< Has string value. */ }; +/** Enum value descriptor. */ struct cli_str_val { - const char *str; - int64_t val; + const char *str; /**< String for the enum value name. */ + int64_t val; /**< The value for this string. */ + const char *d; /**< Description of this value for help output. */ }; +/** Enum data. */ struct cli_enum { - const struct cli_str_val *desc; + const struct cli_str_val *desc; /**< Array describing enum values. */ int64_t *e; /**< Location to store \ref CLI_ENUM value. */ }; @@ -58,9 +61,9 @@ struct cli_table_entry { int64_t *i; /**< Location to store \ref CLI_INT value. */ uint64_t *u; /**< Location to store \ref CLI_UINT value. */ const char **s; /**< Location to store \ref CLI_STRING value. */ - struct cli_enum e; + struct cli_enum e; /**< \ref CLI_ENUM value details. */ } v; /**< Where to store type-specific values. */ - const char *d; /**< Description. */ + const char *d; /**< Description of this argument for help output. */ }; /** -- cgit v1.2.1