cli-kiss 0.2.3 → 0.2.4
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 -1
- package/dist/index.d.ts +643 -667
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/docs/.vitepress/config.mts +1 -3
- package/docs/.vitepress/theme/index.ts +4 -0
- package/docs/.vitepress/theme/style.css +4 -0
- package/docs/guide/02_commands.md +67 -31
- package/docs/guide/03_options.md +11 -10
- package/docs/guide/05_types.md +1 -1
- package/docs/guide/06_run.md +1 -1
- package/docs/index.md +8 -3
- package/docs/public/hero.png +0 -0
- package/package.json +1 -1
- package/src/lib/Command.ts +36 -93
- package/src/lib/Operation.ts +12 -30
- package/src/lib/Option.ts +120 -96
- package/src/lib/Positional.ts +9 -34
- package/src/lib/Reader.ts +122 -98
- package/src/lib/Run.ts +30 -17
- package/src/lib/Type.ts +26 -22
- package/src/lib/Typo.ts +62 -83
- package/src/lib/Usage.ts +174 -78
- package/tests/unit.Reader.aliases.ts +31 -15
- package/tests/unit.Reader.commons.ts +99 -43
- package/tests/unit.Reader.shortBig.ts +75 -31
- package/tests/unit.command.execute.ts +76 -33
- package/tests/unit.command.usage.ts +35 -35
- package/tests/unit.runner.cycle.ts +13 -13
- package/tests/unit.runner.errors.ts +19 -3
package/src/lib/Typo.ts
CHANGED
|
@@ -34,43 +34,43 @@ export type TypoStyle = {
|
|
|
34
34
|
*/
|
|
35
35
|
bgColor?: TypoColor;
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* Reduced intensity.
|
|
38
38
|
*/
|
|
39
39
|
dim?: boolean;
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* Bold.
|
|
42
42
|
*/
|
|
43
43
|
bold?: boolean;
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
45
|
+
* Italic.
|
|
46
46
|
*/
|
|
47
47
|
italic?: boolean;
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
49
|
+
* Underline.
|
|
50
50
|
*/
|
|
51
51
|
underline?: boolean;
|
|
52
52
|
/**
|
|
53
|
-
*
|
|
53
|
+
* Strikethrough.
|
|
54
54
|
*/
|
|
55
55
|
strikethrough?: boolean;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
|
-
*
|
|
59
|
+
* Section title style. Bold dark-green.
|
|
60
60
|
*/
|
|
61
61
|
export const typoStyleTitle: TypoStyle = {
|
|
62
62
|
fgColor: "darkGreen",
|
|
63
63
|
bold: true,
|
|
64
64
|
};
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
66
|
+
* Logic/type identifier style. Bold dark-magenta.
|
|
67
67
|
*/
|
|
68
68
|
export const typoStyleLogic: TypoStyle = {
|
|
69
69
|
fgColor: "darkMagenta",
|
|
70
70
|
bold: true,
|
|
71
71
|
};
|
|
72
72
|
/**
|
|
73
|
-
*
|
|
73
|
+
* Quoted user-input style. Bold dark-yellow.
|
|
74
74
|
*/
|
|
75
75
|
export const typoStyleQuote: TypoStyle = {
|
|
76
76
|
fgColor: "darkYellow",
|
|
@@ -78,7 +78,7 @@ export const typoStyleQuote: TypoStyle = {
|
|
|
78
78
|
};
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
|
-
*
|
|
81
|
+
* Error label style. Bold dark-red.
|
|
82
82
|
*/
|
|
83
83
|
export const typoStyleFailure: TypoStyle = {
|
|
84
84
|
fgColor: "darkRed",
|
|
@@ -86,14 +86,14 @@ export const typoStyleFailure: TypoStyle = {
|
|
|
86
86
|
};
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
|
-
*
|
|
89
|
+
* Option/command name style. Bold dark-cyan.
|
|
90
90
|
*/
|
|
91
91
|
export const typoStyleConstants: TypoStyle = {
|
|
92
92
|
fgColor: "darkCyan",
|
|
93
93
|
bold: true,
|
|
94
94
|
};
|
|
95
95
|
/**
|
|
96
|
-
*
|
|
96
|
+
* Positional/user-input label style. Bold dark-blue.
|
|
97
97
|
*/
|
|
98
98
|
export const typoStyleUserInput: TypoStyle = {
|
|
99
99
|
fgColor: "darkBlue",
|
|
@@ -101,13 +101,13 @@ export const typoStyleUserInput: TypoStyle = {
|
|
|
101
101
|
};
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
|
-
*
|
|
104
|
+
* Strong text style. Bold.
|
|
105
105
|
*/
|
|
106
106
|
export const typoStyleRegularStrong: TypoStyle = {
|
|
107
107
|
bold: true,
|
|
108
108
|
};
|
|
109
109
|
/**
|
|
110
|
-
*
|
|
110
|
+
* Subtle text style. Italic and dim.
|
|
111
111
|
*/
|
|
112
112
|
export const typoStyleRegularWeaker: TypoStyle = {
|
|
113
113
|
italic: true,
|
|
@@ -115,8 +115,7 @@ export const typoStyleRegularWeaker: TypoStyle = {
|
|
|
115
115
|
};
|
|
116
116
|
|
|
117
117
|
/**
|
|
118
|
-
*
|
|
119
|
-
* Compose multiple segments into a {@link TypoText}; rendering is deferred to {@link TypoString.computeStyledString}.
|
|
118
|
+
* Immutable styled string segment. Compose into a {@link TypoText}.
|
|
120
119
|
*/
|
|
121
120
|
export class TypoString {
|
|
122
121
|
#value: string;
|
|
@@ -129,12 +128,6 @@ export class TypoString {
|
|
|
129
128
|
this.#value = value;
|
|
130
129
|
this.#typoStyle = typoStyle;
|
|
131
130
|
}
|
|
132
|
-
/**
|
|
133
|
-
* Returns the unstyled raw text content.
|
|
134
|
-
*/
|
|
135
|
-
getRawString(): string {
|
|
136
|
-
return this.#value;
|
|
137
|
-
}
|
|
138
131
|
/**
|
|
139
132
|
* Returns the text styled by `typoSupport`.
|
|
140
133
|
*
|
|
@@ -143,53 +136,46 @@ export class TypoString {
|
|
|
143
136
|
computeStyledString(typoSupport: TypoSupport): string {
|
|
144
137
|
return typoSupport.computeStyledString(this.#value, this.#typoStyle);
|
|
145
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Returns the raw text.
|
|
141
|
+
*/
|
|
142
|
+
getRawString(): string {
|
|
143
|
+
return this.#value;
|
|
144
|
+
}
|
|
146
145
|
}
|
|
147
146
|
|
|
148
147
|
/**
|
|
149
|
-
*
|
|
150
|
-
* Rendering is deferred to {@link TypoText.computeStyledString}.
|
|
148
|
+
* Mutable sequence of {@link TypoString} segments.
|
|
151
149
|
*/
|
|
152
150
|
export class TypoText {
|
|
153
151
|
#typoStrings: Array<TypoString>;
|
|
154
152
|
/**
|
|
155
|
-
* @param
|
|
153
|
+
* @param segments - Initial text segments
|
|
156
154
|
*/
|
|
157
|
-
constructor(
|
|
155
|
+
constructor(
|
|
156
|
+
...segments: Array<TypoText | Array<TypoString> | TypoString | string>
|
|
157
|
+
) {
|
|
158
158
|
this.#typoStrings = [];
|
|
159
|
-
for (const typoPart of
|
|
160
|
-
|
|
161
|
-
this.pushText(typoPart);
|
|
162
|
-
} else if (typoPart instanceof TypoString) {
|
|
163
|
-
this.pushString(typoPart);
|
|
164
|
-
} else if (typeof typoPart === "string") {
|
|
165
|
-
this.pushString(new TypoString(typoPart));
|
|
166
|
-
}
|
|
159
|
+
for (const typoPart of segments) {
|
|
160
|
+
this.push(typoPart);
|
|
167
161
|
}
|
|
168
162
|
}
|
|
169
163
|
/**
|
|
170
|
-
* Appends
|
|
164
|
+
* Appends new text segment(s).
|
|
171
165
|
*
|
|
172
|
-
* @param
|
|
166
|
+
* @param segment - Text segment(s) to append.
|
|
173
167
|
*/
|
|
174
|
-
|
|
175
|
-
if (typeof
|
|
176
|
-
this.#typoStrings.push(new TypoString(
|
|
177
|
-
} else {
|
|
178
|
-
this.#typoStrings.push(
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Appends all segments from another {@link TypoText} (shallow copy).
|
|
183
|
-
*
|
|
184
|
-
* @param typoText - Source text.
|
|
185
|
-
*/
|
|
186
|
-
pushText(typoText: TypoText | string) {
|
|
187
|
-
if (typeof typoText === "string") {
|
|
188
|
-
this.pushString(typoText);
|
|
189
|
-
} else {
|
|
190
|
-
for (const typoString of typoText.#typoStrings) {
|
|
168
|
+
push(segment: TypoText | Array<TypoString> | TypoString | string) {
|
|
169
|
+
if (typeof segment === "string") {
|
|
170
|
+
this.#typoStrings.push(new TypoString(segment));
|
|
171
|
+
} else if (segment instanceof TypoText) {
|
|
172
|
+
this.#typoStrings.push(...segment.#typoStrings);
|
|
173
|
+
} else if (Array.isArray(segment)) {
|
|
174
|
+
for (const typoString of segment) {
|
|
191
175
|
this.#typoStrings.push(typoString);
|
|
192
176
|
}
|
|
177
|
+
} else {
|
|
178
|
+
this.#typoStrings.push(segment);
|
|
193
179
|
}
|
|
194
180
|
}
|
|
195
181
|
/**
|
|
@@ -204,13 +190,13 @@ export class TypoText {
|
|
|
204
190
|
.join("");
|
|
205
191
|
}
|
|
206
192
|
/**
|
|
207
|
-
* Returns the
|
|
193
|
+
* Returns the concatenated raw text.
|
|
208
194
|
*/
|
|
209
195
|
computeRawString(): string {
|
|
210
196
|
return this.#typoStrings.map((t) => t.getRawString()).join("");
|
|
211
197
|
}
|
|
212
198
|
/**
|
|
213
|
-
* Returns the total character count
|
|
199
|
+
* Returns the total raw character count.
|
|
214
200
|
*/
|
|
215
201
|
computeRawLength(): number {
|
|
216
202
|
let length = 0;
|
|
@@ -222,9 +208,8 @@ export class TypoText {
|
|
|
222
208
|
}
|
|
223
209
|
|
|
224
210
|
/**
|
|
225
|
-
*
|
|
211
|
+
* Column-aligned grid of {@link TypoText} cells.
|
|
226
212
|
* Each column is padded to the widest cell (raw chars); the last column is not padded.
|
|
227
|
-
* Used by {@link usageToStyledLines} to render `Positionals:`, `Subcommands:`, and `Options:`.
|
|
228
213
|
*/
|
|
229
214
|
export class TypoGrid {
|
|
230
215
|
#typoRows: Array<Array<TypoText>>;
|
|
@@ -232,7 +217,7 @@ export class TypoGrid {
|
|
|
232
217
|
this.#typoRows = [];
|
|
233
218
|
}
|
|
234
219
|
/**
|
|
235
|
-
* Appends a row. All rows should have the same cell count
|
|
220
|
+
* Appends a row. All rows should have the same cell count.
|
|
236
221
|
*
|
|
237
222
|
* @param cells - Ordered {@link TypoText} cells.
|
|
238
223
|
*/
|
|
@@ -240,15 +225,14 @@ export class TypoGrid {
|
|
|
240
225
|
this.#typoRows.push(cells);
|
|
241
226
|
}
|
|
242
227
|
/**
|
|
243
|
-
* Renders
|
|
244
|
-
* Join each inner array with `""` to get a line.
|
|
228
|
+
* Renders as an array of styled, column-padded strings.
|
|
245
229
|
*
|
|
246
230
|
* @param typoSupport - Rendering mode.
|
|
247
231
|
* @returns 2-D array of styled strings.
|
|
248
232
|
*/
|
|
249
|
-
|
|
233
|
+
computeStyledLines(typoSupport: TypoSupport): Array<string> {
|
|
250
234
|
const widths = new Array<number>();
|
|
251
|
-
const
|
|
235
|
+
const styledLines = new Array<string>();
|
|
252
236
|
for (const typoGridRow of this.#typoRows) {
|
|
253
237
|
for (
|
|
254
238
|
let typoGridColumnIndex = 0;
|
|
@@ -266,31 +250,29 @@ export class TypoGrid {
|
|
|
266
250
|
}
|
|
267
251
|
}
|
|
268
252
|
for (const typoGridRow of this.#typoRows) {
|
|
269
|
-
const
|
|
253
|
+
const styledGridRow = new Array<string>();
|
|
270
254
|
for (
|
|
271
255
|
let typoGridColumnIndex = 0;
|
|
272
256
|
typoGridColumnIndex < typoGridRow.length;
|
|
273
257
|
typoGridColumnIndex++
|
|
274
258
|
) {
|
|
275
259
|
const typoGridCell = typoGridRow[typoGridColumnIndex]!;
|
|
276
|
-
|
|
277
|
-
printableGridRow.push(printableGridCell);
|
|
260
|
+
styledGridRow.push(typoGridCell.computeStyledString(typoSupport));
|
|
278
261
|
if (typoGridColumnIndex < typoGridRow.length - 1) {
|
|
279
262
|
const width = typoGridCell.computeRawLength();
|
|
280
263
|
const padding = " ".repeat(widths[typoGridColumnIndex]! - width);
|
|
281
|
-
|
|
264
|
+
styledGridRow.push(padding);
|
|
282
265
|
}
|
|
283
266
|
}
|
|
284
|
-
|
|
267
|
+
styledLines.push(styledGridRow.join(""));
|
|
285
268
|
}
|
|
286
|
-
return
|
|
269
|
+
return styledLines;
|
|
287
270
|
}
|
|
288
271
|
}
|
|
289
272
|
|
|
290
273
|
/**
|
|
291
274
|
* `Error` subclass with a {@link TypoText} styled message for rich terminal output.
|
|
292
|
-
*
|
|
293
|
-
* If `source` is a `TypoError`, its styled text is chained after `": "`.
|
|
275
|
+
* Chains `TypoError` sources after `": "`.
|
|
294
276
|
*/
|
|
295
277
|
export class TypoError extends Error {
|
|
296
278
|
#typoText: TypoText;
|
|
@@ -300,20 +282,20 @@ export class TypoError extends Error {
|
|
|
300
282
|
*/
|
|
301
283
|
constructor(currentTypoText: TypoText, source?: unknown) {
|
|
302
284
|
const typoText = new TypoText();
|
|
303
|
-
typoText.
|
|
285
|
+
typoText.push(currentTypoText);
|
|
304
286
|
if (source instanceof TypoError) {
|
|
305
|
-
typoText.
|
|
306
|
-
typoText.
|
|
287
|
+
typoText.push(new TypoString(": "));
|
|
288
|
+
typoText.push(source.#typoText);
|
|
307
289
|
} else if (source instanceof Error) {
|
|
308
|
-
typoText.
|
|
290
|
+
typoText.push(new TypoString(`: ${source.message}`));
|
|
309
291
|
} else if (source !== undefined) {
|
|
310
|
-
typoText.
|
|
292
|
+
typoText.push(new TypoString(`: ${String(source)}`));
|
|
311
293
|
}
|
|
312
294
|
super(typoText.computeRawString());
|
|
313
295
|
this.#typoText = typoText;
|
|
314
296
|
}
|
|
315
297
|
/**
|
|
316
|
-
* Renders the styled
|
|
298
|
+
* Renders the styled message (without `"Error:"` prefix).
|
|
317
299
|
*
|
|
318
300
|
* @param typoSupport - Rendering mode.
|
|
319
301
|
* @returns Styled error string.
|
|
@@ -322,8 +304,7 @@ export class TypoError extends Error {
|
|
|
322
304
|
return this.#typoText.computeStyledString(typoSupport);
|
|
323
305
|
}
|
|
324
306
|
/**
|
|
325
|
-
* Runs `thrower`;
|
|
326
|
-
* Useful for adding call-chain context (e.g. `"at 0: Number: ..."`).
|
|
307
|
+
* Runs `thrower`; wraps any thrown error as a `TypoError` with `context()` prepended.
|
|
327
308
|
*
|
|
328
309
|
* @typeParam Value - Return type of `thrower`.
|
|
329
310
|
* @param thrower - Function to execute; result passed through on success.
|
|
@@ -344,9 +325,7 @@ export class TypoError extends Error {
|
|
|
344
325
|
}
|
|
345
326
|
|
|
346
327
|
/**
|
|
347
|
-
* Controls ANSI terminal styling
|
|
348
|
-
* Create via {@link TypoSupport.none}, {@link TypoSupport.tty}, {@link TypoSupport.mock},
|
|
349
|
-
* or {@link TypoSupport.inferFromProcess}.
|
|
328
|
+
* Controls ANSI terminal styling. Create via the static factory methods.
|
|
350
329
|
*/
|
|
351
330
|
export class TypoSupport {
|
|
352
331
|
#kind: "none" | "tty" | "mock";
|
|
@@ -354,19 +333,19 @@ export class TypoSupport {
|
|
|
354
333
|
this.#kind = kind;
|
|
355
334
|
}
|
|
356
335
|
/**
|
|
357
|
-
*
|
|
336
|
+
* Plain text — no ANSI codes.
|
|
358
337
|
*/
|
|
359
338
|
static none(): TypoSupport {
|
|
360
339
|
return new TypoSupport("none");
|
|
361
340
|
}
|
|
362
341
|
/**
|
|
363
|
-
*
|
|
342
|
+
* ANSI escape codes for color terminals.
|
|
364
343
|
*/
|
|
365
344
|
static tty(): TypoSupport {
|
|
366
345
|
return new TypoSupport("tty");
|
|
367
346
|
}
|
|
368
347
|
/**
|
|
369
|
-
*
|
|
348
|
+
* Deterministic textual styling for snapshot tests.
|
|
370
349
|
* Style flags appear as suffixes: `{text}@color`, `{text}+` (bold), `{text}-` (dim),
|
|
371
350
|
* `{text}*` (italic), `{text}_` (underline), `{text}~` (strikethrough).
|
|
372
351
|
*/
|