From 0a770cbaf0c9509415e6dabf880bf75d25a02606 Mon Sep 17 00:00:00 2001 From: Yaroslav de la Peña Smirnov Date: Sat, 13 Sep 2025 01:18:44 +0300 Subject: cli: header with extra option implementations For now just one, `struct cli_opt_data_size`. --- cli/cli.h | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'cli/cli.h') diff --git a/cli/cli.h b/cli/cli.h index 07f0ab4..72b89c5 100644 --- a/cli/cli.h +++ b/cli/cli.h @@ -8,6 +8,8 @@ * * Copyright (c) 2025 - Yaroslav de la Peña Smirnov */ +#ifndef CLI_H +#define CLI_H #include #include #include @@ -49,7 +51,7 @@ struct cli_ctx { }; /** - * enum cli_opt_type - The type of option. + * enum cli_opt_type - The type of option key. * @__CLI_OT_NONE: unused. * @CLI_OT_FLAG: a flag option; has no value. * @CLI_OT_VALUE: a value option; it expects a value after the option key. @@ -61,17 +63,22 @@ enum cli_opt_type : uint8_t { }; /** - * struct cli_option - A flag or "option" for a command. + * struct cli_opt - A flag or "option" for a command; "abstract class". * @type: the type of the option; see `enum cli_opt_type` for more info. * @shor: short key, e.g. 'k' for "-k". * @lon: long key, e.g. "key" for "--key". * @desc: a short description of the option to be displayed in the help. + * @set: setter method; parses and sets the actual value of the option. + * + * This is an abstract class. You can use the implementations below or make your + * own by embedding this struct in your own and setting the @set method. */ struct cli_opt { enum cli_opt_type type; char shor; const char *lon; const char *desc; + [[gnu::nonnull(1)]] int (*set)(struct cli_opt *self, const char *val); }; @@ -206,6 +213,7 @@ struct cli_cmd { const char *usage; const char *help; struct cli_opt **opts; + [[gnu::nonnull]] int (*run)(const struct cli_cmd *self, const struct cli_ctx *ctx); }; @@ -225,11 +233,13 @@ struct cli { struct cli_opt **opts; }; +[[gnu::nonnull]] static inline bool arg_is_help(const char *const arg) { return !strcmp(arg, "--help") || !strcmp(arg, "help") || !strcmp(arg, "-h"); } +[[gnu::nonnull]] static void list_options(struct cli_opt **opts) { for (size_t i = 0; opts[i]; i++) { @@ -248,6 +258,7 @@ static void list_options(struct cli_opt **opts) } } +[[gnu::nonnull]] static void explain_program(const struct cli *const cli) { if (cli->header) @@ -277,6 +288,7 @@ static void explain_program(const struct cli *const cli) printf("%s\n", cli->footer); } +[[gnu::nonnull]] static void explain_command(const struct cli *const cli, const struct cli_cmd *cmd) { @@ -299,6 +311,7 @@ static void explain_command(const struct cli *const cli, printf("%s\n", cli->footer); } +[[gnu::nonnull]] static int parse_long(struct cli_ctx *ctx) { char *key = ctx->argv[0] + 2; @@ -347,6 +360,7 @@ static int parse_long(struct cli_ctx *ctx) return rc; } +[[gnu::nonnull]] static int parse_short(struct cli_ctx *ctx) { for (const char *c = ctx->argv[0] + 1; *c != '\0'; c++) { @@ -403,6 +417,7 @@ finish: return CLI_RC_OK; } +[[gnu::nonnull]] static int parse_options(struct cli_ctx *ctx) { while (ctx->argc) { @@ -433,6 +448,7 @@ static int parse_options(struct cli_ctx *ctx) return CLI_RC_OK; } +[[gnu::nonnull]] static inline int cli_cmd_run(const struct cli *const cli, const struct cli_cmd *cmd, const struct cli_ctx *global_ctx) @@ -473,7 +489,7 @@ out: * * Return: CLI_RC_OK on success, anything else on error. */ -[[maybe_unused]] +[[maybe_unused, gnu::nonnull]] static int cli_run(struct cli *const cli, int argc, char *argv[]) { cli->binary = cli->binary ?: argv[0]; @@ -514,3 +530,4 @@ out: explain_program(cli); return rc; } +#endif /* CLI_H */ -- cgit v1.2.3