207 lines
4.0 KiB
C
207 lines
4.0 KiB
C
|
|
#include "command.h"
|
||
|
|
|
||
|
|
#include <blue/cmd.h>
|
||
|
|
#include <blue/object/string.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
struct b_command_option *b_command_option_create(void)
|
||
|
|
{
|
||
|
|
struct b_command_option *out = malloc(sizeof *out);
|
||
|
|
if (!out) {
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(out, 0x0, sizeof *out);
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
b_status b_command_option_set_long_name(
|
||
|
|
struct b_command_option *opt, const char *name)
|
||
|
|
{
|
||
|
|
char *n = b_strdup(name);
|
||
|
|
if (!n) {
|
||
|
|
return B_ERR_NO_MEMORY;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (opt->opt_long_name) {
|
||
|
|
free(opt->opt_long_name);
|
||
|
|
opt->opt_long_name = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
opt->opt_long_name = n;
|
||
|
|
return B_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
b_status b_command_option_set_short_name(struct b_command_option *opt, char name)
|
||
|
|
{
|
||
|
|
opt->opt_short_name = name;
|
||
|
|
return B_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
b_status b_command_option_set_description(
|
||
|
|
struct b_command_option *opt, const char *description)
|
||
|
|
{
|
||
|
|
char *desc = b_strdup(description);
|
||
|
|
if (!desc) {
|
||
|
|
return B_ERR_NO_MEMORY;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (opt->opt_description) {
|
||
|
|
free(opt->opt_description);
|
||
|
|
opt->opt_description = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
opt->opt_description = desc;
|
||
|
|
return B_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct b_command_arg *b_command_option_add_arg(struct b_command_option *opt, int id)
|
||
|
|
{
|
||
|
|
struct b_command_arg *arg = malloc(sizeof *arg);
|
||
|
|
if (!arg) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(arg, 0x0, sizeof *arg);
|
||
|
|
|
||
|
|
arg->arg_id = id;
|
||
|
|
|
||
|
|
b_queue_push_back(&opt->opt_args, &arg->arg_entry);
|
||
|
|
return arg;
|
||
|
|
}
|
||
|
|
|
||
|
|
void z__b_get_option_description(struct b_command_option *opt, b_string *out)
|
||
|
|
{
|
||
|
|
if (opt->opt_description) {
|
||
|
|
b_string_append_cstr(out, opt->opt_description);
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t nr_args = b_queue_length(&opt->opt_args);
|
||
|
|
bool close_bracket = false;
|
||
|
|
|
||
|
|
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 || !arg->arg_allowed_values) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (it.i > 0) {
|
||
|
|
b_string_append_cstr(out, "; ");
|
||
|
|
} else {
|
||
|
|
b_string_append_cstr(out, " [");
|
||
|
|
close_bracket = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nr_args > 1) {
|
||
|
|
b_string_append_cstrf(
|
||
|
|
out, "values for `%s`:", arg->arg_name);
|
||
|
|
} else {
|
||
|
|
b_string_append_cstr(out, "values:");
|
||
|
|
}
|
||
|
|
|
||
|
|
for (size_t i = 0; arg->arg_allowed_values[i]; i++) {
|
||
|
|
if (i > 0) {
|
||
|
|
b_string_append_cstr(out, ",");
|
||
|
|
}
|
||
|
|
|
||
|
|
b_string_append_cstrf(
|
||
|
|
out, " " F_GREEN "%s" F_RESET,
|
||
|
|
arg->arg_allowed_values[i]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (close_bracket) {
|
||
|
|
b_string_append_cstr(out, "]");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void z__b_get_option_usage_string(
|
||
|
|
struct b_command_option *opt, enum cmd_string_flags flags,
|
||
|
|
struct b_string *out)
|
||
|
|
{
|
||
|
|
if (flags & CMD_STR_DIRECT_USAGE) {
|
||
|
|
b_string_append_cstr(out, "{");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (opt->opt_short_name) {
|
||
|
|
b_string_append_cstrf(
|
||
|
|
out,
|
||
|
|
(flags & CMD_STR_COLOUR) ? F_GREEN "-%c" F_RESET : "-%c",
|
||
|
|
opt->opt_short_name);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (opt->opt_short_name && opt->opt_long_name) {
|
||
|
|
b_string_append_cstr(
|
||
|
|
out, (flags & CMD_STR_DIRECT_USAGE) ? "|" : ", ");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (opt->opt_long_name) {
|
||
|
|
b_string_append_cstrf(
|
||
|
|
out,
|
||
|
|
(flags & CMD_STR_COLOUR) ? F_GREEN "--%s" F_RESET : "--%s",
|
||
|
|
opt->opt_long_name);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (flags & CMD_STR_DIRECT_USAGE) {
|
||
|
|
b_string_append_cstr(out, "}");
|
||
|
|
}
|
||
|
|
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool optional = false, multi = false;
|
||
|
|
switch (arg->arg_nr_values) {
|
||
|
|
case B_ARG_0_OR_1_VALUES:
|
||
|
|
optional = true;
|
||
|
|
multi = false;
|
||
|
|
break;
|
||
|
|
case B_ARG_0_OR_MORE_VALUES:
|
||
|
|
optional = true;
|
||
|
|
multi = true;
|
||
|
|
break;
|
||
|
|
case B_ARG_1_OR_MORE_VALUES:
|
||
|
|
optional = false;
|
||
|
|
multi = true;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
optional = false;
|
||
|
|
multi = false;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (optional) {
|
||
|
|
b_string_append_cstrf(
|
||
|
|
out,
|
||
|
|
(flags & CMD_STR_COLOUR) ? " " F_GREEN "[%s]"
|
||
|
|
: " [%s]",
|
||
|
|
arg->arg_name);
|
||
|
|
} else {
|
||
|
|
b_string_append_cstrf(
|
||
|
|
out,
|
||
|
|
(flags & CMD_STR_COLOUR) ? " " F_GREEN "<%s>"
|
||
|
|
: " <%s>",
|
||
|
|
arg->arg_name);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 1; i < arg->arg_nr_values; i++) {
|
||
|
|
b_string_append_cstrf(out, " <%s>", arg->arg_name);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (multi) {
|
||
|
|
b_string_append_cstr(out, "...");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (flags & CMD_STR_COLOUR) {
|
||
|
|
b_string_append_cstr(out, F_RESET);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|