Differences From
Artifact [09e6f94502]:
1 +#include <k/core.h>
1 2 #include <k/cli.h>
2 3 #include <k/io.h>
3 4 #include <k/str.h>
5 +
6 +extern char* _k_internal_binary_name;
7 +
8 +static const struct { const char* front, * back; } param_styles [] = {
9 + [kcli_rule_required] = { "<",">" },
10 + [kcli_rule_optional] = { "[","]" },
11 + [kcli_rule_overflow] = { "","..." },
12 +};
4 13
5 14 kcond
6 15 kcli_usage(kcli_set prg, kiochan ch) {
16 + enum { max_name_len = 32 };
17 +
18 + kcond c;
7 19 ubyte buf_space [sizeof(ksbuf) + 256];
8 20 ksbuf* out = ksbufmk(buf_space, ch, 256);
9 21
22 + const char* name = prg.name != null ?
23 + prg.name : _k_internal_binary_name;
24 +
10 25 const char* msg [] = {
11 - prg.name, " v", prg.version, "\n\n",
26 + name, " v", prg.version, "\n\n",
12 27 prg.desc, "\n\n",
28 + "usage: ", _k_internal_binary_name,
29 + prg.optc == 0 ? null : " [-",
13 30 };
14 - for (sz i = 0; i != Kmsz(msg); ++ i) {
15 - ksraw str = { 0, msg[i] };
16 - kcond c = ksbufput(out, str);
31 +
32 + if (!kokay(c = ksbufwrite(out, msg))) return c;
33 +
34 + u8 longest_opt = 0;
35 + u8 opt_lens [prg.optc];
36 + for (sz i = 0; i != prg.optc; ++ i) {
37 + if (prg.opts[i].id[0] == 0) continue;
38 +
39 + opt_lens[i] = kssz(prg.opts[i].name, max_name_len);
40 + if (opt_lens[i] > longest_opt)
41 + longest_opt = opt_lens[i];
42 +
43 + ksraw str = { kssz(prg.opts[i].id, 4), prg.opts[i].id };
44 + if (!kokay(c = ksbufput(out, str))) return c;
17 45 }
46 +
47 + if (!kokay(c = ksbufput(out, Ksraw("]")))) return c;
18 48
49 + u8 longest_param = 0;
50 + u8 param_lens [prg.paramc];
51 + for (sz i = 0; i != prg.paramc; ++ i) {
52 + enum kcli_rule r = prg.params[i].rule;
53 +
54 + param_lens[i] = kssz(prg.params[i].name, max_name_len);
55 + if (param_lens[i] > longest_param)
56 + longest_param = param_lens[i];
57 +
58 + const char* param[] = {
59 + " ", param_styles[r].front, prg.params[i].name,
60 + param_styles[r].back, null
61 + };
62 +
63 + if (!kokay(c = ksbufwrite(out,param))) return c;
64 + }
65 +
66 + if (!kokay(c = ksbufput(out, Ksraw("\n")))) return c;
67 +
68 + const char spacing [] = " ";
69 + Kassert(sizeof spacing - 1 == max_name_len,
70 + "spacing string not equal in length to max_name_len");
71 + /* yes, yes, i know */
72 +
73 + for (sz i = 0; i != prg.paramc; ++ i) {
74 + u8 pad = (longest_param - param_lens[i]) + 1;
75 + const char* tpl [] = {
76 + "\n ", spacing + (sizeof spacing - pad),
77 + prg.params[i].name, ": ", prg.params[i].desc, null
78 + };
79 +
80 + if (!kokay(c = ksbufwrite(out, tpl))) return c;
81 + }
82 +
83 + if (!kokay(c = ksbufput(out, (ksraw){1, "\n"}))) return c;
84 +
85 + for (sz i = 0; i != prg.optc; ++ i) {
86 + u8 pad = (longest_opt - opt_lens[i]) + 1;
87 + const char* tpl [] = {
88 + "\n -", prg.opts[i].id, ", --", prg.opts[i].name,
89 + spacing + (sizeof spacing - pad), ": ", prg.opts[i].desc, null
90 + };
91 +
92 + if (!kokay(c = ksbufwrite(out, tpl))) return c;
93 + }
94 +
19 95 return ksbufflush(out);
20 96 }