@flowscripter/dynamic-cli-framework 1.2.2 → 1.3.1

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.
Files changed (166) hide show
  1. package/README/core-service-providers.md +2 -2
  2. package/README/development.md +3 -6
  3. package/README/implementation-details.md +17 -17
  4. package/README/key-concepts.md +17 -17
  5. package/README.md +4 -4
  6. package/bun.lock +0 -2
  7. package/index.ts +22 -30
  8. package/package.json +19 -19
  9. package/src/api/argument/Argument.ts +1 -1
  10. package/src/api/argument/ArgumentValueTypes.ts +3 -10
  11. package/src/api/argument/ComplexOption.ts +5 -9
  12. package/src/api/command/GlobalCommand.ts +1 -4
  13. package/src/api/service/core/ArgumentPrompterService.ts +1 -3
  14. package/src/api/service/core/AsciiBannerGeneratorService.ts +1 -4
  15. package/src/api/service/core/CompletionService.ts +2 -6
  16. package/src/api/service/core/ImagePrinterService.ts +1 -2
  17. package/src/api/service/core/KeyValueService.ts +1 -2
  18. package/src/api/service/core/PrettyPrinterService.ts +1 -4
  19. package/src/api/service/core/PrinterService.ts +8 -9
  20. package/src/api/service/core/PrompterService.ts +4 -11
  21. package/src/api/service/core/ShutdownService.ts +1 -2
  22. package/src/api/service/core/SyntaxHighlighterService.ts +1 -5
  23. package/src/api/service/core/Table.ts +7 -25
  24. package/src/api/service/core/TreePrinterService.ts +1 -2
  25. package/src/cli/BaseCLI.ts +17 -47
  26. package/src/cli/DefaultRuntimeCLI.ts +1 -4
  27. package/src/command/CompletionCommand.ts +19 -45
  28. package/src/command/MultiCommandCliHelpCommand.ts +45 -92
  29. package/src/command/SingleCommandCliHelpCommand.ts +17 -28
  30. package/src/command/UsageCommand.ts +6 -12
  31. package/src/command/VersionCommand.ts +2 -6
  32. package/src/launcher.ts +4 -2
  33. package/src/runtime/DefaultContext.ts +2 -5
  34. package/src/runtime/argument/ArgumentTypeGuards.ts +1 -3
  35. package/src/runtime/command/CommandTypeGuards.ts +5 -14
  36. package/src/runtime/command/CommandValidator.ts +56 -118
  37. package/src/runtime/parser.ts +13 -17
  38. package/src/runtime/registry/CommandRegistry.ts +2 -7
  39. package/src/runtime/registry/DefaultCommandRegistry.ts +32 -84
  40. package/src/runtime/registry/DefaultServiceProviderRegistry.ts +3 -9
  41. package/src/runtime/runner.ts +103 -142
  42. package/src/runtime/scanner.ts +28 -46
  43. package/src/runtime/values/ValuePopulationResult.ts +1 -2
  44. package/src/runtime/values/argumentValueMerge.ts +16 -28
  45. package/src/runtime/values/argumentValueValidation.ts +21 -67
  46. package/src/runtime/values/globalCommandValuePopulation.ts +9 -18
  47. package/src/runtime/values/subCommandValuePopulation.ts +42 -65
  48. package/src/service/argumentPrompter/ArgumentPrompterServiceProvider.ts +3 -10
  49. package/src/service/argumentPrompter/DefaultArgumentPrompterService.ts +22 -59
  50. package/src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.ts +5 -14
  51. package/src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.ts +59 -77
  52. package/src/service/banner/BannerServiceProvider.ts +13 -35
  53. package/src/service/banner/command/NoBannerCommand.ts +2 -8
  54. package/src/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.ts +5 -10
  55. package/src/service/completion/CompletionServiceProvider.ts +20 -48
  56. package/src/service/completion/DefaultCompletionService.ts +17 -56
  57. package/src/service/completion/shell/ShellHandler.ts +1 -3
  58. package/src/service/completion/shell/fish.ts +1 -1
  59. package/src/service/completion/shell/powershell.ts +2 -12
  60. package/src/service/completion/shell/zsh.ts +1 -1
  61. package/src/service/configuration/ConfigurationServiceProvider.ts +40 -133
  62. package/src/service/configuration/DefaultKeyValueService.ts +6 -20
  63. package/src/service/configuration/DefaultSecretService.ts +10 -14
  64. package/src/service/configuration/command/ConfigCommand.ts +1 -4
  65. package/src/service/configuration/command/DumpConfigCommand.ts +9 -21
  66. package/src/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.ts +5 -14
  67. package/src/service/dataDumpGenerator/DefaultDataDumpGeneratorService.ts +5 -12
  68. package/src/service/imagePrinter/DefaultImagePrinterService.ts +1 -5
  69. package/src/service/imagePrinter/ImagePrinterServiceProvider.ts +1 -4
  70. package/src/service/prettyPrinter/DefaultPrettyPrinterService.ts +4 -12
  71. package/src/service/prettyPrinter/PrettyPrinterServiceProvider.ts +3 -10
  72. package/src/service/printer/DefaultPrinterService.ts +20 -83
  73. package/src/service/printer/PrinterServiceProvider.ts +3 -11
  74. package/src/service/printer/command/DarkModeCommand.ts +3 -10
  75. package/src/service/printer/command/LogLevelCommand.ts +7 -26
  76. package/src/service/printer/command/NoColorCommand.ts +3 -10
  77. package/src/service/printer/command/NoHyperlinksCommand.ts +3 -10
  78. package/src/service/printer/terminal/Progress.ts +99 -90
  79. package/src/service/printer/terminal/Spinner.ts +7 -26
  80. package/src/service/prompter/DefaultPrompterService.ts +2 -6
  81. package/src/service/prompter/PrompterServiceProvider.ts +3 -11
  82. package/src/service/prompter/command/NoPromptCommand.ts +3 -10
  83. package/src/service/prompter/prompt/PromptContext.ts +5 -18
  84. package/src/service/prompter/prompt/promptMultiSelect.ts +6 -21
  85. package/src/service/prompter/prompt/promptOpenUrl.ts +7 -22
  86. package/src/service/prompter/prompt/promptSingleSelect.ts +6 -23
  87. package/src/service/prompter/prompt/promptText.ts +10 -27
  88. package/src/service/prompter/prompt/promptToggle.ts +8 -8
  89. package/src/service/shutdown/ShutdownServiceProvider.ts +3 -10
  90. package/src/service/syntaxHighlighter/DefaultSyntaxHighlighterService.ts +13 -26
  91. package/src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.ts +8 -21
  92. package/src/service/tableGenerator/DefaultTableGeneratorService.ts +44 -68
  93. package/src/service/tableGenerator/TableGeneratorServiceProvider.ts +7 -16
  94. package/src/service/treePrinter/DefaultTreePrinterService.ts +2 -7
  95. package/src/service/treePrinter/TreePrinterServiceProvider.ts +4 -12
  96. package/src/terminal/ImageRenderer.ts +35 -54
  97. package/src/terminal/PngDecoder.ts +10 -19
  98. package/src/terminal/TtyStyler.ts +11 -9
  99. package/src/terminal/TtyTerminal.ts +2 -10
  100. package/src/terminal/supportsHyperlinks.ts +4 -10
  101. package/src/util/configHelper.ts +3 -10
  102. package/src/util/envVarHelper.ts +50 -88
  103. package/src/util/helpHelper.ts +123 -193
  104. package/src/util/logger.ts +12 -42
  105. package/src/util/runnerHelper.ts +20 -61
  106. package/tests/cli/BaseCLI.test.ts +23 -80
  107. package/tests/command/CompletionCommand.test.ts +1 -6
  108. package/tests/command/MultiCommandCliHelpCommand.test.ts +51 -205
  109. package/tests/command/SingleCommandCliHelpCommand.test.ts +21 -103
  110. package/tests/command/UsageCommand.test.ts +4 -10
  111. package/tests/fixtures/Command.ts +87 -68
  112. package/tests/fixtures/CommandRegistry.ts +1 -3
  113. package/tests/fixtures/Context.ts +3 -11
  114. package/tests/fixtures/ServiceProviderRegistry.ts +1 -1
  115. package/tests/fixtures/prettierPluginFoo.ts +1 -1
  116. package/tests/fixtures/util.ts +2 -8
  117. package/tests/runtime/argument/ArgumentTypeGuards.test.ts +1 -3
  118. package/tests/runtime/command/CommandValidator.test.ts +881 -604
  119. package/tests/runtime/parser.test.ts +222 -246
  120. package/tests/runtime/registry/DefaultCommandRegistry.test.ts +15 -37
  121. package/tests/runtime/registry/DefaultServiceProviderRegistry.test.ts +2 -8
  122. package/tests/runtime/runner.test.ts +231 -281
  123. package/tests/runtime/scanner.test.ts +277 -475
  124. package/tests/runtime/values/argumentValueMerge.test.ts +133 -81
  125. package/tests/runtime/values/argumentValueValidation.test.ts +444 -588
  126. package/tests/runtime/values/globalCommandValuePopulation.test.ts +71 -253
  127. package/tests/runtime/values/subCommandValuePopulation.test.ts +1342 -1570
  128. package/tests/service/argumentPrompter/ArgumentPrompterServiceProvider.test.ts +3 -12
  129. package/tests/service/argumentPrompter/DefaultArgumentPrompterService.test.ts +36 -45
  130. package/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.ts +2 -8
  131. package/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.ts +40 -62
  132. package/tests/service/banner/BannerServiceProvider.test.ts +5 -18
  133. package/tests/service/banner/command/NoBannerCommand.test.ts +1 -4
  134. package/tests/service/completion/CompletionServiceProvider.test.ts +145 -214
  135. package/tests/service/completion/DefaultCompletionService.test.ts +17 -79
  136. package/tests/service/completion/shell/fish.test.ts +1 -3
  137. package/tests/service/configuration/ConfigurationServiceProvider.test.ts +26 -75
  138. package/tests/service/configuration/DefaultKeyValueService.test.ts +9 -21
  139. package/tests/service/configuration/DefaultSecretService.test.ts +7 -15
  140. package/tests/service/configuration/command/DumpConfigCommand.test.ts +4 -13
  141. package/tests/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.test.ts +6 -12
  142. package/tests/service/dataDumpGenerator/DefaultDataDumpGeneratorService.test.ts +1 -10
  143. package/tests/service/imagePrinter/DefaultImagePrinterService.test.ts +5 -70
  144. package/tests/service/prettyPrinter/DefaultPrettyPrinterService.test.ts +4 -11
  145. package/tests/service/prettyPrinter/PrettyPrinterServiceProvider.test.ts +2 -6
  146. package/tests/service/printer/DefaultPrinterService.test.ts +57 -255
  147. package/tests/service/printer/PrinterServiceProvider.test.ts +2 -8
  148. package/tests/service/printer/command/DarkModeCommand.test.ts +4 -12
  149. package/tests/service/printer/command/LogLevelCommand.test.ts +4 -17
  150. package/tests/service/printer/command/NoColorCommand.test.ts +4 -12
  151. package/tests/service/printer/command/NoHyperlinksCommand.test.ts +7 -21
  152. package/tests/service/printer/terminal/Progress.test.ts +1 -3
  153. package/tests/service/printer/terminal/Spinner.test.ts +2 -8
  154. package/tests/service/prompter/DefaultPrompterService.test.ts +52 -69
  155. package/tests/service/prompter/PrompterServiceProvider.test.ts +2 -8
  156. package/tests/service/shutdown/ShutdownServiceProvider.test.ts +1 -3
  157. package/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.ts +13 -99
  158. package/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.ts +2 -7
  159. package/tests/service/tableGenerator/DefaultTableGeneratorService.test.ts +12 -33
  160. package/tests/service/tableGenerator/TableGeneratorServiceProvider.test.ts +2 -2
  161. package/tests/service/treePrinter/DefaultTreePrinterService.test.ts +4 -6
  162. package/tests/service/treePrinter/TreePrinterServiceProvider.test.ts +4 -8
  163. package/tests/terminal/ImageRenderer.test.ts +2 -11
  164. package/tests/terminal/PngDecoder.test.ts +2 -6
  165. package/tests/util/configHelper.test.ts +55 -137
  166. 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
