#ifndef KIcli
#define KIcli
#include <k/core.h>
#include <k/io.h>
#include <k/type.h>
#include <k/internal.egroup.h>
/* input types */
typedef struct kcli_opt {
rune id;
const char* name;
enum kcli_opt_kind {
kcli_opt_none /* flag is disabled and hidden */,
kcli_opt_string /* flag takes a string argument */,
kcli_opt_flag /* on if present, off if absent */,
kcli_opt_toggle /* off by default, value toggles
* for each occurrence */,
kcli_opt_accumulate /* u8, value increases for each
* occurrence, saturates at 255 */,
kcli_opt_enum /* matched against a table of string
* values to retrieve the corresponding
* integer ID */,
kcli_opt_int = 0x40,
/* kcli_opt_int takes a default base parameter.
* for instance, to take a decimal number, you
* might write `kcli_opt_int | 10.` if the
* argument takes a base prefix, the default
* base will be disregarded. */
kcli_opt_oct = kcli_opt_int | 8,
kcli_opt_dec = kcli_opt_int | 10,
kcli_opt_hex = kcli_opt_int | 16,
} kind;
void* val;
const char* desc;
} kcli_opt;
typedef struct kcli_param {
const char* name;
enum kcli_param_kind {
kcli_param_none,
kcli_param_string,
kcli_param_enum,
kcli_param_int = 0x40,
kcli_param_oct = kcli_param_int | 8,
kcli_param_dec = kcli_param_int | 10,
kcli_param_hex = kcli_param_int | 16,
} kind;
enum kcli_rule {
kcli_rule_forbidden,
kcli_rule_required,
kcli_rule_optional,
kcli_rule_overflow,
} rule;
void* val;
const char* desc;
} kcli_param;
typedef struct kcli_set {
const char* name;
const char* version;
const char** args; sz argc;
const char* desc;
const kcli_param* params; sz paramc;
const kcli_opt* opts; sz optc;
} kcli_set;
/* output types */
typedef enum kcli_cond {
kcli_cond_ok = kcli_cond_id,
kcli_cond_extra /* parse succeded, but arguments or
flags were left over */,
kcli_cond_fail /* unspecified error */,
kcli_cond_parse /* bad syntax, parse failed */,
kcli_cond_overlong /* a string in the configuration structures is longer than allowed */,
} kcli_cond;
typedef enum kcli_flag {
kcli_flag_off = 0,
kcli_flag_on = 1,
} kcli_flag;
/* functions */
kcond kcli_usage(kcli_set, kiochan);
kcli_cond kcli_parse(kcli_set);
/* macros */
#define Kcli_param(field,kind,rule,description) \
{#field, kcli_param_##kind, kcli_rule_##rule, &field, description}
#define Kcli_opt(long,short,kind,description) \
{short, #long, kcli_opt_##kind, &long, description}
#endif