@flowscripter/dynamic-cli-framework 1.2.2 → 1.3.0
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/core-service-providers.md +2 -2
- package/README/development.md +3 -6
- package/README/implementation-details.md +17 -17
- package/README/key-concepts.md +17 -17
- package/README.md +4 -4
- package/bun.lock +0 -2
- package/index.ts +22 -30
- package/package.json +19 -19
- package/src/api/argument/Argument.ts +1 -1
- package/src/api/argument/ArgumentValueTypes.ts +3 -10
- package/src/api/argument/ComplexOption.ts +5 -9
- package/src/api/command/GlobalCommand.ts +1 -4
- package/src/api/service/core/ArgumentPrompterService.ts +1 -3
- package/src/api/service/core/AsciiBannerGeneratorService.ts +1 -4
- package/src/api/service/core/CompletionService.ts +2 -6
- package/src/api/service/core/ImagePrinterService.ts +1 -2
- package/src/api/service/core/KeyValueService.ts +1 -2
- package/src/api/service/core/PrettyPrinterService.ts +1 -4
- package/src/api/service/core/PrinterService.ts +8 -9
- package/src/api/service/core/PrompterService.ts +4 -11
- package/src/api/service/core/ShutdownService.ts +1 -2
- package/src/api/service/core/SyntaxHighlighterService.ts +1 -5
- package/src/api/service/core/Table.ts +7 -25
- package/src/api/service/core/TreePrinterService.ts +1 -2
- package/src/cli/BaseCLI.ts +17 -47
- package/src/cli/DefaultRuntimeCLI.ts +1 -4
- package/src/command/CompletionCommand.ts +19 -45
- package/src/command/MultiCommandCliHelpCommand.ts +45 -92
- package/src/command/SingleCommandCliHelpCommand.ts +17 -28
- package/src/command/UsageCommand.ts +6 -12
- package/src/command/VersionCommand.ts +2 -6
- package/src/launcher.ts +4 -2
- package/src/runtime/DefaultContext.ts +2 -5
- package/src/runtime/argument/ArgumentTypeGuards.ts +1 -3
- package/src/runtime/command/CommandTypeGuards.ts +5 -14
- package/src/runtime/command/CommandValidator.ts +56 -118
- package/src/runtime/parser.ts +13 -17
- package/src/runtime/registry/CommandRegistry.ts +2 -7
- package/src/runtime/registry/DefaultCommandRegistry.ts +32 -84
- package/src/runtime/registry/DefaultServiceProviderRegistry.ts +3 -9
- package/src/runtime/runner.ts +103 -142
- package/src/runtime/scanner.ts +28 -46
- package/src/runtime/values/ValuePopulationResult.ts +1 -2
- package/src/runtime/values/argumentValueMerge.ts +16 -28
- package/src/runtime/values/argumentValueValidation.ts +21 -67
- package/src/runtime/values/globalCommandValuePopulation.ts +9 -18
- package/src/runtime/values/subCommandValuePopulation.ts +42 -65
- package/src/service/argumentPrompter/ArgumentPrompterServiceProvider.ts +3 -10
- package/src/service/argumentPrompter/DefaultArgumentPrompterService.ts +22 -59
- package/src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.ts +5 -14
- package/src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.ts +59 -77
- package/src/service/banner/BannerServiceProvider.ts +13 -35
- package/src/service/banner/command/NoBannerCommand.ts +2 -8
- package/src/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.ts +5 -10
- package/src/service/completion/CompletionServiceProvider.ts +20 -48
- package/src/service/completion/DefaultCompletionService.ts +17 -56
- package/src/service/completion/shell/ShellHandler.ts +1 -3
- package/src/service/completion/shell/fish.ts +1 -1
- package/src/service/completion/shell/powershell.ts +2 -12
- package/src/service/completion/shell/zsh.ts +1 -1
- package/src/service/configuration/ConfigurationServiceProvider.ts +40 -133
- package/src/service/configuration/DefaultKeyValueService.ts +6 -20
- package/src/service/configuration/DefaultSecretService.ts +10 -14
- package/src/service/configuration/command/ConfigCommand.ts +1 -4
- package/src/service/configuration/command/DumpConfigCommand.ts +9 -21
- package/src/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.ts +5 -14
- package/src/service/dataDumpGenerator/DefaultDataDumpGeneratorService.ts +5 -12
- package/src/service/imagePrinter/DefaultImagePrinterService.ts +1 -5
- package/src/service/imagePrinter/ImagePrinterServiceProvider.ts +1 -4
- package/src/service/prettyPrinter/DefaultPrettyPrinterService.ts +4 -12
- package/src/service/prettyPrinter/PrettyPrinterServiceProvider.ts +3 -10
- package/src/service/printer/DefaultPrinterService.ts +20 -83
- package/src/service/printer/PrinterServiceProvider.ts +3 -11
- package/src/service/printer/command/DarkModeCommand.ts +3 -10
- package/src/service/printer/command/LogLevelCommand.ts +7 -26
- package/src/service/printer/command/NoColorCommand.ts +3 -10
- package/src/service/printer/command/NoHyperlinksCommand.ts +3 -10
- package/src/service/printer/terminal/Progress.ts +99 -90
- package/src/service/printer/terminal/Spinner.ts +7 -26
- package/src/service/prompter/DefaultPrompterService.ts +2 -6
- package/src/service/prompter/PrompterServiceProvider.ts +3 -11
- package/src/service/prompter/command/NoPromptCommand.ts +3 -10
- package/src/service/prompter/prompt/PromptContext.ts +5 -18
- package/src/service/prompter/prompt/promptMultiSelect.ts +6 -21
- package/src/service/prompter/prompt/promptOpenUrl.ts +7 -22
- package/src/service/prompter/prompt/promptSingleSelect.ts +6 -23
- package/src/service/prompter/prompt/promptText.ts +10 -27
- package/src/service/prompter/prompt/promptToggle.ts +8 -8
- package/src/service/shutdown/ShutdownServiceProvider.ts +3 -10
- package/src/service/syntaxHighlighter/DefaultSyntaxHighlighterService.ts +13 -26
- package/src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.ts +8 -21
- package/src/service/tableGenerator/DefaultTableGeneratorService.ts +44 -68
- package/src/service/tableGenerator/TableGeneratorServiceProvider.ts +7 -16
- package/src/service/treePrinter/DefaultTreePrinterService.ts +2 -7
- package/src/service/treePrinter/TreePrinterServiceProvider.ts +4 -12
- package/src/terminal/ImageRenderer.ts +35 -54
- package/src/terminal/PngDecoder.ts +10 -19
- package/src/terminal/TtyStyler.ts +11 -9
- package/src/terminal/TtyTerminal.ts +2 -10
- package/src/terminal/supportsHyperlinks.ts +4 -10
- package/src/util/configHelper.ts +3 -10
- package/src/util/envVarHelper.ts +50 -88
- package/src/util/helpHelper.ts +123 -193
- package/src/util/logger.ts +12 -42
- package/src/util/runnerHelper.ts +20 -61
- package/tests/cli/BaseCLI.test.ts +23 -80
- package/tests/command/CompletionCommand.test.ts +1 -6
- package/tests/command/MultiCommandCliHelpCommand.test.ts +51 -205
- package/tests/command/SingleCommandCliHelpCommand.test.ts +21 -103
- package/tests/command/UsageCommand.test.ts +4 -10
- package/tests/fixtures/Command.ts +87 -68
- package/tests/fixtures/CommandRegistry.ts +1 -3
- package/tests/fixtures/Context.ts +3 -11
- package/tests/fixtures/ServiceProviderRegistry.ts +1 -1
- package/tests/fixtures/prettierPluginFoo.ts +1 -1
- package/tests/fixtures/util.ts +2 -8
- package/tests/runtime/argument/ArgumentTypeGuards.test.ts +1 -3
- package/tests/runtime/command/CommandValidator.test.ts +881 -604
- package/tests/runtime/parser.test.ts +222 -246
- package/tests/runtime/registry/DefaultCommandRegistry.test.ts +15 -37
- package/tests/runtime/registry/DefaultServiceProviderRegistry.test.ts +2 -8
- package/tests/runtime/runner.test.ts +231 -281
- package/tests/runtime/scanner.test.ts +277 -475
- package/tests/runtime/values/argumentValueMerge.test.ts +133 -81
- package/tests/runtime/values/argumentValueValidation.test.ts +444 -588
- package/tests/runtime/values/globalCommandValuePopulation.test.ts +71 -253
- package/tests/runtime/values/subCommandValuePopulation.test.ts +1342 -1570
- package/tests/service/argumentPrompter/ArgumentPrompterServiceProvider.test.ts +3 -12
- package/tests/service/argumentPrompter/DefaultArgumentPrompterService.test.ts +36 -45
- package/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.ts +2 -8
- package/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.ts +40 -62
- package/tests/service/banner/BannerServiceProvider.test.ts +5 -18
- package/tests/service/banner/command/NoBannerCommand.test.ts +1 -4
- package/tests/service/completion/CompletionServiceProvider.test.ts +145 -214
- package/tests/service/completion/DefaultCompletionService.test.ts +17 -79
- package/tests/service/completion/shell/fish.test.ts +1 -3
- package/tests/service/configuration/ConfigurationServiceProvider.test.ts +26 -75
- package/tests/service/configuration/DefaultKeyValueService.test.ts +9 -21
- package/tests/service/configuration/DefaultSecretService.test.ts +7 -15
- package/tests/service/configuration/command/DumpConfigCommand.test.ts +4 -13
- package/tests/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.test.ts +6 -12
- package/tests/service/dataDumpGenerator/DefaultDataDumpGeneratorService.test.ts +1 -10
- package/tests/service/imagePrinter/DefaultImagePrinterService.test.ts +5 -70
- package/tests/service/prettyPrinter/DefaultPrettyPrinterService.test.ts +4 -11
- package/tests/service/prettyPrinter/PrettyPrinterServiceProvider.test.ts +2 -6
- package/tests/service/printer/DefaultPrinterService.test.ts +57 -255
- package/tests/service/printer/PrinterServiceProvider.test.ts +2 -8
- package/tests/service/printer/command/DarkModeCommand.test.ts +4 -12
- package/tests/service/printer/command/LogLevelCommand.test.ts +4 -17
- package/tests/service/printer/command/NoColorCommand.test.ts +4 -12
- package/tests/service/printer/command/NoHyperlinksCommand.test.ts +7 -21
- package/tests/service/printer/terminal/Progress.test.ts +1 -3
- package/tests/service/printer/terminal/Spinner.test.ts +2 -8
- package/tests/service/prompter/DefaultPrompterService.test.ts +52 -69
- package/tests/service/prompter/PrompterServiceProvider.test.ts +2 -8
- package/tests/service/shutdown/ShutdownServiceProvider.test.ts +1 -3
- package/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.ts +13 -99
- package/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.ts +2 -7
- package/tests/service/tableGenerator/DefaultTableGeneratorService.test.ts +12 -33
- package/tests/service/tableGenerator/TableGeneratorServiceProvider.test.ts +2 -2
- package/tests/service/treePrinter/DefaultTreePrinterService.test.ts +4 -6
- package/tests/service/treePrinter/TreePrinterServiceProvider.test.ts +4 -8
- package/tests/terminal/ImageRenderer.test.ts +2 -11
- package/tests/terminal/PngDecoder.test.ts +2 -6
- package/tests/util/configHelper.test.ts +55 -137
- package/tests/util/envVarHelper.test.ts +46 -110
|
@@ -18,20 +18,12 @@ const BORDER_BOTTOM = "─";
|
|
|
18
18
|
const BORDER_BOTTOM_MIDDLE = "┴";
|
|
19
19
|
const BORDER_BOTTOM_RIGHT = "┘";
|
|
20
20
|
|
|
21
|
-
export default class DefaultTableGeneratorService
|
|
22
|
-
implements TableGeneratorService {
|
|
21
|
+
export default class DefaultTableGeneratorService implements TableGeneratorService {
|
|
23
22
|
colorEnabled = true;
|
|
24
|
-
colorFunction: (text: string, hexFormattedColor: string) => string = (
|
|
25
|
-
|
|
26
|
-
) => text;
|
|
27
|
-
backgroundColorFunction: (text: string, hexFormattedColor: string) => string =
|
|
28
|
-
(text) => text;
|
|
23
|
+
colorFunction: (text: string, hexFormattedColor: string) => string = (text) => text;
|
|
24
|
+
backgroundColorFunction: (text: string, hexFormattedColor: string) => string = (text) => text;
|
|
29
25
|
|
|
30
|
-
#resolveAlign(
|
|
31
|
-
table: Table,
|
|
32
|
-
rowIndex: number,
|
|
33
|
-
columnIndex: number,
|
|
34
|
-
): Align {
|
|
26
|
+
#resolveAlign(table: Table, rowIndex: number, columnIndex: number): Align {
|
|
35
27
|
const cellOpts = table.getCell(rowIndex, columnIndex)?.options;
|
|
36
28
|
if (cellOpts?.align !== undefined) return cellOpts.align;
|
|
37
29
|
const rowOpts = table.getRowOptions(rowIndex);
|
|
@@ -46,14 +38,9 @@ export default class DefaultTableGeneratorService
|
|
|
46
38
|
const padding = table.options.padding ?? 1;
|
|
47
39
|
const maxWidth = table.options.maxWidth ?? 80;
|
|
48
40
|
|
|
49
|
-
const borderOverhead = border
|
|
50
|
-
? table.columnCount + 1
|
|
51
|
-
: Math.max(table.columnCount - 1, 0);
|
|
41
|
+
const borderOverhead = border ? table.columnCount + 1 : Math.max(table.columnCount - 1, 0);
|
|
52
42
|
const paddingOverhead = table.columnCount * 2 * padding;
|
|
53
|
-
const contentBudget = Math.max(
|
|
54
|
-
maxWidth - borderOverhead - paddingOverhead,
|
|
55
|
-
table.columnCount,
|
|
56
|
-
);
|
|
43
|
+
const contentBudget = Math.max(maxWidth - borderOverhead - paddingOverhead, table.columnCount);
|
|
57
44
|
|
|
58
45
|
const naturalWidths: number[] = [];
|
|
59
46
|
for (let col = 0; col < table.columnCount; col++) {
|
|
@@ -103,12 +90,7 @@ export default class DefaultTableGeneratorService
|
|
|
103
90
|
return total;
|
|
104
91
|
}
|
|
105
92
|
|
|
106
|
-
#distributeGrow(
|
|
107
|
-
table: Table,
|
|
108
|
-
widths: number[],
|
|
109
|
-
surplus: number,
|
|
110
|
-
totalFlexWeight: number,
|
|
111
|
-
): void {
|
|
93
|
+
#distributeGrow(table: Table, widths: number[], surplus: number, totalFlexWeight: number): void {
|
|
112
94
|
let remaining = surplus;
|
|
113
95
|
for (let col = 0; col < table.columnCount; col++) {
|
|
114
96
|
const colOpts = table.getColumnOptions(col);
|
|
@@ -139,11 +121,7 @@ export default class DefaultTableGeneratorService
|
|
|
139
121
|
}
|
|
140
122
|
}
|
|
141
123
|
|
|
142
|
-
#distributeShrink(
|
|
143
|
-
table: Table,
|
|
144
|
-
widths: number[],
|
|
145
|
-
excess: number,
|
|
146
|
-
): void {
|
|
124
|
+
#distributeShrink(table: Table, widths: number[], excess: number): void {
|
|
147
125
|
let remaining = excess;
|
|
148
126
|
const shrinkable = new Set<number>();
|
|
149
127
|
for (let col = 0; col < table.columnCount; col++) {
|
|
@@ -168,9 +146,7 @@ export default class DefaultTableGeneratorService
|
|
|
168
146
|
const weight = colOpts?.flexWeight ?? 0;
|
|
169
147
|
const share = Math.max(
|
|
170
148
|
1,
|
|
171
|
-
Math.floor(
|
|
172
|
-
(weight * widths[col]! / totalWeightedWidth) * remaining,
|
|
173
|
-
),
|
|
149
|
+
Math.floor(((weight * widths[col]!) / totalWeightedWidth) * remaining),
|
|
174
150
|
);
|
|
175
151
|
const minWidth = colOpts?.minWidth ?? 1;
|
|
176
152
|
const maxShrink = widths[col]! - minWidth;
|
|
@@ -296,10 +272,7 @@ export default class DefaultTableGeneratorService
|
|
|
296
272
|
#colorBorder(char: string, table: Table): string {
|
|
297
273
|
let result = char;
|
|
298
274
|
if (this.colorEnabled && table.options.borderBackgroundColor) {
|
|
299
|
-
result = this.backgroundColorFunction(
|
|
300
|
-
result,
|
|
301
|
-
table.options.borderBackgroundColor,
|
|
302
|
-
);
|
|
275
|
+
result = this.backgroundColorFunction(result, table.options.borderBackgroundColor);
|
|
303
276
|
}
|
|
304
277
|
if (this.colorEnabled && table.options.borderColor) {
|
|
305
278
|
result = this.colorFunction(result, table.options.borderColor);
|
|
@@ -320,10 +293,7 @@ export default class DefaultTableGeneratorService
|
|
|
320
293
|
let maxHeight = 1;
|
|
321
294
|
for (let col = 0; col < table.columnCount; col++) {
|
|
322
295
|
const cell = table.getCell(row, col);
|
|
323
|
-
const lines = this.#wrapCellContent(
|
|
324
|
-
cell?.contents ?? "",
|
|
325
|
-
columnWidths[col]!,
|
|
326
|
-
);
|
|
296
|
+
const lines = this.#wrapCellContent(cell?.contents ?? "", columnWidths[col]!);
|
|
327
297
|
rowCells.push(lines);
|
|
328
298
|
if (lines.length > maxHeight) maxHeight = lines.length;
|
|
329
299
|
}
|
|
@@ -334,15 +304,17 @@ export default class DefaultTableGeneratorService
|
|
|
334
304
|
const output: string[] = [];
|
|
335
305
|
|
|
336
306
|
if (border) {
|
|
337
|
-
output.push(
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
307
|
+
output.push(
|
|
308
|
+
this.#renderHorizontalBorder(
|
|
309
|
+
table,
|
|
310
|
+
columnWidths,
|
|
311
|
+
padding,
|
|
312
|
+
BORDER_TOP_LEFT,
|
|
313
|
+
BORDER_TOP,
|
|
314
|
+
BORDER_TOP_MIDDLE,
|
|
315
|
+
BORDER_TOP_RIGHT,
|
|
316
|
+
),
|
|
317
|
+
);
|
|
346
318
|
}
|
|
347
319
|
|
|
348
320
|
for (let row = 0; row < table.rowCount; row++) {
|
|
@@ -365,28 +337,32 @@ export default class DefaultTableGeneratorService
|
|
|
365
337
|
}
|
|
366
338
|
|
|
367
339
|
if (border && row < table.rowCount - 1) {
|
|
368
|
-
output.push(
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
340
|
+
output.push(
|
|
341
|
+
this.#renderHorizontalBorder(
|
|
342
|
+
table,
|
|
343
|
+
columnWidths,
|
|
344
|
+
padding,
|
|
345
|
+
BORDER_LEFT_MIDDLE,
|
|
346
|
+
BORDER_MIDDLE,
|
|
347
|
+
BORDER_MIDDLE_MIDDLE,
|
|
348
|
+
BORDER_RIGHT_MIDDLE,
|
|
349
|
+
),
|
|
350
|
+
);
|
|
377
351
|
}
|
|
378
352
|
}
|
|
379
353
|
|
|
380
354
|
if (border) {
|
|
381
|
-
output.push(
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
355
|
+
output.push(
|
|
356
|
+
this.#renderHorizontalBorder(
|
|
357
|
+
table,
|
|
358
|
+
columnWidths,
|
|
359
|
+
padding,
|
|
360
|
+
BORDER_BOTTOM_LEFT,
|
|
361
|
+
BORDER_BOTTOM,
|
|
362
|
+
BORDER_BOTTOM_MIDDLE,
|
|
363
|
+
BORDER_BOTTOM_RIGHT,
|
|
364
|
+
),
|
|
365
|
+
);
|
|
390
366
|
}
|
|
391
367
|
|
|
392
368
|
return output.join("\n");
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ServiceInfo,
|
|
3
|
-
ServiceProvider,
|
|
4
|
-
} from "../../api/service/ServiceProvider.ts";
|
|
1
|
+
import type { ServiceInfo, ServiceProvider } from "../../api/service/ServiceProvider.ts";
|
|
5
2
|
import DefaultTableGeneratorService from "./DefaultTableGeneratorService.ts";
|
|
6
3
|
import { TABLE_GENERATOR_SERVICE_ID } from "../../api/service/core/TableGeneratorService.ts";
|
|
7
4
|
import type Context from "../../api/Context.ts";
|
|
@@ -13,9 +10,7 @@ export default class TableGeneratorServiceProvider implements ServiceProvider {
|
|
|
13
10
|
readonly serviceId: string = TABLE_GENERATOR_SERVICE_ID;
|
|
14
11
|
readonly #defaultTableGeneratorService: DefaultTableGeneratorService;
|
|
15
12
|
|
|
16
|
-
public constructor(
|
|
17
|
-
readonly servicePriority: number,
|
|
18
|
-
) {
|
|
13
|
+
public constructor(readonly servicePriority: number) {
|
|
19
14
|
this.#defaultTableGeneratorService = new DefaultTableGeneratorService();
|
|
20
15
|
}
|
|
21
16
|
|
|
@@ -27,16 +22,12 @@ export default class TableGeneratorServiceProvider implements ServiceProvider {
|
|
|
27
22
|
}
|
|
28
23
|
|
|
29
24
|
initService(context: Context): Promise<void> {
|
|
30
|
-
const printerService = context.getServiceById(
|
|
31
|
-
PRINTER_SERVICE_ID,
|
|
32
|
-
) as PrinterService;
|
|
25
|
+
const printerService = context.getServiceById(PRINTER_SERVICE_ID) as PrinterService;
|
|
33
26
|
|
|
34
|
-
this.#defaultTableGeneratorService.colorEnabled =
|
|
35
|
-
|
|
36
|
-
this.#defaultTableGeneratorService.
|
|
37
|
-
.bind(printerService);
|
|
38
|
-
this.#defaultTableGeneratorService.backgroundColorFunction = printerService
|
|
39
|
-
.backgroundColor.bind(printerService);
|
|
27
|
+
this.#defaultTableGeneratorService.colorEnabled = printerService.colorEnabled;
|
|
28
|
+
this.#defaultTableGeneratorService.colorFunction = printerService.color.bind(printerService);
|
|
29
|
+
this.#defaultTableGeneratorService.backgroundColorFunction =
|
|
30
|
+
printerService.backgroundColor.bind(printerService);
|
|
40
31
|
|
|
41
32
|
return Promise.resolve(undefined);
|
|
42
33
|
}
|
|
@@ -5,8 +5,7 @@ const DEFAULT_NODE_COLOR = "#839496";
|
|
|
5
5
|
|
|
6
6
|
export default class DefaultTreePrinterService implements TreePrinterService {
|
|
7
7
|
colorEnabled = true;
|
|
8
|
-
colorFunction: (text: string, hexFormattedColor: string) => string = (text) =>
|
|
9
|
-
text;
|
|
8
|
+
colorFunction: (text: string, hexFormattedColor: string) => string = (text) => text;
|
|
10
9
|
|
|
11
10
|
readonly #nodeColor: string;
|
|
12
11
|
|
|
@@ -21,11 +20,7 @@ export default class DefaultTreePrinterService implements TreePrinterService {
|
|
|
21
20
|
return label;
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
#renderChildren(
|
|
25
|
-
children: Array<TreeNode | string>,
|
|
26
|
-
prefix: string,
|
|
27
|
-
lines: string[],
|
|
28
|
-
): void {
|
|
23
|
+
#renderChildren(children: Array<TreeNode | string>, prefix: string, lines: string[]): void {
|
|
29
24
|
for (let i = 0; i < children.length; i++) {
|
|
30
25
|
const child = children[i]!;
|
|
31
26
|
const isLast = i === children.length - 1;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ServiceInfo,
|
|
3
|
-
ServiceProvider,
|
|
4
|
-
} from "../../api/service/ServiceProvider.ts";
|
|
1
|
+
import type { ServiceInfo, ServiceProvider } from "../../api/service/ServiceProvider.ts";
|
|
5
2
|
import DefaultTreePrinterService from "./DefaultTreePrinterService.ts";
|
|
6
3
|
import { TREE_PRINTER_SERVICE_ID } from "../../api/service/core/TreePrinterService.ts";
|
|
7
4
|
import type Context from "../../api/Context.ts";
|
|
@@ -13,9 +10,7 @@ export default class TreePrinterServiceProvider implements ServiceProvider {
|
|
|
13
10
|
readonly serviceId: string = TREE_PRINTER_SERVICE_ID;
|
|
14
11
|
readonly #defaultTreePrinterService: DefaultTreePrinterService;
|
|
15
12
|
|
|
16
|
-
public constructor(
|
|
17
|
-
readonly servicePriority: number,
|
|
18
|
-
) {
|
|
13
|
+
public constructor(readonly servicePriority: number) {
|
|
19
14
|
this.#defaultTreePrinterService = new DefaultTreePrinterService();
|
|
20
15
|
}
|
|
21
16
|
|
|
@@ -27,13 +22,10 @@ export default class TreePrinterServiceProvider implements ServiceProvider {
|
|
|
27
22
|
}
|
|
28
23
|
|
|
29
24
|
initService(context: Context): Promise<void> {
|
|
30
|
-
const printerService = context.getServiceById(
|
|
31
|
-
PRINTER_SERVICE_ID,
|
|
32
|
-
) as PrinterService;
|
|
25
|
+
const printerService = context.getServiceById(PRINTER_SERVICE_ID) as PrinterService;
|
|
33
26
|
|
|
34
27
|
this.#defaultTreePrinterService.colorEnabled = printerService.colorEnabled;
|
|
35
|
-
this.#defaultTreePrinterService.colorFunction = printerService.color
|
|
36
|
-
.bind(printerService);
|
|
28
|
+
this.#defaultTreePrinterService.colorFunction = printerService.color.bind(printerService);
|
|
37
29
|
|
|
38
30
|
return Promise.resolve(undefined);
|
|
39
31
|
}
|
|
@@ -30,29 +30,24 @@ export default class ImageRenderer {
|
|
|
30
30
|
return this.#renderITerm2(imageBuffer, widthPercentage);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
return this.#renderAnsiBlocks(
|
|
34
|
-
imageBuffer,
|
|
35
|
-
widthPercentage,
|
|
36
|
-
hexFormattedBackgroundColor,
|
|
37
|
-
);
|
|
33
|
+
return this.#renderAnsiBlocks(imageBuffer, widthPercentage, hexFormattedBackgroundColor);
|
|
38
34
|
}
|
|
39
35
|
|
|
40
36
|
#isMultiplexer(): boolean {
|
|
41
37
|
const term = (process.env.TERM || "").toLowerCase();
|
|
42
38
|
const termProgram = (process.env.TERM_PROGRAM || "").toLowerCase();
|
|
43
|
-
return
|
|
44
|
-
|
|
39
|
+
return (
|
|
40
|
+
termProgram === "tmux" ||
|
|
41
|
+
termProgram === "screen" ||
|
|
42
|
+
term.startsWith("tmux") ||
|
|
43
|
+
term.startsWith("screen")
|
|
44
|
+
);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
// https://sw.kovidgoyal.net/kitty/graphics-protocol/
|
|
48
|
-
async #renderKitty(
|
|
49
|
-
imageBuffer: Uint8Array,
|
|
50
|
-
widthPercentage: number,
|
|
51
|
-
): Promise<string> {
|
|
48
|
+
async #renderKitty(imageBuffer: Uint8Array, widthPercentage: number): Promise<string> {
|
|
52
49
|
const pngBytes = await new Bun.Image(imageBuffer).png().bytes();
|
|
53
|
-
const columns = Math.floor(
|
|
54
|
-
this.#terminal.columns() * widthPercentage / 100,
|
|
55
|
-
);
|
|
50
|
+
const columns = Math.floor((this.#terminal.columns() * widthPercentage) / 100);
|
|
56
51
|
const base64 = Buffer.from(pngBytes).toString("base64");
|
|
57
52
|
const chunks: string[] = [];
|
|
58
53
|
for (let i = 0; i < base64.length; i += 4096) {
|
|
@@ -62,9 +57,7 @@ export default class ImageRenderer {
|
|
|
62
57
|
for (let i = 0; i < chunks.length; i++) {
|
|
63
58
|
const isLast = i === chunks.length - 1;
|
|
64
59
|
if (i === 0) {
|
|
65
|
-
result += `\x1b_Gf=100,a=T,c=${columns},m=${isLast ? 0 : 1};${
|
|
66
|
-
chunks[i]
|
|
67
|
-
}\x1b\\`;
|
|
60
|
+
result += `\x1b_Gf=100,a=T,c=${columns},m=${isLast ? 0 : 1};${chunks[i]}\x1b\\`;
|
|
68
61
|
} else {
|
|
69
62
|
result += `\x1b_Gm=${isLast ? 0 : 1};${chunks[i]}\x1b\\`;
|
|
70
63
|
}
|
|
@@ -73,18 +66,13 @@ export default class ImageRenderer {
|
|
|
73
66
|
}
|
|
74
67
|
|
|
75
68
|
// https://iterm2.com/documentation-images.html
|
|
76
|
-
async #renderITerm2(
|
|
77
|
-
imageBuffer: Uint8Array,
|
|
78
|
-
widthPercentage: number,
|
|
79
|
-
): Promise<string> {
|
|
69
|
+
async #renderITerm2(imageBuffer: Uint8Array, widthPercentage: number): Promise<string> {
|
|
80
70
|
const pngBytes = await new Bun.Image(imageBuffer).png().bytes();
|
|
81
71
|
const base64 = Buffer.from(pngBytes).toString("base64");
|
|
82
72
|
return `\x1b]1337;File=inline=1;width=${widthPercentage}%:${base64}\x07`;
|
|
83
73
|
}
|
|
84
74
|
|
|
85
|
-
static #parseHexColor(
|
|
86
|
-
hex: string,
|
|
87
|
-
): { r: number; g: number; b: number } | undefined {
|
|
75
|
+
static #parseHexColor(hex: string): { r: number; g: number; b: number } | undefined {
|
|
88
76
|
const match = hex.match(/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);
|
|
89
77
|
if (!match) return undefined;
|
|
90
78
|
return {
|
|
@@ -104,7 +92,7 @@ export default class ImageRenderer {
|
|
|
104
92
|
: undefined;
|
|
105
93
|
const columns = this.#terminal.columns();
|
|
106
94
|
const rows = this.#terminal.rows();
|
|
107
|
-
const targetWidth = Math.floor(columns * widthPercentage / 100);
|
|
95
|
+
const targetWidth = Math.floor((columns * widthPercentage) / 100);
|
|
108
96
|
|
|
109
97
|
const meta = await new Bun.Image(imageBuffer).metadata();
|
|
110
98
|
const aspectRatio = meta.height! / meta.width!;
|
|
@@ -139,51 +127,44 @@ export default class ImageRenderer {
|
|
|
139
127
|
|
|
140
128
|
if (a === 0 && a2 === 0) {
|
|
141
129
|
if (bg) {
|
|
142
|
-
line += backgroundColorStart(
|
|
143
|
-
bg.r,
|
|
144
|
-
bg.g,
|
|
145
|
-
bg.b,
|
|
146
|
-
) + " " + BACKGROUND_COLOR_END;
|
|
130
|
+
line += backgroundColorStart(bg.r, bg.g, bg.b) + " " + BACKGROUND_COLOR_END;
|
|
147
131
|
} else {
|
|
148
132
|
line += " ";
|
|
149
133
|
}
|
|
150
134
|
} else if (a === 0) {
|
|
151
135
|
if (bg) {
|
|
152
|
-
line +=
|
|
153
|
-
bg.r,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
136
|
+
line +=
|
|
137
|
+
backgroundColorStart(bg.r, bg.g, bg.b) +
|
|
138
|
+
foregroundColorStart(r2, g2, b2) +
|
|
139
|
+
"▄" +
|
|
140
|
+
FOREGROUND_COLOR_END +
|
|
141
|
+
BACKGROUND_COLOR_END;
|
|
158
142
|
} else {
|
|
159
|
-
line += foregroundColorStart(r2, g2, b2) + "▄" +
|
|
160
|
-
FOREGROUND_COLOR_END;
|
|
143
|
+
line += foregroundColorStart(r2, g2, b2) + "▄" + FOREGROUND_COLOR_END;
|
|
161
144
|
}
|
|
162
145
|
} else if (a2 === 0) {
|
|
163
146
|
if (bg) {
|
|
164
|
-
line +=
|
|
165
|
-
bg.r,
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
147
|
+
line +=
|
|
148
|
+
backgroundColorStart(bg.r, bg.g, bg.b) +
|
|
149
|
+
foregroundColorStart(r, g, b) +
|
|
150
|
+
"▀" +
|
|
151
|
+
FOREGROUND_COLOR_END +
|
|
152
|
+
BACKGROUND_COLOR_END;
|
|
170
153
|
} else {
|
|
171
|
-
line += foregroundColorStart(r, g, b) + "▀" +
|
|
172
|
-
FOREGROUND_COLOR_END;
|
|
154
|
+
line += foregroundColorStart(r, g, b) + "▀" + FOREGROUND_COLOR_END;
|
|
173
155
|
}
|
|
174
156
|
} else {
|
|
175
|
-
line +=
|
|
176
|
-
|
|
177
|
-
|
|
157
|
+
line +=
|
|
158
|
+
backgroundColorStart(r, g, b) +
|
|
159
|
+
foregroundColorStart(r2, g2, b2) +
|
|
160
|
+
"▄" +
|
|
161
|
+
FOREGROUND_COLOR_END +
|
|
162
|
+
BACKGROUND_COLOR_END;
|
|
178
163
|
}
|
|
179
164
|
} else {
|
|
180
165
|
if (a === 0) {
|
|
181
166
|
if (bg) {
|
|
182
|
-
line += backgroundColorStart(
|
|
183
|
-
bg.r,
|
|
184
|
-
bg.g,
|
|
185
|
-
bg.b,
|
|
186
|
-
) + " " + BACKGROUND_COLOR_END;
|
|
167
|
+
line += backgroundColorStart(bg.r, bg.g, bg.b) + " " + BACKGROUND_COLOR_END;
|
|
187
168
|
} else {
|
|
188
169
|
line += " ";
|
|
189
170
|
}
|
|
@@ -11,19 +11,17 @@ function paethPredictor(a: number, b: number, c: number): number {
|
|
|
11
11
|
return c;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export function decodePngToRGBA(
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
export function decodePngToRGBA(pngBytes: Uint8Array): {
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
pixels: Uint8Array;
|
|
18
|
+
} {
|
|
17
19
|
const sig = [137, 80, 78, 71, 13, 10, 26, 10];
|
|
18
20
|
for (let i = 0; i < 8; i++) {
|
|
19
21
|
if (pngBytes[i] !== sig[i]) throw new Error("Invalid PNG signature");
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
const view = new DataView(
|
|
23
|
-
pngBytes.buffer,
|
|
24
|
-
pngBytes.byteOffset,
|
|
25
|
-
pngBytes.byteLength,
|
|
26
|
-
);
|
|
24
|
+
const view = new DataView(pngBytes.buffer, pngBytes.byteOffset, pngBytes.byteLength);
|
|
27
25
|
let offset = 8;
|
|
28
26
|
|
|
29
27
|
let width = 0;
|
|
@@ -49,14 +47,10 @@ export function decodePngToRGBA(
|
|
|
49
47
|
colorType = pngBytes[dataStart + 9]!;
|
|
50
48
|
const interlace = pngBytes[dataStart + 12]!;
|
|
51
49
|
if (bitDepth !== 8) {
|
|
52
|
-
throw new Error(
|
|
53
|
-
`Unsupported bit depth: ${bitDepth} (only 8 supported)`,
|
|
54
|
-
);
|
|
50
|
+
throw new Error(`Unsupported bit depth: ${bitDepth} (only 8 supported)`);
|
|
55
51
|
}
|
|
56
52
|
if (colorType !== 2 && colorType !== 6) {
|
|
57
|
-
throw new Error(
|
|
58
|
-
`Unsupported color type: ${colorType} (only RGB=2 and RGBA=6 supported)`,
|
|
59
|
-
);
|
|
53
|
+
throw new Error(`Unsupported color type: ${colorType} (only RGB=2 and RGBA=6 supported)`);
|
|
60
54
|
}
|
|
61
55
|
if (interlace !== 0) {
|
|
62
56
|
throw new Error("Interlaced PNGs are not supported");
|
|
@@ -74,9 +68,7 @@ export function decodePngToRGBA(
|
|
|
74
68
|
if (idatChunks.length === 0) throw new Error("Missing IDAT chunks");
|
|
75
69
|
|
|
76
70
|
const bpp = colorType === 6 ? 4 : 3;
|
|
77
|
-
const compressed = new Uint8Array(
|
|
78
|
-
idatChunks.reduce((sum, c) => sum + c.length, 0),
|
|
79
|
-
);
|
|
71
|
+
const compressed = new Uint8Array(idatChunks.reduce((sum, c) => sum + c.length, 0));
|
|
80
72
|
let pos = 0;
|
|
81
73
|
for (const chunk of idatChunks) {
|
|
82
74
|
compressed.set(chunk, pos);
|
|
@@ -116,8 +108,7 @@ export function decodePngToRGBA(
|
|
|
116
108
|
currRow[x] = (currRow[x]! + ((left + up) >> 1)) & 0xff;
|
|
117
109
|
break;
|
|
118
110
|
case 4:
|
|
119
|
-
currRow[x] = (currRow[x]! + paethPredictor(left, up, upperLeft)) &
|
|
120
|
-
0xff;
|
|
111
|
+
currRow[x] = (currRow[x]! + paethPredictor(left, up, upperLeft)) & 0xff;
|
|
121
112
|
break;
|
|
122
113
|
default:
|
|
123
114
|
throw new Error(`Unknown filter type: ${filterType}`);
|
|
@@ -48,21 +48,23 @@ export default class TtyStyler implements Styler {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
if (this.colorLevel === 3) {
|
|
51
|
-
const r = (colorValue >> 16) &
|
|
52
|
-
const g = (colorValue >> 8) &
|
|
53
|
-
const b = colorValue &
|
|
51
|
+
const r = (colorValue >> 16) & 0xff;
|
|
52
|
+
const g = (colorValue >> 8) & 0xff;
|
|
53
|
+
const b = colorValue & 0xff;
|
|
54
54
|
return `\x1b[48;2;${r};${g};${b}m${text}${BACKGROUND_COLOR_END}`;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
if (this.colorLevel === 2) {
|
|
58
|
-
return
|
|
59
|
-
BACKGROUND_COLOR_END
|
|
58
|
+
return (
|
|
59
|
+
Bun.color(colorValue, "ansi-256")!.replace("[38;", "[48;") + text + BACKGROUND_COLOR_END
|
|
60
|
+
);
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
return
|
|
63
|
-
/\[(\d+)m/,
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
return (
|
|
64
|
+
Bun.color(colorValue, "ansi-16")!.replace(/\[(\d+)m/, (_, n) => `[${Number(n) + 10}m`) +
|
|
65
|
+
text +
|
|
66
|
+
BACKGROUND_COLOR_END
|
|
67
|
+
);
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
italicText(text: string): string {
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { WriteStream } from "node:tty";
|
|
2
2
|
import type Terminal from "./Terminal.ts";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
CLEAR_LINE,
|
|
6
|
-
CURSOR_LEFT,
|
|
7
|
-
CURSOR_UP,
|
|
8
|
-
HIDE_CURSOR,
|
|
9
|
-
SHOW_CURSOR,
|
|
10
|
-
} from "./Ansi.ts";
|
|
4
|
+
import { CLEAR_LINE, CURSOR_LEFT, CURSOR_UP, HIDE_CURSOR, SHOW_CURSOR } from "./Ansi.ts";
|
|
11
5
|
|
|
12
6
|
export default class TtyTerminal implements Terminal {
|
|
13
7
|
readonly #ttyWriteStream: WriteStream;
|
|
@@ -34,9 +28,7 @@ export default class TtyTerminal implements Terminal {
|
|
|
34
28
|
}
|
|
35
29
|
|
|
36
30
|
clearUpLines(count: number): Promise<void> {
|
|
37
|
-
this.#writeAll(
|
|
38
|
-
(CURSOR_UP + CLEAR_LINE).repeat(count) + CLEAR_LINE + CURSOR_LEFT,
|
|
39
|
-
);
|
|
31
|
+
this.#writeAll((CURSOR_UP + CLEAR_LINE).repeat(count) + CLEAR_LINE + CURSOR_LEFT);
|
|
40
32
|
return Promise.resolve();
|
|
41
33
|
}
|
|
42
34
|
|
|
@@ -15,9 +15,7 @@ function parseVersion(versionString = ""): {
|
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const versions = (versionString ?? "").split(".").map((n) =>
|
|
19
|
-
Number.parseInt(n, 10)
|
|
20
|
-
);
|
|
18
|
+
const versions = (versionString ?? "").split(".").map((n) => Number.parseInt(n, 10));
|
|
21
19
|
return {
|
|
22
20
|
major: versions[0] ?? 0,
|
|
23
21
|
minor: versions[1] ?? 0,
|
|
@@ -25,9 +23,7 @@ function parseVersion(versionString = ""): {
|
|
|
25
23
|
};
|
|
26
24
|
}
|
|
27
25
|
|
|
28
|
-
export default function supportsHyperlinks(
|
|
29
|
-
stream: WriteStream | undefined,
|
|
30
|
-
): boolean {
|
|
26
|
+
export default function supportsHyperlinks(stream: WriteStream | undefined): boolean {
|
|
31
27
|
const {
|
|
32
28
|
CI,
|
|
33
29
|
CURSOR_TRACE_ID,
|
|
@@ -40,8 +36,7 @@ export default function supportsHyperlinks(
|
|
|
40
36
|
} = process.env;
|
|
41
37
|
|
|
42
38
|
if (FORCE_HYPERLINK) {
|
|
43
|
-
return !(FORCE_HYPERLINK.length > 0 &&
|
|
44
|
-
Number.parseInt(FORCE_HYPERLINK, 10) === 0);
|
|
39
|
+
return !(FORCE_HYPERLINK.length > 0 && Number.parseInt(FORCE_HYPERLINK, 10) === 0);
|
|
45
40
|
}
|
|
46
41
|
|
|
47
42
|
if (stream && !stream.isTTY) {
|
|
@@ -81,8 +76,7 @@ export default function supportsHyperlinks(
|
|
|
81
76
|
if (CURSOR_TRACE_ID) {
|
|
82
77
|
return true;
|
|
83
78
|
}
|
|
84
|
-
return version.major > 1 ||
|
|
85
|
-
(version.major === 1 && version.minor >= 72);
|
|
79
|
+
return version.major > 1 || (version.major === 1 && version.minor >= 72);
|
|
86
80
|
}
|
|
87
81
|
case "ghostty":
|
|
88
82
|
return true;
|
package/src/util/configHelper.ts
CHANGED
|
@@ -32,10 +32,7 @@ export function getSubCommandArgumentConfigurationKey(
|
|
|
32
32
|
command: Command,
|
|
33
33
|
argumentAncestry: Array<SubCommandArgument>,
|
|
34
34
|
): string | undefined {
|
|
35
|
-
if (
|
|
36
|
-
(command.enableConfiguration === undefined) ||
|
|
37
|
-
(command.enableConfiguration !== true)
|
|
38
|
-
) {
|
|
35
|
+
if (command.enableConfiguration === undefined || command.enableConfiguration !== true) {
|
|
39
36
|
return undefined;
|
|
40
37
|
}
|
|
41
38
|
if (argumentAncestry.length === 0) {
|
|
@@ -50,8 +47,7 @@ export function getSubCommandArgumentConfigurationKey(
|
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
argumentAncestry.forEach((argument) => {
|
|
53
|
-
const isArray = (argument as Option).isArray ||
|
|
54
|
-
(argument as Positional).isVarargMultiple;
|
|
50
|
+
const isArray = (argument as Option).isArray || (argument as Positional).isVarargMultiple;
|
|
55
51
|
keySegments.push(
|
|
56
52
|
getKeySegment(
|
|
57
53
|
argument.configurationKey || argument.name,
|
|
@@ -76,10 +72,7 @@ export function getGlobalCommandArgumentConfigurationKey(
|
|
|
76
72
|
command: Command,
|
|
77
73
|
globalCommandArgument: GlobalCommandArgument,
|
|
78
74
|
): string | undefined {
|
|
79
|
-
if (
|
|
80
|
-
(command.enableConfiguration === undefined) ||
|
|
81
|
-
(command.enableConfiguration !== true)
|
|
82
|
-
) {
|
|
75
|
+
if (command.enableConfiguration === undefined || command.enableConfiguration !== true) {
|
|
83
76
|
return undefined;
|
|
84
77
|
}
|
|
85
78
|
|