- text,
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(this.#renderHorizontalBorder(
338
- table,
339
- columnWidths,
340
- padding,
341
- BORDER_TOP_LEFT,
342
- BORDER_TOP,
343
- BORDER_TOP_MIDDLE,
344
- BORDER_TOP_RIGHT,
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(this.#renderHorizontalBorder(
369
- table,
370
- columnWidths,
371
- padding,
372
- BORDER_LEFT_MIDDLE,
373
- BORDER_MIDDLE,
374
- BORDER_MIDDLE_MIDDLE,
375
- BORDER_RIGHT_MIDDLE,
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(this.#renderHorizontalBorder(
382
- table,
383
- columnWidths,
384
- padding,
385
- BORDER_BOTTOM_LEFT,
386
- BORDER_BOTTOM,
387
- BORDER_BOTTOM_MIDDLE,
388
- BORDER_BOTTOM_RIGHT,
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
- printerService.colorEnabled;
36
- this.#defaultTableGeneratorService.colorFunction = printerService.color
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 termProgram === "tmux" || termProgram === "screen" ||
44
- term.startsWith("tmux") || term.startsWith("screen");
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 += backgroundColorStart(
153
- bg.r,
154
- bg.g,
155
- bg.b,
156
- ) + foregroundColorStart(r2, g2, b2) + "▄" +
157
- FOREGROUND_COLOR_END + BACKGROUND_COLOR_END;
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 += backgroundColorStart(
165
- bg.r,
166
- bg.g,
167
- bg.b,
168
- ) + foregroundColorStart(r, g, b) + "▀" +
169
- FOREGROUND_COLOR_END + BACKGROUND_COLOR_END;
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 += backgroundColorStart(r, g, b) +
176
- foregroundColorStart(r2, g2, b2) + "▄" +
177
- FOREGROUND_COLOR_END + BACKGROUND_COLOR_END;
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
- pngBytes: Uint8Array,
16
- ): { width: number; height: number; pixels: Uint8Array } {
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) & 0xFF;
52
- const g = (colorValue >> 8) & 0xFF;
53
- const b = colorValue & 0xFF;
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 Bun.color(colorValue, "ansi-256")!.replace("[38;", "[48;") + text +
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 Bun.color(colorValue, "ansi-16")!.replace(
63
- /\[(\d+)m/,
64
- (_, n) => `[${Number(n) + 10}m`,
65
- ) + text + BACKGROUND_COLOR_END;
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;
@@ -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