#include <k/core.h>
#include <k/cli.h>
#include <k/io.h>
#include <k/str.h>
extern char* _k_internal_binary_name;
static const struct { const char* front, * back; } param_styles [] = {
[kcli_rule_required] = { "<",">" },
[kcli_rule_optional] = { "[","]" },
[kcli_rule_overflow] = { "","..." },
};
kcond
kcli_usage(kcli_set prg, kiochan ch) {
enum { max_name_len = 32 };
kcond c;
ubyte buf_space [sizeof(ksbuf) + 256];
ksbuf* out = ksbufmk(buf_space, ch, 256);
const char* name = prg.name != null ?
prg.name : _k_internal_binary_name;
const char* msg [] = {
name, " v", prg.version, "\n\n",
prg.desc, "\n\n",
"usage: ", _k_internal_binary_name,
prg.optc == 0 ? null : " [-", null,
};
if (!kokay(c = ksbufwrite(out, msg))) return c;
u8 longest_opt = 0;
u8 opt_lens [prg.optc];
for (sz i = 0; i != prg.optc; ++ i) {
if (prg.opts[i].id[0] == 0) continue;
opt_lens[i] = kssz(prg.opts[i].name, max_name_len);
if (opt_lens[i] > longest_opt)
longest_opt = opt_lens[i];
ksraw str = { kssz(prg.opts[i].id, 4), prg.opts[i].id };
if (!kokay(c = ksbufput(out, str))) return c;
}
if (!kokay(c = ksbufput(out, Ksraw("]")))) return c;
u8 longest_param = 0;
u8 param_lens [prg.paramc];
for (sz i = 0; i != prg.paramc; ++ i) {
enum kcli_rule r = prg.params[i].rule;
param_lens[i] = kssz(prg.params[i].name, max_name_len);
if (param_lens[i] > longest_param)
longest_param = param_lens[i];
const char* param[] = {
" ", param_styles[r].front, prg.params[i].name,
param_styles[r].back, null
};
if (!kokay(c = ksbufwrite(out,param))) return c;
}
if (!kokay(c = ksbufput(out, Ksraw("\n")))) return c;
const char spacing [] = " ";
Kassert(sizeof spacing - 1 == max_name_len,
"spacing string not equal in length to max_name_len");
/* yes, yes, i know */
for (sz i = 0; i != prg.paramc; ++ i) {
u8 pad = (longest_param - param_lens[i]) + 1;
const char* tpl [] = {
"\n ", spacing + (sizeof spacing - pad),
prg.params[i].name, ": ", prg.params[i].desc, null
};
if (!kokay(c = ksbufwrite(out, tpl))) return c;
}
if (!kokay(c = ksbufput(out, (ksraw){1, "\n"}))) return c;
for (sz i = 0; i != prg.optc; ++ i) {
u8 pad = (longest_opt - opt_lens[i]) + 1;
const char* tpl [] = {
"\n -", prg.opts[i].id, ", --", prg.opts[i].name,
spacing + (sizeof spacing - pad), ": ", prg.opts[i].desc, null
};
if (!kokay(c = ksbufwrite(out, tpl))) return c;
}
return ksbufflush(out);
}