libk  Diff

Differences From Artifact [09e6f94502]:

To Artifact [51bd833f89]:



1
2
3








4
5
6



7
8
9



10
11
12


13





14
15







16
17
18
















































19
20

#include <k/cli.h>
#include <k/io.h>
#include <k/str.h>









kcond
kcli_usage(kcli_set prg, kiochan ch) {



	ubyte buf_space [sizeof(ksbuf) + 256];
	ksbuf* out = ksbufmk(buf_space, ch, 256);




	const char* msg [] = {
		prg.name, " v", prg.version, "\n\n",
		prg.desc, "\n\n",


	};





	for (sz i = 0; i != Kmsz(msg); ++ i) {
		ksraw str = { 0, msg[i] };







		kcond c = ksbufput(out, str);
	}
	
















































	return ksbufflush(out);
}
>



>
>
>
>
>
>
>
>



>
>
>



>
>
>

|

>
>

>
>
>
>
>
|
<
>
>
>
>
>
>
>
|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#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 : " [-",
	};

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