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/src/lib/Typo.ts CHANGED
@@ -34,43 +34,43 @@ export type TypoStyle = {
34
34
  */
35
35
  bgColor?: TypoColor;
36
36
  /**
37
- * Render with reduced intensity.
37
+ * Reduced intensity.
38
38
  */
39
39
  dim?: boolean;
40
40
  /**
41
- * Render in bold.
41
+ * Bold.
42
42
  */
43
43
  bold?: boolean;
44
44
  /**
45
- * Render in italic.
45
+ * Italic.
46
46
  */
47
47
  italic?: boolean;
48
48
  /**
49
- * Render with an underline.
49
+ * Underline.
50
50
  */
51
51
  underline?: boolean;
52
52
  /**
53
- * Render with a strikethrough.
53
+ * Strikethrough.
54
54
  */
55
55
  strikethrough?: boolean;
56
56
  };
57
57
 
58
58
  /**
59
- * Pre-defined style for section titles (e.g. `"Positionals:"`). Bold dark-green.
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
- * Pre-defined style for logic/type identifiers in error messages. Bold dark-magenta.
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
- * Pre-defined style for quoted user-supplied values in error messages. Bold dark-yellow.
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
- * Pre-defined style for failure/error labels (e.g. `"Error:"`). Bold dark-red.
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
- * Pre-defined style for CLI flag/option/command names. Bold dark-cyan.
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
- * Pre-defined style for positional placeholders and user-input labels. Bold dark-blue.
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
- * Pre-defined style for strong regular text (e.g. command descriptions). Bold.
104
+ * Strong text style. Bold.
105
105
  */
106
106
  export const typoStyleRegularStrong: TypoStyle = {
107
107
  bold: true,
108
108
  };
109
109
  /**
110
- * Pre-defined style for subtle supplementary text (e.g. hints). Italic and dim.
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
- * An immutable styled string segment: a raw text value paired with a {@link TypoStyle}.
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
- * A mutable sequence of {@link TypoString} segments forming a styled multi-part message.
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 typoParts - Initial segments; `TypoText` is flattened, `string` is wrapped unstyled.
153
+ * @param segments - Initial text segments
156
154
  */
157
- constructor(...typoParts: Array<TypoText | TypoString | string>) {
155
+ constructor(
156
+ ...segments: Array<TypoText | Array<TypoString> | TypoString | string>
157
+ ) {
158
158
  this.#typoStrings = [];
159
- for (const typoPart of typoParts) {
160
- if (typoPart instanceof TypoText) {
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 a {@link TypoString} segment.
164
+ * Appends new text segment(s).
171
165
  *
172
- * @param typoString - Segment to append.
166
+ * @param segment - Text segment(s) to append.
173
167
  */
174
- pushString(typoString: TypoString | string) {
175
- if (typeof typoString === "string") {
176
- this.#typoStrings.push(new TypoString(typoString));
177
- } else {
178
- this.#typoStrings.push(typoString);
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 concatenation of all segments' raw (unstyled) text.
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 of the raw (unstyled) text.
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
- * A column-aligned grid of {@link TypoText} cells.
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 for alignment to be meaningful.
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 the grid as a 2-D array of styled (and column-padded) strings.
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
- computeStyledGrid(typoSupport: TypoSupport): Array<Array<string>> {
233
+ computeStyledLines(typoSupport: TypoSupport): Array<string> {
250
234
  const widths = new Array<number>();
251
- const printableGrid = new Array<Array<string>>();
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 printableGridRow = new Array<string>();
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
- const printableGridCell = typoGridCell.computeStyledString(typoSupport);
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
- printableGridRow.push(padding);
264
+ styledGridRow.push(padding);
282
265
  }
283
266
  }
284
- printableGrid.push(printableGridRow);
267
+ styledLines.push(styledGridRow.join(""));
285
268
  }
286
- return printableGrid;
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
- * Used throughout the library for parse failures (unknown option, type decode error, etc.).
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.pushText(currentTypoText);
285
+ typoText.push(currentTypoText);
304
286
  if (source instanceof TypoError) {
305
- typoText.pushString(new TypoString(": "));
306
- typoText.pushText(source.#typoText);
287
+ typoText.push(new TypoString(": "));
288
+ typoText.push(source.#typoText);
307
289
  } else if (source instanceof Error) {
308
- typoText.pushString(new TypoString(`: ${source.message}`));
290
+ typoText.push(new TypoString(`: ${source.message}`));
309
291
  } else if (source !== undefined) {
310
- typoText.pushString(new TypoString(`: ${String(source)}`));
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 error message (without a `"Error:"` prefix).
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`; on any throw wraps it as a `TypoError` with `context()` prepended.
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 for {@link TypoString}, {@link TypoText}, and error rendering.
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
- * Returns a `TypoSupport` that strips all styling (plain text, no ANSI codes).
336
+ * Plain text no ANSI codes.
358
337
  */
359
338
  static none(): TypoSupport {
360
339
  return new TypoSupport("none");
361
340
  }
362
341
  /**
363
- * Returns a `TypoSupport` that applies ANSI escape codes (for color-capable terminals).
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
- * Returns a `TypoSupport` with deterministic textual styling for snapshot tests.
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
  */