#include #include #include #include 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); }