cmd: add functions to report option/arg errors to the public API
This commit is contained in:
240
cmd/arglist.c
240
cmd/arglist.c
@@ -65,6 +65,7 @@ struct b_arglist *b_arglist_create(void)
|
|||||||
static void move_to_subcommand(struct argv_parser *parser, struct b_command *cmd)
|
static void move_to_subcommand(struct argv_parser *parser, struct b_command *cmd)
|
||||||
{
|
{
|
||||||
parser->cmd = cmd;
|
parser->cmd = cmd;
|
||||||
|
parser->arglist->list_command = cmd;
|
||||||
b_queue_iterator_begin(&cmd->b_arg, &parser->arg_it);
|
b_queue_iterator_begin(&cmd->b_arg, &parser->arg_it);
|
||||||
parser->nr_values_cur_arg = 0;
|
parser->nr_values_cur_arg = 0;
|
||||||
}
|
}
|
||||||
@@ -84,48 +85,6 @@ static b_status set_opt(struct b_arglist *args, struct b_command_option *opt)
|
|||||||
return B_SUCCESS;
|
return B_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void report_invalid_arg_value(
|
|
||||||
struct argv_parser *parser, struct b_command_option *opt,
|
|
||||||
struct b_command_arg *arg, const char *value)
|
|
||||||
{
|
|
||||||
struct b_string *usage
|
|
||||||
= z__b_command_default_usage_string(parser->cmd, opt);
|
|
||||||
struct b_string *opt_string = b_string_create();
|
|
||||||
|
|
||||||
if (opt) {
|
|
||||||
z__b_get_option_usage_string(opt, 0, opt_string);
|
|
||||||
} else {
|
|
||||||
z__b_get_arg_usage_string(arg, 0, opt_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_err("invalid value '" F_YELLOW "%s" F_RESET "' for '" F_YELLOW
|
|
||||||
"%s" F_RESET "'.",
|
|
||||||
value, b_string_ptr(opt_string));
|
|
||||||
|
|
||||||
if (opt) {
|
|
||||||
b_i("'" F_YELLOW "%s" F_RESET
|
|
||||||
"' accepts the following values for '" F_YELLOW "%s" F_RESET
|
|
||||||
"':",
|
|
||||||
b_string_ptr(opt_string), arg->arg_name);
|
|
||||||
} else {
|
|
||||||
b_i("'" F_YELLOW "%s" F_RESET "' accepts the following values:",
|
|
||||||
b_string_ptr(opt_string));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; arg->arg_allowed_values[i]; i++) {
|
|
||||||
b_printf(
|
|
||||||
" * " F_GREEN "%s" F_RESET "\n",
|
|
||||||
arg->arg_allowed_values[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_printf("\n");
|
|
||||||
b_i("usage: %s", b_string_ptr(usage));
|
|
||||||
b_i("for more information, use '" F_YELLOW "--help" F_RESET);
|
|
||||||
|
|
||||||
b_string_release(usage);
|
|
||||||
b_string_release(opt_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status put_arg(
|
static b_status put_arg(
|
||||||
struct b_arglist *args, struct b_command_arg *arg, const char *value)
|
struct b_arglist *args, struct b_command_arg *arg, const char *value)
|
||||||
{
|
{
|
||||||
@@ -209,70 +168,17 @@ static b_status put_opt_arg(
|
|||||||
return B_SUCCESS;
|
return B_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void report_missing_args(
|
static void report_missing_args(
|
||||||
struct argv_parser *parser, struct b_command_option *opt,
|
struct argv_parser *parser, struct b_command_option *opt,
|
||||||
struct b_command_arg *arg, int args_supplied)
|
struct b_command_arg *arg, int args_supplied)
|
||||||
{
|
{
|
||||||
struct b_string *usage
|
|
||||||
= z__b_command_default_usage_string(parser->cmd, opt);
|
|
||||||
struct b_string *opt_string = b_string_create();
|
|
||||||
|
|
||||||
if (opt) {
|
|
||||||
z__b_get_option_usage_string(opt, 0, opt_string);
|
|
||||||
} else {
|
|
||||||
z__b_get_arg_usage_string(arg, 0, opt_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
char supplied_arg_str[64];
|
|
||||||
if (args_supplied == 0) {
|
|
||||||
snprintf(
|
|
||||||
supplied_arg_str, sizeof supplied_arg_str,
|
|
||||||
F_RED_BOLD "none" F_RESET " were provided");
|
|
||||||
} else if (args_supplied == 1) {
|
|
||||||
snprintf(
|
|
||||||
supplied_arg_str, sizeof supplied_arg_str,
|
|
||||||
"only " F_YELLOW_BOLD "%d" F_RESET " was provided",
|
|
||||||
args_supplied);
|
|
||||||
} else {
|
|
||||||
snprintf(
|
|
||||||
supplied_arg_str, sizeof supplied_arg_str,
|
|
||||||
"only " F_YELLOW_BOLD "%d" F_RESET " were provided",
|
|
||||||
args_supplied);
|
|
||||||
}
|
|
||||||
|
|
||||||
char required_arg_count[64];
|
|
||||||
switch (arg->arg_nr_values) {
|
|
||||||
case B_ARG_1_OR_MORE_VALUES:
|
|
||||||
snprintf(
|
|
||||||
required_arg_count, sizeof required_arg_count,
|
|
||||||
"one or more");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
snprintf(
|
|
||||||
required_arg_count, sizeof required_arg_count, "%d",
|
|
||||||
arg->arg_nr_values);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_err("argument '" F_YELLOW "%s" F_RESET "' requires " F_GREEN_BOLD
|
|
||||||
"%s" F_RESET " `" F_YELLOW "%s" F_RESET "` values, but %s.\n\n",
|
|
||||||
b_string_ptr(opt_string), required_arg_count, arg->arg_name,
|
|
||||||
supplied_arg_str);
|
|
||||||
b_i("usage: %s", b_string_ptr(usage));
|
|
||||||
b_i("for more information, use '" F_YELLOW "--help" F_RESET "'");
|
|
||||||
|
|
||||||
b_string_release(usage);
|
|
||||||
b_string_release(opt_string);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void report_unexpected_arg(struct argv_parser *parser, const char *value)
|
static void report_unexpected_arg(struct argv_parser *parser, const char *value)
|
||||||
{
|
{
|
||||||
struct b_string *usage
|
|
||||||
= z__b_command_default_usage_string(parser->cmd, NULL);
|
|
||||||
|
|
||||||
b_err("unexpected argument '" F_YELLOW "%s" F_RESET "' found.", value);
|
|
||||||
b_i("usage: %s", b_string_ptr(usage));
|
|
||||||
b_i("for more information, use '" F_YELLOW "--help" F_RESET "'");
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static b_status check_required_args(struct argv_parser *parser)
|
static b_status check_required_args(struct argv_parser *parser)
|
||||||
{
|
{
|
||||||
@@ -295,12 +201,16 @@ static b_status check_required_args(struct argv_parser *parser)
|
|||||||
return B_SUCCESS;
|
return B_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_missing_args(parser, NULL, arg, parser->nr_values_cur_arg);
|
b_arglist_report_missing_args(
|
||||||
|
parser->arglist, B_COMMAND_INVALID_ID, arg->arg_id,
|
||||||
|
parser->nr_values_cur_arg);
|
||||||
return B_ERR_BAD_FORMAT;
|
return B_ERR_BAD_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser->nr_values_cur_arg != arg->arg_nr_values) {
|
if (parser->nr_values_cur_arg != arg->arg_nr_values) {
|
||||||
report_missing_args(parser, NULL, arg, parser->nr_values_cur_arg);
|
b_arglist_report_missing_args(
|
||||||
|
parser->arglist, B_COMMAND_INVALID_ID, arg->arg_id,
|
||||||
|
parser->nr_values_cur_arg);
|
||||||
return B_ERR_BAD_FORMAT;
|
return B_ERR_BAD_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +237,7 @@ static b_status parse_arg(struct argv_parser *parser)
|
|||||||
struct b_command_arg, parser->arg_it.entry, arg_entry);
|
struct b_command_arg, parser->arg_it.entry, arg_entry);
|
||||||
|
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
report_unexpected_arg(parser, value);
|
b_arglist_report_unexpected_arg(parser->arglist, value);
|
||||||
return B_ERR_BAD_FORMAT;
|
return B_ERR_BAD_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +246,9 @@ static b_status parse_arg(struct argv_parser *parser)
|
|||||||
advance(parser);
|
advance(parser);
|
||||||
|
|
||||||
if (status == B_ERR_INVALID_ARGUMENT) {
|
if (status == B_ERR_INVALID_ARGUMENT) {
|
||||||
report_invalid_arg_value(parser, NULL, arg, value);
|
b_arglist_report_invalid_arg_value(
|
||||||
|
parser->arglist, B_COMMAND_INVALID_ID,
|
||||||
|
arg->arg_id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (B_ERR(status)) {
|
if (B_ERR(status)) {
|
||||||
@@ -471,7 +383,9 @@ static b_status parse_short_opt(struct argv_parser *parser)
|
|||||||
nr_args_cur_opt++;
|
nr_args_cur_opt++;
|
||||||
|
|
||||||
if (status == B_ERR_INVALID_ARGUMENT) {
|
if (status == B_ERR_INVALID_ARGUMENT) {
|
||||||
report_invalid_arg_value(parser, NULL, arg, value);
|
b_arglist_report_invalid_arg_value(
|
||||||
|
parser->arglist, B_COMMAND_INVALID_ID,
|
||||||
|
arg->arg_id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (B_ERR(status)) {
|
if (B_ERR(status)) {
|
||||||
@@ -498,7 +412,9 @@ static b_status parse_short_opt(struct argv_parser *parser)
|
|||||||
goto next_value;
|
goto next_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_missing_args(parser, opt, arg, nr_args_cur_opt);
|
b_arglist_report_missing_args(
|
||||||
|
parser->arglist, opt->opt_id, arg->arg_id,
|
||||||
|
nr_args_cur_opt);
|
||||||
return B_ERR_BAD_FORMAT;
|
return B_ERR_BAD_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +425,9 @@ static b_status parse_short_opt(struct argv_parser *parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
report_missing_args(parser, opt, arg, nr_args_cur_opt);
|
b_arglist_report_missing_args(
|
||||||
|
parser->arglist, opt->opt_id, arg->arg_id,
|
||||||
|
nr_args_cur_opt);
|
||||||
return B_ERR_BAD_FORMAT;
|
return B_ERR_BAD_FORMAT;
|
||||||
}
|
}
|
||||||
next_value:
|
next_value:
|
||||||
@@ -594,7 +512,9 @@ static b_status parse_long_opt(struct argv_parser *parser)
|
|||||||
advance(parser);
|
advance(parser);
|
||||||
|
|
||||||
if (status == B_ERR_INVALID_ARGUMENT) {
|
if (status == B_ERR_INVALID_ARGUMENT) {
|
||||||
report_invalid_arg_value(parser, NULL, arg, value);
|
b_arglist_report_invalid_arg_value(
|
||||||
|
parser->arglist, B_COMMAND_INVALID_ID,
|
||||||
|
arg->arg_id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (B_ERR(status)) {
|
if (B_ERR(status)) {
|
||||||
@@ -621,7 +541,9 @@ static b_status parse_long_opt(struct argv_parser *parser)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_missing_args(parser, opt, arg, nr_args_cur_opt);
|
b_arglist_report_missing_args(
|
||||||
|
parser->arglist, opt->opt_id, arg->arg_id,
|
||||||
|
nr_args_cur_opt);
|
||||||
return B_ERR_BAD_FORMAT;
|
return B_ERR_BAD_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,7 +554,9 @@ static b_status parse_long_opt(struct argv_parser *parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
report_missing_args(parser, opt, arg, nr_args_cur_opt);
|
b_arglist_report_missing_args(
|
||||||
|
parser->arglist, opt->opt_id, arg->arg_id,
|
||||||
|
nr_args_cur_opt);
|
||||||
return B_ERR_BAD_FORMAT;
|
return B_ERR_BAD_FORMAT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -882,6 +806,8 @@ b_status b_arglist_option_get_value(
|
|||||||
return B_ERR_NO_ENTRY;
|
return B_ERR_NO_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************ arglist iterator functions **************************/
|
||||||
|
|
||||||
static bool arglist_iterator_next(struct b_iterator *it)
|
static bool arglist_iterator_next(struct b_iterator *it)
|
||||||
{
|
{
|
||||||
return b_arglist_iterator_next((struct b_arglist_iterator *)it);
|
return b_arglist_iterator_next((struct b_arglist_iterator *)it);
|
||||||
@@ -1043,3 +969,103 @@ bool b_arglist_iterator_is_valid(const struct b_arglist_iterator *it)
|
|||||||
{
|
{
|
||||||
return it->opt_id != B_COMMAND_INVALID_ID || it->value != NULL;
|
return it->opt_id != B_COMMAND_INVALID_ID || it->value != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************* arglist option iterator functions **********************/
|
||||||
|
|
||||||
|
static bool arglist_option_iterator_next(struct b_iterator *it)
|
||||||
|
{
|
||||||
|
return b_arglist_option_iterator_next(
|
||||||
|
(struct b_arglist_option_iterator *)it);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool arglist_option_iterator_is_valid(const struct b_iterator *it)
|
||||||
|
{
|
||||||
|
return b_arglist_option_iterator_is_valid(
|
||||||
|
(const struct b_arglist_option_iterator *)it);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct b_arglist_option *advance_to_next_opt2(
|
||||||
|
struct b_arglist_option_iterator *it)
|
||||||
|
{
|
||||||
|
struct b_arglist_option *opt;
|
||||||
|
|
||||||
|
// b_btree_iterator_next(&it->_opt_it);
|
||||||
|
|
||||||
|
while (b_btree_iterator_is_valid(&it->_opt_it)) {
|
||||||
|
opt = b_unbox(struct b_arglist_option, it->_opt_it.node, opt_node);
|
||||||
|
if (opt
|
||||||
|
&& (opt->opt_id == it->_opt_filter
|
||||||
|
|| it->_opt_filter == B_COMMAND_INVALID_ID)) {
|
||||||
|
it->opt_id = opt->opt_id;
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
|
||||||
|
b_btree_iterator_next(&it->_opt_it);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static b_iterator_ops option_it_ops = {
|
||||||
|
.it_next = arglist_option_iterator_next,
|
||||||
|
.it_is_valid = arglist_option_iterator_is_valid,
|
||||||
|
};
|
||||||
|
|
||||||
|
int b_arglist_option_iterator_begin(
|
||||||
|
const struct b_arglist *args, unsigned int opt_filter,
|
||||||
|
struct b_arglist_option_iterator *it)
|
||||||
|
{
|
||||||
|
memset(it, 0x0, sizeof *it);
|
||||||
|
|
||||||
|
it->opt_id = B_COMMAND_INVALID_ID;
|
||||||
|
|
||||||
|
it->_base.it_ops = &it_ops;
|
||||||
|
it->_opt_filter = opt_filter;
|
||||||
|
|
||||||
|
b_btree_iterator_begin(&args->list_options, &it->_opt_it);
|
||||||
|
struct b_arglist_option *opt = NULL;
|
||||||
|
struct b_arglist_value *val = NULL;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (!b_btree_iterator_is_valid(&it->_opt_it)) {
|
||||||
|
opt = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
opt = b_unbox(struct b_arglist_option, it->_opt_it.node, opt_node);
|
||||||
|
if (opt
|
||||||
|
&& (opt_filter == opt->opt_id
|
||||||
|
|| opt_filter == B_COMMAND_INVALID_ID)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
b_btree_iterator_next(&it->_opt_it);
|
||||||
|
}
|
||||||
|
|
||||||
|
it->opt_id = opt->opt_id;
|
||||||
|
it->opt = opt;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool b_arglist_option_iterator_next(struct b_arglist_option_iterator *it)
|
||||||
|
{
|
||||||
|
struct b_arglist_option *opt;
|
||||||
|
struct b_arglist_value *val;
|
||||||
|
|
||||||
|
b_btree_iterator_next(&it->_opt_it);
|
||||||
|
opt = advance_to_next_opt2(it);
|
||||||
|
if (!opt) {
|
||||||
|
it->opt = NULL;
|
||||||
|
it->opt_id = B_COMMAND_INVALID_ID;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->opt = opt;
|
||||||
|
it->opt_id = opt->opt_id;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool b_arglist_option_iterator_is_valid(const struct b_arglist_option_iterator *it)
|
||||||
|
{
|
||||||
|
return it->opt_id != B_COMMAND_INVALID_ID || it->opt != NULL;
|
||||||
|
}
|
||||||
|
|||||||
153
cmd/command.c
153
cmd/command.c
@@ -55,10 +55,10 @@ static void command_usage_destroy(struct b_command_usage *usage)
|
|||||||
{
|
{
|
||||||
struct b_queue_iterator it = {0};
|
struct b_queue_iterator it = {0};
|
||||||
|
|
||||||
b_queue_iterator_begin(&usage->u_arg, &it);
|
b_queue_iterator_begin(&usage->u_parts, &it);
|
||||||
while (b_queue_iterator_is_valid(&it)) {
|
while (b_queue_iterator_is_valid(&it)) {
|
||||||
struct b_command_usage_arg *arg = b_unbox(
|
struct b_command_usage_entry *arg = b_unbox(
|
||||||
struct b_command_usage_arg, it.entry, arg_entry);
|
struct b_command_usage_entry, it.entry, e_entry);
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -67,18 +67,6 @@ static void command_usage_destroy(struct b_command_usage *usage)
|
|||||||
free(arg);
|
free(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
b_queue_iterator_begin(&usage->u_opt, &it);
|
|
||||||
while (b_queue_iterator_is_valid(&it)) {
|
|
||||||
struct b_command_usage_opt *opt = b_unbox(
|
|
||||||
struct b_command_usage_opt, it.entry, opt_entry);
|
|
||||||
if (!opt) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_queue_iterator_erase(&it);
|
|
||||||
free(opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(usage);
|
free(usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,47 +265,50 @@ struct b_command_usage *b_command_add_usage(struct b_command *cmd)
|
|||||||
b_status b_command_usage_add_option(
|
b_status b_command_usage_add_option(
|
||||||
struct b_command_usage *usage, struct b_command_option *opt)
|
struct b_command_usage *usage, struct b_command_option *opt)
|
||||||
{
|
{
|
||||||
struct b_command_usage_opt *u_opt = malloc(sizeof *u_opt);
|
struct b_command_usage_entry *u_opt = malloc(sizeof *u_opt);
|
||||||
if (!u_opt) {
|
if (!u_opt) {
|
||||||
return B_ERR_NO_MEMORY;
|
return B_ERR_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(u_opt, 0x0, sizeof *u_opt);
|
memset(u_opt, 0x0, sizeof *u_opt);
|
||||||
|
|
||||||
u_opt->opt = opt;
|
u_opt->e_type = CMD_USAGE_OPT;
|
||||||
|
u_opt->e_opt = opt;
|
||||||
|
|
||||||
b_queue_push_back(&usage->u_opt, &u_opt->opt_entry);
|
b_queue_push_back(&usage->u_parts, &u_opt->e_entry);
|
||||||
return B_SUCCESS;
|
return B_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
b_status b_command_usage_add_arg(
|
b_status b_command_usage_add_arg(
|
||||||
struct b_command_usage *usage, struct b_command_arg *arg)
|
struct b_command_usage *usage, struct b_command_arg *arg)
|
||||||
{
|
{
|
||||||
struct b_command_usage_arg *u_arg = malloc(sizeof *u_arg);
|
struct b_command_usage_entry *u_arg = malloc(sizeof *u_arg);
|
||||||
if (!u_arg) {
|
if (!u_arg) {
|
||||||
return B_ERR_NO_MEMORY;
|
return B_ERR_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(u_arg, 0x0, sizeof *u_arg);
|
memset(u_arg, 0x0, sizeof *u_arg);
|
||||||
|
|
||||||
u_arg->arg = arg;
|
u_arg->e_type = CMD_USAGE_ARG;
|
||||||
|
u_arg->e_arg = arg;
|
||||||
|
|
||||||
b_queue_push_back(&usage->u_arg, &u_arg->arg_entry);
|
b_queue_push_back(&usage->u_parts, &u_arg->e_entry);
|
||||||
return B_SUCCESS;
|
return B_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
b_status b_command_usage_add_command(b_command_usage *usage, unsigned int cmd_id)
|
b_status b_command_usage_add_command(b_command_usage *usage, unsigned int cmd_id)
|
||||||
{
|
{
|
||||||
struct b_command_usage_command *u_cmd = malloc(sizeof *u_cmd);
|
struct b_command_usage_entry *u_cmd = malloc(sizeof *u_cmd);
|
||||||
if (!u_cmd) {
|
if (!u_cmd) {
|
||||||
return B_ERR_NO_MEMORY;
|
return B_ERR_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(u_cmd, 0x0, sizeof *u_cmd);
|
memset(u_cmd, 0x0, sizeof *u_cmd);
|
||||||
|
|
||||||
u_cmd->cmd_id = cmd_id;
|
u_cmd->e_type = CMD_USAGE_COMMAND;
|
||||||
|
u_cmd->e_cmd_id = cmd_id;
|
||||||
|
|
||||||
b_queue_push_back(&usage->u_cmd, &u_cmd->cmd_entry);
|
b_queue_push_back(&usage->u_parts, &u_cmd->e_entry);
|
||||||
return B_SUCCESS;
|
return B_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,66 +372,52 @@ static void get_usage_string(
|
|||||||
struct b_string *cmd_name = b_string_create();
|
struct b_string *cmd_name = b_string_create();
|
||||||
|
|
||||||
b_queue_iterator it;
|
b_queue_iterator it;
|
||||||
b_queue_foreach (&it, &usage->u_cmd) {
|
b_queue_foreach (&it, &usage->u_parts) {
|
||||||
struct b_command_usage_command *subcmd = b_unbox(
|
struct b_command_usage_entry *entry = b_unbox(
|
||||||
struct b_command_usage_command, it.entry, cmd_entry);
|
struct b_command_usage_entry, it.entry, e_entry);
|
||||||
|
|
||||||
if (!subcmd) {
|
if (!entry) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
b_string_clear(cmd_name);
|
b_string_clear(cmd_name);
|
||||||
b_string_append_cstr(out, " ");
|
b_string_append_cstr(out, " ");
|
||||||
|
|
||||||
if (subcmd->cmd_id == B_COMMAND_INVALID_ID) {
|
switch (entry->e_type) {
|
||||||
b_string_append_cstr(out, "[COMMAND]");
|
case CMD_USAGE_ARG:
|
||||||
|
if (entry->e_arg) {
|
||||||
|
z__b_get_arg_usage_string(entry->e_arg, false, out);
|
||||||
} else {
|
} else {
|
||||||
|
b_string_append_cstr(out, "[[ARGS]");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CMD_USAGE_OPT:
|
||||||
|
if (entry->e_opt) {
|
||||||
|
z__b_get_option_usage_string(
|
||||||
|
entry->e_opt, CMD_STR_DIRECT_USAGE, out);
|
||||||
|
} else {
|
||||||
|
b_string_append_cstr(out, "[[OPTIONS]");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case CMD_USAGE_COMMAND:
|
||||||
|
if (entry->e_cmd_id == B_COMMAND_INVALID_ID) {
|
||||||
|
b_string_append_cstr(out, "[[COMMAND]");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
struct b_command *subcmd_info
|
struct b_command *subcmd_info
|
||||||
= get_command(&command_list, subcmd->cmd_id);
|
= get_command(&command_list, entry->e_cmd_id);
|
||||||
prepend_command_name(subcmd_info, cmd_name);
|
prepend_command_name(subcmd_info, cmd_name);
|
||||||
|
|
||||||
b_string_append_s(out, cmd_name);
|
b_string_append_s(out, cmd_name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b_string_release(cmd_name);
|
b_string_release(cmd_name);
|
||||||
|
|
||||||
b_queue_foreach (&it, &usage->u_opt) {
|
|
||||||
struct b_command_usage_opt *opt = b_unbox(
|
|
||||||
struct b_command_usage_opt, it.entry, opt_entry);
|
|
||||||
|
|
||||||
if (!opt) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_string_append_cstr(out, " ");
|
|
||||||
|
|
||||||
if (opt->opt
|
|
||||||
== (struct b_command_option *)(uintptr_t)B_COMMAND_INVALID_ID) {
|
|
||||||
b_string_append_cstr(out, "[OPTIONS]");
|
|
||||||
} else {
|
|
||||||
z__b_get_option_usage_string(
|
|
||||||
opt->opt, CMD_STR_DIRECT_USAGE, out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b_queue_foreach (&it, &usage->u_arg) {
|
|
||||||
struct b_command_usage_arg *arg = b_unbox(
|
|
||||||
struct b_command_usage_arg, it.entry, arg_entry);
|
|
||||||
|
|
||||||
if (!arg) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_string_append_cstr(out, " ");
|
|
||||||
|
|
||||||
if (arg->arg
|
|
||||||
== (struct b_command_arg *)(uintptr_t)B_COMMAND_INVALID_ID) {
|
|
||||||
b_string_append_cstr(out, "[ARGS]");
|
|
||||||
} else {
|
|
||||||
z__b_get_arg_usage_string(arg->arg, false, out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b_string *z__b_command_default_usage_string(
|
b_string *z__b_command_default_usage_string(
|
||||||
@@ -833,6 +810,44 @@ struct b_command_option *b_command_get_option_with_short_name(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct b_command_option *b_command_get_option_with_id(
|
||||||
|
struct b_command *cmd, unsigned int id)
|
||||||
|
{
|
||||||
|
b_queue_iterator it;
|
||||||
|
b_queue_foreach (&it, &cmd->b_opt) {
|
||||||
|
struct b_command_option *opt
|
||||||
|
= b_unbox(struct b_command_option, it.entry, opt_entry);
|
||||||
|
if (!opt) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt->opt_id == id) {
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct b_command_arg *b_command_get_arg_with_id(
|
||||||
|
struct b_command *cmd, unsigned int id)
|
||||||
|
{
|
||||||
|
b_queue_iterator it;
|
||||||
|
b_queue_foreach (&it, &cmd->b_arg) {
|
||||||
|
struct b_command_arg *arg
|
||||||
|
= b_unbox(struct b_command_arg, it.entry, arg_entry);
|
||||||
|
if (!arg) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg->arg_id == id) {
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void print_usage(struct b_command *cmd)
|
static void print_usage(struct b_command *cmd)
|
||||||
{
|
{
|
||||||
b_paragraph_format format = {0};
|
b_paragraph_format format = {0};
|
||||||
@@ -963,6 +978,8 @@ int b_command_dispatch(unsigned int cmd_id, int argc, const char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct b_arglist *args = b_arglist_create();
|
struct b_arglist *args = b_arglist_create();
|
||||||
|
args->list_command = cmd;
|
||||||
|
|
||||||
b_status status = b_arglist_parse(args, &cmd, argc, argv);
|
b_status status = b_arglist_parse(args, &cmd, argc, argv);
|
||||||
if (B_ERR(status)) {
|
if (B_ERR(status)) {
|
||||||
b_arglist_destroy(args);
|
b_arglist_destroy(args);
|
||||||
|
|||||||
@@ -19,6 +19,13 @@ enum cmd_string_flags {
|
|||||||
CMD_STR_DIRECT_USAGE = 0x02u,
|
CMD_STR_DIRECT_USAGE = 0x02u,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum b_command_usage_entry_type {
|
||||||
|
CMD_USAGE_NONE = 0,
|
||||||
|
CMD_USAGE_ARG,
|
||||||
|
CMD_USAGE_OPT,
|
||||||
|
CMD_USAGE_COMMAND,
|
||||||
|
};
|
||||||
|
|
||||||
struct b_string;
|
struct b_string;
|
||||||
|
|
||||||
struct b_command {
|
struct b_command {
|
||||||
@@ -41,28 +48,22 @@ struct b_command {
|
|||||||
struct b_btree_node b_node;
|
struct b_btree_node b_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct b_command_usage_opt {
|
struct b_command_usage_entry {
|
||||||
struct b_queue_entry opt_entry;
|
struct b_queue_entry e_entry;
|
||||||
struct b_command_option *opt;
|
enum b_command_usage_entry_type e_type;
|
||||||
};
|
|
||||||
|
|
||||||
struct b_command_usage_arg {
|
union {
|
||||||
struct b_queue_entry arg_entry;
|
struct b_command_option *e_opt;
|
||||||
struct b_command_arg *arg;
|
struct b_command_arg *e_arg;
|
||||||
|
unsigned int e_cmd_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct b_command_usage_command {
|
|
||||||
struct b_queue_entry cmd_entry;
|
|
||||||
unsigned int cmd_id;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct b_command_usage {
|
struct b_command_usage {
|
||||||
b_command_usage_flags u_flags;
|
b_command_usage_flags u_flags;
|
||||||
struct b_queue_entry u_entry;
|
struct b_queue_entry u_entry;
|
||||||
|
|
||||||
struct b_queue u_cmd;
|
struct b_queue u_parts;
|
||||||
struct b_queue u_opt;
|
|
||||||
struct b_queue u_arg;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct b_command_option {
|
struct b_command_option {
|
||||||
@@ -97,6 +98,7 @@ struct b_arglist_option {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct b_arglist {
|
struct b_arglist {
|
||||||
|
struct b_command *list_command;
|
||||||
struct b_btree list_options;
|
struct b_btree list_options;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,6 +113,13 @@ BLUE_API struct b_command_option *b_command_get_option_with_long_name(
|
|||||||
struct b_command *cmd, const char *long_name);
|
struct b_command *cmd, const char *long_name);
|
||||||
BLUE_API struct b_command_option *b_command_get_option_with_short_name(
|
BLUE_API struct b_command_option *b_command_get_option_with_short_name(
|
||||||
struct b_command *cmd, char short_name);
|
struct b_command *cmd, char short_name);
|
||||||
|
BLUE_API struct b_command_option *b_command_get_option_with_id(
|
||||||
|
struct b_command *cmd, unsigned int id);
|
||||||
|
BLUE_API struct b_command_arg *b_command_get_arg_with_id(
|
||||||
|
struct b_command *cmd, unsigned int id);
|
||||||
|
|
||||||
|
BLUE_API struct b_command_arg *b_command_option_get_arg_with_id(
|
||||||
|
struct b_command_option *opt, unsigned int id);
|
||||||
|
|
||||||
BLUE_API struct b_command_option *b_command_option_create(void);
|
BLUE_API struct b_command_option *b_command_option_create(void);
|
||||||
BLUE_API void b_command_option_destroy(struct b_command_option *opt);
|
BLUE_API void b_command_option_destroy(struct b_command_option *opt);
|
||||||
|
|||||||
@@ -19,6 +19,18 @@
|
|||||||
= b_arglist_iterator_begin(q, opt_id, arg_id, (it)); \
|
= b_arglist_iterator_begin(q, opt_id, arg_id, (it)); \
|
||||||
b_arglist_iterator_is_valid(it); b_arglist_iterator_next(it))
|
b_arglist_iterator_is_valid(it); b_arglist_iterator_next(it))
|
||||||
|
|
||||||
|
#define b_arglist_option_foreach(it, q) \
|
||||||
|
for (int z__b_unique_name() \
|
||||||
|
= b_arglist_option_iterator_begin(q, B_COMMAND_INVALID_ID, (it)); \
|
||||||
|
b_arglist_option_iterator_is_valid(it); \
|
||||||
|
b_arglist_option_iterator_next(it))
|
||||||
|
|
||||||
|
#define b_arglist_option_foreach_filtered(it, q, opt_id) \
|
||||||
|
for (int z__b_unique_name() \
|
||||||
|
= b_arglist_option_iterator_begin(q, opt_id, (it)); \
|
||||||
|
b_arglist_option_iterator_is_valid(it); \
|
||||||
|
b_arglist_option_iterator_next(it))
|
||||||
|
|
||||||
#define B_COMMAND(id, parent_id) \
|
#define B_COMMAND(id, parent_id) \
|
||||||
static b_command *command_##id = NULL; \
|
static b_command *command_##id = NULL; \
|
||||||
static void __init_##id( \
|
static void __init_##id( \
|
||||||
@@ -105,15 +117,13 @@
|
|||||||
b_command_usage_add_option(this_usage, opt_##opt_id)
|
b_command_usage_add_option(this_usage, opt_##opt_id)
|
||||||
|
|
||||||
#define B_COMMAND_USAGE_OPT_PLACEHOLDER() \
|
#define B_COMMAND_USAGE_OPT_PLACEHOLDER() \
|
||||||
b_command_usage_add_option( \
|
b_command_usage_add_option(this_usage, NULL)
|
||||||
this_usage, (struct b_command_option *)B_COMMAND_INVALID_ID)
|
|
||||||
|
|
||||||
#define B_COMMAND_USAGE_ARG(opt_id) \
|
#define B_COMMAND_USAGE_ARG(opt_id) \
|
||||||
b_command_usage_add_arg(this_usage, arg_##opt_id)
|
b_command_usage_add_arg(this_usage, arg_##opt_id)
|
||||||
|
|
||||||
#define B_COMMAND_USAGE_ARG_PLACEHOLDER() \
|
#define B_COMMAND_USAGE_ARG_PLACEHOLDER() \
|
||||||
b_command_usage_add_arg( \
|
b_command_usage_add_arg(this_usage, NULL)
|
||||||
this_usage, (struct b_command_arg *)B_COMMAND_INVALID_ID)
|
|
||||||
|
|
||||||
#define B_COMMAND_OPTION_HELP ((uintptr_t)0xF0000001)
|
#define B_COMMAND_OPTION_HELP ((uintptr_t)0xF0000001)
|
||||||
#define B_COMMAND_INVALID_ID ((uintptr_t)0xFFFFFFFF)
|
#define B_COMMAND_INVALID_ID ((uintptr_t)0xFFFFFFFF)
|
||||||
@@ -164,6 +174,17 @@ typedef struct b_arglist_iterator {
|
|||||||
unsigned int _opt_filter, _arg_filter;
|
unsigned int _opt_filter, _arg_filter;
|
||||||
} b_arglist_iterator;
|
} b_arglist_iterator;
|
||||||
|
|
||||||
|
typedef struct b_arglist_option_iterator {
|
||||||
|
b_iterator _base;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
unsigned int opt_id;
|
||||||
|
struct b_arglist_option *opt;
|
||||||
|
|
||||||
|
b_btree_iterator _opt_it;
|
||||||
|
unsigned int _opt_filter;
|
||||||
|
} b_arglist_option_iterator;
|
||||||
|
|
||||||
typedef struct b_command b_command;
|
typedef struct b_command b_command;
|
||||||
typedef struct b_command_option b_command_option;
|
typedef struct b_command_option b_command_option;
|
||||||
typedef struct b_command_arg b_command_arg;
|
typedef struct b_command_arg b_command_arg;
|
||||||
@@ -228,6 +249,17 @@ BLUE_API b_status b_arglist_get_option(
|
|||||||
BLUE_API size_t b_arglist_get_count(
|
BLUE_API size_t b_arglist_get_count(
|
||||||
const b_arglist *args, unsigned int opt_id, unsigned int arg_id);
|
const b_arglist *args, unsigned int opt_id, unsigned int arg_id);
|
||||||
|
|
||||||
|
BLUE_API b_status b_arglist_report_missing_option(
|
||||||
|
const b_arglist *args, unsigned int opt_id);
|
||||||
|
BLUE_API b_status b_arglist_report_unexpected_arg(
|
||||||
|
const b_arglist *args, const char *value);
|
||||||
|
BLUE_API b_status b_arglist_report_invalid_arg_value(
|
||||||
|
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
|
||||||
|
const char *value);
|
||||||
|
BLUE_API b_status b_arglist_report_missing_args(
|
||||||
|
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
|
||||||
|
size_t nr_supplied);
|
||||||
|
|
||||||
BLUE_API b_status b_arglist_option_get_value(
|
BLUE_API b_status b_arglist_option_get_value(
|
||||||
const b_arglist_option *opt, unsigned int arg_id, unsigned int index,
|
const b_arglist_option *opt, unsigned int arg_id, unsigned int index,
|
||||||
b_arglist_value **out);
|
b_arglist_value **out);
|
||||||
@@ -238,4 +270,11 @@ BLUE_API int b_arglist_iterator_begin(
|
|||||||
BLUE_API bool b_arglist_iterator_next(b_arglist_iterator *it);
|
BLUE_API bool b_arglist_iterator_next(b_arglist_iterator *it);
|
||||||
BLUE_API bool b_arglist_iterator_is_valid(const b_arglist_iterator *it);
|
BLUE_API bool b_arglist_iterator_is_valid(const b_arglist_iterator *it);
|
||||||
|
|
||||||
|
BLUE_API int b_arglist_option_iterator_begin(
|
||||||
|
const b_arglist *args, unsigned int opt_filter,
|
||||||
|
b_arglist_option_iterator *it);
|
||||||
|
BLUE_API bool b_arglist_option_iterator_next(b_arglist_option_iterator *it);
|
||||||
|
BLUE_API bool b_arglist_option_iterator_is_valid(
|
||||||
|
const b_arglist_option_iterator *it);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
19
cmd/option.c
19
cmd/option.c
@@ -231,3 +231,22 @@ void z__b_get_option_usage_string(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct b_command_arg *b_command_option_get_arg_with_id(
|
||||||
|
struct b_command_option *opt, unsigned int id)
|
||||||
|
{
|
||||||
|
b_queue_iterator it;
|
||||||
|
b_queue_foreach (&it, &opt->opt_args) {
|
||||||
|
struct b_command_arg *arg
|
||||||
|
= b_unbox(struct b_command_arg, it.entry, arg_entry);
|
||||||
|
if (!arg) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg->arg_id == id) {
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|||||||
193
cmd/report.c
Normal file
193
cmd/report.c
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
#include "command.h"
|
||||||
|
|
||||||
|
#include <blue/core/stringstream.h>
|
||||||
|
#include <blue/object/string.h>
|
||||||
|
#include <blue/term/print.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
enum b_status b_arglist_report_missing_option(
|
||||||
|
const b_arglist *args, unsigned int opt_id)
|
||||||
|
{
|
||||||
|
struct b_command_option *opt = NULL;
|
||||||
|
|
||||||
|
if (opt_id != B_COMMAND_INVALID_ID) {
|
||||||
|
opt = b_command_get_option_with_id(args->list_command, opt_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opt) {
|
||||||
|
return B_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct b_string *opt_string = b_string_create();
|
||||||
|
z__b_get_option_usage_string(opt, 0, opt_string);
|
||||||
|
|
||||||
|
char opt_name_s[128];
|
||||||
|
struct b_stringstream opt_name;
|
||||||
|
b_stringstream_begin(&opt_name, opt_name_s, sizeof opt_name_s);
|
||||||
|
|
||||||
|
int opt_names = 0;
|
||||||
|
if (opt->opt_short_name) {
|
||||||
|
opt_names++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt->opt_long_name) {
|
||||||
|
opt_names++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_names == 2) {
|
||||||
|
b_stringstream_addf(
|
||||||
|
&opt_name, "-%c / --%s", opt->opt_short_name,
|
||||||
|
opt->opt_long_name);
|
||||||
|
} else if (opt->opt_short_name) {
|
||||||
|
b_stringstream_addf(&opt_name, "-%c", opt->opt_short_name);
|
||||||
|
} else if (opt->opt_long_name) {
|
||||||
|
b_stringstream_addf(&opt_name, "--%s", opt->opt_long_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
b_err("required option `" F_YELLOW "%s" F_RESET "` was not specified.",
|
||||||
|
opt_name_s);
|
||||||
|
b_i("usage: %s", b_string_ptr(opt_string));
|
||||||
|
b_i("for more information, use `" F_YELLOW "--help" F_RESET "`");
|
||||||
|
|
||||||
|
b_string_release(opt_string);
|
||||||
|
|
||||||
|
return B_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
b_err("unexpected argument '" F_YELLOW "%s" F_RESET "' found.", value);
|
||||||
|
b_i("usage: %s", b_string_ptr(usage));
|
||||||
|
b_i("for more information, use '" F_YELLOW "--help" F_RESET "'");
|
||||||
|
|
||||||
|
return B_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum b_status b_arglist_report_invalid_arg_value(
|
||||||
|
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
struct b_command_option *opt = NULL;
|
||||||
|
struct b_command_arg *arg = NULL;
|
||||||
|
|
||||||
|
if (opt_id != B_COMMAND_INVALID_ID) {
|
||||||
|
opt = b_command_get_option_with_id(args->list_command, opt_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg_id != B_COMMAND_INVALID_ID) {
|
||||||
|
arg = opt ? b_command_option_get_arg_with_id(opt, arg_id)
|
||||||
|
: 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 *opt_string = b_string_create();
|
||||||
|
|
||||||
|
if (opt) {
|
||||||
|
z__b_get_option_usage_string(opt, 0, opt_string);
|
||||||
|
} else {
|
||||||
|
z__b_get_arg_usage_string(arg, 0, opt_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
b_err("invalid value '" F_YELLOW "%s" F_RESET "' for '" F_YELLOW
|
||||||
|
"%s" F_RESET "'.",
|
||||||
|
value, b_string_ptr(opt_string));
|
||||||
|
|
||||||
|
if (opt) {
|
||||||
|
b_i("'" F_YELLOW "%s" F_RESET
|
||||||
|
"' accepts the following values for '" F_YELLOW "%s" F_RESET
|
||||||
|
"':",
|
||||||
|
b_string_ptr(opt_string), arg->arg_name);
|
||||||
|
} else {
|
||||||
|
b_i("'" F_YELLOW "%s" F_RESET "' accepts the following values:",
|
||||||
|
b_string_ptr(opt_string));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; arg->arg_allowed_values[i]; i++) {
|
||||||
|
b_printf(
|
||||||
|
" * " F_GREEN "%s" F_RESET "\n",
|
||||||
|
arg->arg_allowed_values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
b_printf("\n");
|
||||||
|
b_i("usage: %s", b_string_ptr(usage));
|
||||||
|
b_i("for more information, use '" F_YELLOW "--help" F_RESET);
|
||||||
|
|
||||||
|
b_string_release(usage);
|
||||||
|
b_string_release(opt_string);
|
||||||
|
|
||||||
|
return B_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum b_status b_arglist_report_missing_args(
|
||||||
|
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
|
||||||
|
size_t args_supplied)
|
||||||
|
{
|
||||||
|
struct b_command_option *opt = NULL;
|
||||||
|
struct b_command_arg *arg = NULL;
|
||||||
|
|
||||||
|
if (opt_id != B_COMMAND_INVALID_ID) {
|
||||||
|
opt = b_command_get_option_with_id(args->list_command, opt_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg_id != B_COMMAND_INVALID_ID) {
|
||||||
|
arg = opt ? b_command_option_get_arg_with_id(opt, arg_id)
|
||||||
|
: 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 *opt_string = b_string_create();
|
||||||
|
|
||||||
|
if (opt) {
|
||||||
|
z__b_get_option_usage_string(opt, 0, opt_string);
|
||||||
|
} else {
|
||||||
|
z__b_get_arg_usage_string(arg, 0, opt_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
char supplied_arg_str[64];
|
||||||
|
if (args_supplied == 0) {
|
||||||
|
snprintf(
|
||||||
|
supplied_arg_str, sizeof supplied_arg_str,
|
||||||
|
F_RED_BOLD "none" F_RESET " were provided");
|
||||||
|
} else if (args_supplied == 1) {
|
||||||
|
snprintf(
|
||||||
|
supplied_arg_str, sizeof supplied_arg_str,
|
||||||
|
"only " F_YELLOW_BOLD "%zu" F_RESET " was provided",
|
||||||
|
args_supplied);
|
||||||
|
} else {
|
||||||
|
snprintf(
|
||||||
|
supplied_arg_str, sizeof supplied_arg_str,
|
||||||
|
"only " F_YELLOW_BOLD "%zu" F_RESET " were provided",
|
||||||
|
args_supplied);
|
||||||
|
}
|
||||||
|
|
||||||
|
char required_arg_count[64];
|
||||||
|
switch (arg->arg_nr_values) {
|
||||||
|
case B_ARG_1_OR_MORE_VALUES:
|
||||||
|
snprintf(
|
||||||
|
required_arg_count, sizeof required_arg_count,
|
||||||
|
"one or more");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
snprintf(
|
||||||
|
required_arg_count, sizeof required_arg_count, "%d",
|
||||||
|
arg->arg_nr_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
b_err("argument `" F_YELLOW "%s" F_RESET "` requires " F_GREEN_BOLD
|
||||||
|
"%s" F_RESET " `" F_YELLOW "%s" F_RESET "` value%s, but %s.",
|
||||||
|
b_string_ptr(opt_string), required_arg_count, arg->arg_name,
|
||||||
|
(arg->arg_nr_values == 1) ? "" : "s", supplied_arg_str);
|
||||||
|
b_i("usage: %s", b_string_ptr(usage));
|
||||||
|
b_i("for more information, use '" F_YELLOW "--help" F_RESET "'");
|
||||||
|
|
||||||
|
b_string_release(usage);
|
||||||
|
b_string_release(opt_string);
|
||||||
|
|
||||||
|
return B_SUCCESS;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user