cli-kiss 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/dist/index.d.ts +527 -830
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/docs/.vitepress/config.mts +3 -0
- package/docs/guide/01_getting_started.md +9 -9
- package/docs/guide/02_commands.md +6 -11
- package/docs/guide/03_options.md +4 -6
- package/docs/guide/04_positionals.md +6 -8
- package/docs/guide/05_types.md +8 -10
- package/docs/guide/06_run.md +6 -7
- package/docs/index.md +4 -4
- package/package.json +1 -1
- package/src/lib/Command.ts +189 -256
- package/src/lib/Operation.ts +68 -82
- package/src/lib/Option.ts +115 -132
- package/src/lib/Positional.ts +95 -100
- package/src/lib/Reader.ts +53 -78
- package/src/lib/Run.ts +40 -58
- package/src/lib/Type.ts +81 -141
- package/src/lib/Typo.ts +121 -164
- package/src/lib/Usage.ts +56 -18
- package/tests/unit.command.execute.ts +83 -71
- package/tests/unit.command.usage.ts +230 -109
- package/tests/unit.runner.cycle.ts +56 -7
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { expect, it } from "@jest/globals";
|
|
2
2
|
import {
|
|
3
3
|
command,
|
|
4
|
-
|
|
4
|
+
Command,
|
|
5
|
+
commandChained,
|
|
5
6
|
commandWithSubcommands,
|
|
6
7
|
operation,
|
|
7
8
|
optionFlag,
|
|
@@ -16,64 +17,69 @@ import {
|
|
|
16
17
|
typeString,
|
|
17
18
|
} from "../src";
|
|
18
19
|
|
|
19
|
-
const rootCommand =
|
|
20
|
-
{ description: "
|
|
20
|
+
const rootCommand = commandChained(
|
|
21
|
+
{ description: "?" },
|
|
21
22
|
operation(
|
|
22
23
|
{
|
|
23
|
-
options: {
|
|
24
|
-
|
|
25
|
-
long: "boolean-flag",
|
|
26
|
-
default: () => false,
|
|
27
|
-
}),
|
|
28
|
-
stringOption: optionSingleValue({
|
|
29
|
-
long: "string-option",
|
|
30
|
-
type: typeString,
|
|
31
|
-
default: () => undefined,
|
|
32
|
-
}),
|
|
33
|
-
numberOption: optionRepeatable({
|
|
34
|
-
long: "number-option",
|
|
35
|
-
type: typeList(typeNumber),
|
|
36
|
-
}),
|
|
37
|
-
},
|
|
38
|
-
positionals: [
|
|
39
|
-
positionalRequired({ type: typeNumber }),
|
|
40
|
-
positionalRequired({ type: typeNumber }),
|
|
41
|
-
],
|
|
24
|
+
options: { flag: optionFlag({ short: "b", long: "boolean-flag" }) },
|
|
25
|
+
positionals: [positionalRequired({ label: "POS-1", type: typeNumber })],
|
|
42
26
|
},
|
|
43
27
|
async (context, inputs) => {
|
|
44
28
|
return { at: "root", context, inputs };
|
|
45
29
|
},
|
|
46
30
|
),
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
31
|
+
commandWithSubcommands<any, any, any>(
|
|
32
|
+
{ description: "?" },
|
|
33
|
+
operation(
|
|
34
|
+
{
|
|
35
|
+
options: {
|
|
36
|
+
string: optionSingleValue({
|
|
37
|
+
long: "string-option",
|
|
38
|
+
type: typeString,
|
|
39
|
+
default: () => undefined,
|
|
40
|
+
}),
|
|
41
|
+
number: optionRepeatable({
|
|
42
|
+
long: "number-option",
|
|
43
|
+
type: typeList(typeNumber),
|
|
44
|
+
}),
|
|
57
45
|
},
|
|
58
|
-
|
|
46
|
+
positionals: [positionalRequired({ type: typeNumber })],
|
|
47
|
+
},
|
|
48
|
+
async (context, inputs) => {
|
|
49
|
+
return { at: "mid", context, inputs };
|
|
50
|
+
},
|
|
59
51
|
),
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
positionalRequired({ type:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return { at: "sub2", context, inputs };
|
|
73
|
-
},
|
|
52
|
+
{
|
|
53
|
+
sub1: command(
|
|
54
|
+
{ description: "?" },
|
|
55
|
+
operation(
|
|
56
|
+
{
|
|
57
|
+
options: {},
|
|
58
|
+
positionals: [positionalRequired({ type: typeString })],
|
|
59
|
+
},
|
|
60
|
+
async (context, inputs) => {
|
|
61
|
+
return { at: "sub1", context, inputs };
|
|
62
|
+
},
|
|
63
|
+
),
|
|
74
64
|
),
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
sub2: command(
|
|
66
|
+
{ description: "?" },
|
|
67
|
+
operation(
|
|
68
|
+
{
|
|
69
|
+
options: {},
|
|
70
|
+
positionals: [
|
|
71
|
+
positionalRequired({ type: typeNumber }),
|
|
72
|
+
positionalOptional({ type: typeString, default: () => "42" }),
|
|
73
|
+
positionalVariadics({ type: typeString }),
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
async (context, inputs) => {
|
|
77
|
+
return { at: "sub2", context, inputs };
|
|
78
|
+
},
|
|
79
|
+
),
|
|
80
|
+
),
|
|
81
|
+
},
|
|
82
|
+
),
|
|
77
83
|
);
|
|
78
84
|
|
|
79
85
|
it("run", async () => {
|
|
@@ -83,23 +89,26 @@ it("run", async () => {
|
|
|
83
89
|
rootCommand,
|
|
84
90
|
);
|
|
85
91
|
expect(res1).toStrictEqual({
|
|
92
|
+
at: "sub1",
|
|
86
93
|
context: {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
at: "mid",
|
|
95
|
+
context: {
|
|
96
|
+
at: "root",
|
|
97
|
+
context: "Run Context Input",
|
|
98
|
+
inputs: {
|
|
99
|
+
options: { flag: false },
|
|
100
|
+
positionals: [50],
|
|
93
101
|
},
|
|
94
|
-
positionals: [50, 51],
|
|
95
102
|
},
|
|
96
|
-
|
|
103
|
+
inputs: {
|
|
104
|
+
options: { string: undefined, number: [] },
|
|
105
|
+
positionals: [51],
|
|
106
|
+
},
|
|
97
107
|
},
|
|
98
108
|
inputs: {
|
|
99
109
|
options: {},
|
|
100
110
|
positionals: ["final"],
|
|
101
111
|
},
|
|
102
|
-
at: "sub1",
|
|
103
112
|
});
|
|
104
113
|
|
|
105
114
|
const res2 = await executeInterpreted(
|
|
@@ -121,33 +130,36 @@ it("run", async () => {
|
|
|
121
130
|
rootCommand,
|
|
122
131
|
);
|
|
123
132
|
expect(res2).toStrictEqual({
|
|
133
|
+
at: "sub2",
|
|
124
134
|
context: {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
135
|
+
at: "mid",
|
|
136
|
+
context: {
|
|
137
|
+
at: "root",
|
|
138
|
+
context: "Run Context Input",
|
|
139
|
+
inputs: {
|
|
140
|
+
options: { flag: true },
|
|
141
|
+
positionals: [40],
|
|
131
142
|
},
|
|
132
|
-
positionals: [40, 41],
|
|
133
143
|
},
|
|
134
|
-
|
|
144
|
+
inputs: {
|
|
145
|
+
options: { string: "hello", number: [[123.1, 123.2], [123.3]] },
|
|
146
|
+
positionals: [41],
|
|
147
|
+
},
|
|
135
148
|
},
|
|
136
149
|
inputs: {
|
|
137
150
|
options: {},
|
|
138
151
|
positionals: [88.88, "a,b", ["final"]],
|
|
139
152
|
},
|
|
140
|
-
at: "sub2",
|
|
141
153
|
});
|
|
142
154
|
});
|
|
143
155
|
|
|
144
156
|
async function executeInterpreted<Context, Result>(
|
|
145
157
|
args: Array<string>,
|
|
146
158
|
context: Context,
|
|
147
|
-
command:
|
|
159
|
+
command: Command<Context, Result>,
|
|
148
160
|
) {
|
|
149
161
|
const readerArgs = new ReaderArgs(args);
|
|
150
|
-
const
|
|
151
|
-
const
|
|
152
|
-
return await
|
|
162
|
+
const commandDecoder = command.consumeAndMakeDecoder(readerArgs);
|
|
163
|
+
const commandInterpreter = commandDecoder.decodeAndMakeInterpreter();
|
|
164
|
+
return await commandInterpreter.executeWithContext(context);
|
|
153
165
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { it } from "@jest/globals";
|
|
2
2
|
import {
|
|
3
3
|
command,
|
|
4
|
-
|
|
4
|
+
Command,
|
|
5
|
+
commandChained,
|
|
5
6
|
commandWithSubcommands,
|
|
6
7
|
operation,
|
|
7
8
|
optionFlag,
|
|
@@ -19,10 +20,16 @@ import {
|
|
|
19
20
|
usageToStyledLines,
|
|
20
21
|
} from "../src";
|
|
21
22
|
|
|
22
|
-
const
|
|
23
|
+
const rootCommand = commandChained<any, any, any>(
|
|
23
24
|
{
|
|
24
25
|
description: "Root command description",
|
|
25
|
-
details: ["Root command details.", "
|
|
26
|
+
details: ["Root command details.", "Root second line of command details."],
|
|
27
|
+
examples: [
|
|
28
|
+
{
|
|
29
|
+
explanation: "Example usage of the root command",
|
|
30
|
+
commandArgs: [{ positional: "42" }, { option: { short: "b" } }],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
26
33
|
},
|
|
27
34
|
operation(
|
|
28
35
|
{
|
|
@@ -30,20 +37,7 @@ const cmd = commandWithSubcommands<string, any, any>(
|
|
|
30
37
|
booleanFlag: optionFlag({
|
|
31
38
|
short: "b",
|
|
32
39
|
long: "boolean-flag",
|
|
33
|
-
description: "
|
|
34
|
-
}),
|
|
35
|
-
stringOption: optionSingleValue({
|
|
36
|
-
short: "s",
|
|
37
|
-
long: "string-option",
|
|
38
|
-
type: typeString,
|
|
39
|
-
default: () => undefined,
|
|
40
|
-
label: "COOL-STUFF",
|
|
41
|
-
description: "Root string-option description",
|
|
42
|
-
}),
|
|
43
|
-
complexOption: optionRepeatable({
|
|
44
|
-
long: "complex-option",
|
|
45
|
-
type: typeTuple([typeNumber, typeList(typeString)]),
|
|
46
|
-
description: "Root complex-option description",
|
|
40
|
+
description: "boolean-flag description",
|
|
47
41
|
}),
|
|
48
42
|
},
|
|
49
43
|
positionals: [
|
|
@@ -52,107 +46,203 @@ const cmd = commandWithSubcommands<string, any, any>(
|
|
|
52
46
|
description: "Required positional number 1",
|
|
53
47
|
type: typeNumber,
|
|
54
48
|
}),
|
|
55
|
-
positionalRequired({
|
|
56
|
-
label: "POS-2",
|
|
57
|
-
description: "Required positional number 2",
|
|
58
|
-
type: typeNumber,
|
|
59
|
-
}),
|
|
60
49
|
],
|
|
61
50
|
},
|
|
62
51
|
async (context, inputs) => {
|
|
63
52
|
return { at: "root", context, inputs };
|
|
64
53
|
},
|
|
65
54
|
),
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"Subcommand 1 details.",
|
|
72
|
-
"Second line of subcommand 1 details.",
|
|
73
|
-
],
|
|
74
|
-
},
|
|
75
|
-
operation(
|
|
55
|
+
commandWithSubcommands<any, any, any>(
|
|
56
|
+
{
|
|
57
|
+
description: "Mid command description",
|
|
58
|
+
details: ["Mid command details.", "Mid second line of command details."],
|
|
59
|
+
examples: [
|
|
76
60
|
{
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
type: typeString,
|
|
83
|
-
}),
|
|
61
|
+
explanation: "Example usage of the mid command",
|
|
62
|
+
commandArgs: [
|
|
63
|
+
{ positional: "42" },
|
|
64
|
+
{ option: { short: "b" } },
|
|
65
|
+
{ positional: "43" },
|
|
84
66
|
],
|
|
85
67
|
},
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
),
|
|
90
|
-
),
|
|
91
|
-
sub2: command(
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
operation(
|
|
92
71
|
{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
72
|
+
options: {
|
|
73
|
+
stringOption: optionSingleValue({
|
|
74
|
+
short: "s",
|
|
75
|
+
long: "string-option",
|
|
76
|
+
type: typeString,
|
|
77
|
+
default: () => undefined,
|
|
78
|
+
label: "COOL-STUFF",
|
|
79
|
+
description: "string-option description",
|
|
80
|
+
}),
|
|
81
|
+
complexOption: optionRepeatable({
|
|
82
|
+
long: "complex-option",
|
|
83
|
+
type: typeTuple([typeNumber, typeList(typeString)]),
|
|
84
|
+
description: "complex-option description",
|
|
85
|
+
}),
|
|
86
|
+
},
|
|
87
|
+
positionals: [
|
|
88
|
+
positionalRequired({
|
|
89
|
+
label: "POS-2",
|
|
90
|
+
description: "Required positional number 2",
|
|
91
|
+
type: typeNumber,
|
|
92
|
+
}),
|
|
98
93
|
],
|
|
99
94
|
},
|
|
100
|
-
|
|
95
|
+
async (context, inputs) => {
|
|
96
|
+
return { at: "root", context, inputs };
|
|
97
|
+
},
|
|
98
|
+
),
|
|
99
|
+
{
|
|
100
|
+
sub1: command(
|
|
101
101
|
{
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
label: "OPT-POS",
|
|
119
|
-
description: "Optional positional string",
|
|
120
|
-
hint: "Optional positional hint",
|
|
121
|
-
type: typeString,
|
|
122
|
-
default: () => "42",
|
|
123
|
-
}),
|
|
124
|
-
positionalVariadics({
|
|
125
|
-
label: "VARIADIC",
|
|
126
|
-
description: "Variadic positionals strings",
|
|
127
|
-
type: typeString,
|
|
128
|
-
}),
|
|
102
|
+
description: "Subcommand 1 description",
|
|
103
|
+
details: [
|
|
104
|
+
"Subcommand 1 details.",
|
|
105
|
+
"Subcommand 1 second line of details.",
|
|
106
|
+
],
|
|
107
|
+
examples: [
|
|
108
|
+
{
|
|
109
|
+
explanation: "Example usage of subcommand 1",
|
|
110
|
+
commandArgs: [
|
|
111
|
+
{ option: { short: "b" } },
|
|
112
|
+
{ positional: "42" },
|
|
113
|
+
{ positional: "43" },
|
|
114
|
+
{ subcommand: "sub1" },
|
|
115
|
+
{ positional: "valid" },
|
|
116
|
+
],
|
|
117
|
+
},
|
|
129
118
|
],
|
|
130
119
|
},
|
|
131
|
-
|
|
132
|
-
|
|
120
|
+
operation(
|
|
121
|
+
{
|
|
122
|
+
options: {},
|
|
123
|
+
positionals: [
|
|
124
|
+
positionalRequired({
|
|
125
|
+
label: "POS-STRING",
|
|
126
|
+
description: "Required positional string",
|
|
127
|
+
type: typeString,
|
|
128
|
+
}),
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
async (context, inputs) => {
|
|
132
|
+
return { at: "sub1", context, inputs };
|
|
133
|
+
},
|
|
134
|
+
),
|
|
135
|
+
),
|
|
136
|
+
sub2: command(
|
|
137
|
+
{
|
|
138
|
+
description: "Subcommand 2 description",
|
|
139
|
+
hint: "Subcommand 2 hint",
|
|
140
|
+
details: [
|
|
141
|
+
"Subcommand 2 details.",
|
|
142
|
+
"Subcommand 2 second line of details.",
|
|
143
|
+
],
|
|
144
|
+
examples: [
|
|
145
|
+
{
|
|
146
|
+
explanation: "Example usage of subcommand 2",
|
|
147
|
+
commandArgs: [
|
|
148
|
+
{ positional: "40" },
|
|
149
|
+
{ positional: "41" },
|
|
150
|
+
{ subcommand: "sub2" },
|
|
151
|
+
{ option: { long: "dudu", value: "hello" } },
|
|
152
|
+
{ positional: "50" },
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
],
|
|
133
156
|
},
|
|
157
|
+
operation(
|
|
158
|
+
{
|
|
159
|
+
options: {
|
|
160
|
+
duduValue: optionSingleValue({
|
|
161
|
+
long: "dudu",
|
|
162
|
+
type: typeString,
|
|
163
|
+
default: () => "duduDefault",
|
|
164
|
+
hint: "Dudu option hint",
|
|
165
|
+
description: "Dudu option description",
|
|
166
|
+
}),
|
|
167
|
+
},
|
|
168
|
+
positionals: [
|
|
169
|
+
positionalRequired({
|
|
170
|
+
label: "POS-NUMBER",
|
|
171
|
+
description: "Required positional number",
|
|
172
|
+
type: typeNumber,
|
|
173
|
+
}),
|
|
174
|
+
positionalOptional({
|
|
175
|
+
label: "OPT-POS",
|
|
176
|
+
description: "Optional positional string",
|
|
177
|
+
hint: "Optional positional hint",
|
|
178
|
+
type: typeString,
|
|
179
|
+
default: () => "42",
|
|
180
|
+
}),
|
|
181
|
+
positionalVariadics({
|
|
182
|
+
label: "VARIADIC",
|
|
183
|
+
description: "Variadic positionals strings",
|
|
184
|
+
type: typeString,
|
|
185
|
+
}),
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
async (context, inputs) => {
|
|
189
|
+
return { at: "sub2", context, inputs };
|
|
190
|
+
},
|
|
191
|
+
),
|
|
134
192
|
),
|
|
135
|
-
|
|
136
|
-
|
|
193
|
+
},
|
|
194
|
+
),
|
|
137
195
|
);
|
|
138
196
|
|
|
139
197
|
it("run", async () => {
|
|
140
|
-
const usage1 = await getUsage([],
|
|
141
|
-
const usage2 = await getUsage(["50"
|
|
142
|
-
const usage3 = await getUsage(["
|
|
198
|
+
const usage1 = await getUsage([], rootCommand);
|
|
199
|
+
const usage2 = await getUsage(["50"], rootCommand);
|
|
200
|
+
const usage3 = await getUsage(["50", "51"], rootCommand);
|
|
201
|
+
const usage4 = await getUsage(["50", "51", "sub1"], rootCommand);
|
|
202
|
+
const usage5 = await getUsage(["50", "51", "sub1", "valid"], rootCommand);
|
|
203
|
+
const usage6 = await getUsage(
|
|
204
|
+
["40", "41", "sub2", "--doesn't-exist"],
|
|
205
|
+
rootCommand,
|
|
206
|
+
);
|
|
207
|
+
const usage7 = await getUsage(
|
|
208
|
+
["40", "41", "sub2", "not-a-number"],
|
|
209
|
+
rootCommand,
|
|
210
|
+
);
|
|
143
211
|
|
|
144
|
-
/*
|
|
145
212
|
console.log(usage1.join("\n"));
|
|
146
213
|
console.log(usage2.join("\n"));
|
|
147
214
|
console.log(usage3.join("\n"));
|
|
215
|
+
console.log(usage4.join("\n"));
|
|
216
|
+
console.log(usage5.join("\n"));
|
|
217
|
+
console.log(usage6.join("\n"));
|
|
218
|
+
console.log(usage7.join("\n"));
|
|
219
|
+
/*
|
|
148
220
|
*/
|
|
149
221
|
|
|
150
|
-
|
|
151
|
-
"{{Usage:}@darkMagenta}+ {{my-cli}@darkCyan}+ {{<POS-1>}@darkBlue}+ {{
|
|
222
|
+
const usageRoot = [
|
|
223
|
+
"{{Usage:}@darkMagenta}+ {{my-cli}@darkCyan}+ {{<POS-1>}@darkBlue}+ {{[REST]...}@darkBlue}+",
|
|
152
224
|
"",
|
|
153
225
|
"{Root command description}+",
|
|
154
226
|
"{{Root command details.}-}*",
|
|
155
|
-
"{{
|
|
227
|
+
"{{Root second line of command details.}-}*",
|
|
228
|
+
"",
|
|
229
|
+
"{{Positionals:}@darkGreen}+",
|
|
230
|
+
" {{<POS-1>}@darkBlue}+ Required positional number 1",
|
|
231
|
+
"",
|
|
232
|
+
"{{Options:}@darkGreen}+",
|
|
233
|
+
" {{-b}@darkCyan}+, {{--boolean-flag}@darkCyan}+{{[=no]}-}* boolean-flag description",
|
|
234
|
+
"",
|
|
235
|
+
"{{Examples:}@darkGreen}+",
|
|
236
|
+
" {{# Example usage of the root command}-}*",
|
|
237
|
+
" {{my-cli}@darkCyan}+ {{42}@darkBlue}+ {{-b}@darkCyan}+",
|
|
238
|
+
"",
|
|
239
|
+
];
|
|
240
|
+
const usageMid = [
|
|
241
|
+
"{{Usage:}@darkMagenta}+ {{my-cli}@darkCyan}+ {{<POS-1>}@darkBlue}+ {{<POS-2>}@darkBlue}+ {{<SUBCOMMAND>}@darkBlue}+",
|
|
242
|
+
"",
|
|
243
|
+
"{Mid command description}+",
|
|
244
|
+
"{{Mid command details.}-}*",
|
|
245
|
+
"{{Mid second line of command details.}-}*",
|
|
156
246
|
"",
|
|
157
247
|
"{{Positionals:}@darkGreen}+",
|
|
158
248
|
" {{<POS-1>}@darkBlue}+ Required positional number 1",
|
|
@@ -163,17 +253,21 @@ it("run", async () => {
|
|
|
163
253
|
" {{sub2}@darkCyan}+ Subcommand 2 description {{(Subcommand 2 hint)}-}*",
|
|
164
254
|
"",
|
|
165
255
|
"{{Options:}@darkGreen}+",
|
|
166
|
-
" {{-b}@darkCyan}+, {{--boolean-flag}@darkCyan}+{{[=no]}-}*
|
|
167
|
-
" {{-s}@darkCyan}+, {{--string-option}@darkCyan}+ {{<COOL-STUFF>}@darkBlue}+
|
|
168
|
-
" {{--complex-option}@darkCyan}+ {{<NUMBER,STRING[,STRING]...>}@darkBlue}+
|
|
256
|
+
" {{-b}@darkCyan}+, {{--boolean-flag}@darkCyan}+{{[=no]}-}* boolean-flag description",
|
|
257
|
+
" {{-s}@darkCyan}+, {{--string-option}@darkCyan}+ {{<COOL-STUFF>}@darkBlue}+ string-option description",
|
|
258
|
+
" {{--complex-option}@darkCyan}+ {{<NUMBER,STRING[,STRING]...>}@darkBlue}+ complex-option description",
|
|
259
|
+
"",
|
|
260
|
+
"{{Examples:}@darkGreen}+",
|
|
261
|
+
" {{# Example usage of the mid command}-}*",
|
|
262
|
+
" {{my-cli}@darkCyan}+ {{42}@darkBlue}+ {{-b}@darkCyan}+ {{43}@darkBlue}+",
|
|
169
263
|
"",
|
|
170
|
-
]
|
|
171
|
-
|
|
264
|
+
];
|
|
265
|
+
const usageSub1 = [
|
|
172
266
|
"{{Usage:}@darkMagenta}+ {{my-cli}@darkCyan}+ {{<POS-1>}@darkBlue}+ {{<POS-2>}@darkBlue}+ {{sub1}@darkCyan}+ {{<POS-STRING>}@darkBlue}+",
|
|
173
267
|
"",
|
|
174
268
|
"{Subcommand 1 description}+",
|
|
175
269
|
"{{Subcommand 1 details.}-}*",
|
|
176
|
-
"{{
|
|
270
|
+
"{{Subcommand 1 second line of details.}-}*",
|
|
177
271
|
"",
|
|
178
272
|
"{{Positionals:}@darkGreen}+",
|
|
179
273
|
" {{<POS-1>}@darkBlue}+ Required positional number 1",
|
|
@@ -181,17 +275,21 @@ it("run", async () => {
|
|
|
181
275
|
" {{<POS-STRING>}@darkBlue}+ Required positional string",
|
|
182
276
|
"",
|
|
183
277
|
"{{Options:}@darkGreen}+",
|
|
184
|
-
" {{-b}@darkCyan}+, {{--boolean-flag}@darkCyan}+{{[=no]}-}*
|
|
185
|
-
" {{-s}@darkCyan}+, {{--string-option}@darkCyan}+ {{<COOL-STUFF>}@darkBlue}+
|
|
186
|
-
" {{--complex-option}@darkCyan}+ {{<NUMBER,STRING[,STRING]...>}@darkBlue}+
|
|
278
|
+
" {{-b}@darkCyan}+, {{--boolean-flag}@darkCyan}+{{[=no]}-}* boolean-flag description",
|
|
279
|
+
" {{-s}@darkCyan}+, {{--string-option}@darkCyan}+ {{<COOL-STUFF>}@darkBlue}+ string-option description",
|
|
280
|
+
" {{--complex-option}@darkCyan}+ {{<NUMBER,STRING[,STRING]...>}@darkBlue}+ complex-option description",
|
|
281
|
+
"",
|
|
282
|
+
"{{Examples:}@darkGreen}+",
|
|
283
|
+
" {{# Example usage of subcommand 1}-}*",
|
|
284
|
+
" {{my-cli}@darkCyan}+ {{-b}@darkCyan}+ {{42}@darkBlue}+ {{43}@darkBlue}+ {{sub1}@darkCyan}+ {{valid}@darkBlue}+",
|
|
187
285
|
"",
|
|
188
|
-
]
|
|
189
|
-
|
|
286
|
+
];
|
|
287
|
+
const usageSub2 = [
|
|
190
288
|
"{{Usage:}@darkMagenta}+ {{my-cli}@darkCyan}+ {{<POS-1>}@darkBlue}+ {{<POS-2>}@darkBlue}+ {{sub2}@darkCyan}+ {{<POS-NUMBER>}@darkBlue}+ {{[OPT-POS]}@darkBlue}+ {{[VARIADIC]...}@darkBlue}+",
|
|
191
289
|
"",
|
|
192
290
|
"{Subcommand 2 description}+ {{(Subcommand 2 hint)}-}*",
|
|
193
291
|
"{{Subcommand 2 details.}-}*",
|
|
194
|
-
"{{
|
|
292
|
+
"{{Subcommand 2 second line of details.}-}*",
|
|
195
293
|
"",
|
|
196
294
|
"{{Positionals:}@darkGreen}+",
|
|
197
295
|
" {{<POS-1>}@darkBlue}+ Required positional number 1",
|
|
@@ -201,23 +299,46 @@ it("run", async () => {
|
|
|
201
299
|
" {{[VARIADIC]...}@darkBlue}+ Variadic positionals strings",
|
|
202
300
|
"",
|
|
203
301
|
"{{Options:}@darkGreen}+",
|
|
204
|
-
" {{-b}@darkCyan}+, {{--boolean-flag}@darkCyan}+{{[=no]}-}*
|
|
205
|
-
" {{-s}@darkCyan}+, {{--string-option}@darkCyan}+ {{<COOL-STUFF>}@darkBlue}+
|
|
206
|
-
" {{--complex-option}@darkCyan}+ {{<NUMBER,STRING[,STRING]...>}@darkBlue}+
|
|
302
|
+
" {{-b}@darkCyan}+, {{--boolean-flag}@darkCyan}+{{[=no]}-}* boolean-flag description",
|
|
303
|
+
" {{-s}@darkCyan}+, {{--string-option}@darkCyan}+ {{<COOL-STUFF>}@darkBlue}+ string-option description",
|
|
304
|
+
" {{--complex-option}@darkCyan}+ {{<NUMBER,STRING[,STRING]...>}@darkBlue}+ complex-option description",
|
|
207
305
|
" {{--dudu}@darkCyan}+ {{<STRING>}@darkBlue}+ Dudu option description {{(Dudu option hint)}-}*",
|
|
208
306
|
"",
|
|
209
|
-
|
|
307
|
+
"{{Examples:}@darkGreen}+",
|
|
308
|
+
" {{# Example usage of subcommand 2}-}*",
|
|
309
|
+
" {{my-cli}@darkCyan}+ {{40}@darkBlue}+ {{41}@darkBlue}+ {{sub2}@darkCyan}+ {{--dudu}@darkCyan}+{{=}-}*{{hello}@darkBlue}+ {{50}@darkBlue}+",
|
|
310
|
+
"",
|
|
311
|
+
];
|
|
312
|
+
|
|
313
|
+
expect(usage1).toStrictEqual(usageRoot);
|
|
314
|
+
expect(usage2).toStrictEqual(usageMid);
|
|
315
|
+
expect(usage3).toStrictEqual(usageMid);
|
|
316
|
+
expect(usage4).toStrictEqual(usageSub1);
|
|
317
|
+
expect(usage5).toStrictEqual(usageSub1);
|
|
318
|
+
expect(usage6).toStrictEqual(usageSub2);
|
|
319
|
+
expect(usage7).toStrictEqual(usageSub2);
|
|
210
320
|
});
|
|
211
321
|
|
|
212
322
|
async function getUsage<Context, Result>(
|
|
213
323
|
args: Array<string>,
|
|
214
|
-
command:
|
|
324
|
+
command: Command<Context, Result>,
|
|
215
325
|
) {
|
|
216
326
|
const readerArgs = new ReaderArgs(args);
|
|
217
|
-
const
|
|
327
|
+
const commandDecoder = command.consumeAndMakeDecoder(readerArgs);
|
|
328
|
+
/*
|
|
329
|
+
try {
|
|
330
|
+
const interpreter = commandDecoder.decodeAndMakeInterpreter();
|
|
331
|
+
const result = await interpreter.executeWithContext(
|
|
332
|
+
"" as unknown as Context,
|
|
333
|
+
);
|
|
334
|
+
console.log(result);
|
|
335
|
+
} catch (error) {
|
|
336
|
+
console.log(TypoSupport.tty().computeStyledErrorMessage(error));
|
|
337
|
+
}
|
|
338
|
+
*/
|
|
218
339
|
return usageToStyledLines({
|
|
219
340
|
cliName: "my-cli",
|
|
220
|
-
commandUsage:
|
|
221
|
-
typoSupport: TypoSupport.
|
|
341
|
+
commandUsage: commandDecoder.generateUsage(),
|
|
342
|
+
typoSupport: TypoSupport.tty(),
|
|
222
343
|
});
|
|
223
344
|
}
|