aboutsummaryrefslogtreecommitdiff
path: root/cli/cli.h
diff options
context:
space:
mode:
Diffstat (limited to 'cli/cli.h')
-rw-r--r--cli/cli.h23
1 files changed, 20 insertions, 3 deletions
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 <errno.h>
#include <stdbool.h>
#include <stdio.h>
@@ -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 */