@flowscripter/dynamic-cli-framework 1.2.1 → 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
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { ArgumentSingleValueType } from "../../argument/ArgumentValueTypes.ts";
|
|
2
2
|
|
|
3
|
-
export const PROMPTER_SERVICE_ID =
|
|
4
|
-
"@flowscripter/dynamic-cli-framework/prompter-service";
|
|
3
|
+
export const PROMPTER_SERVICE_ID = "@flowscripter/dynamic-cli-framework/prompter-service";
|
|
5
4
|
|
|
6
5
|
export enum PromptType {
|
|
7
6
|
SINGLE_SELECT = 0,
|
|
@@ -17,9 +16,7 @@ export interface PromptOption {
|
|
|
17
16
|
readonly returnedValue: ArgumentSingleValueType;
|
|
18
17
|
readonly min?: number;
|
|
19
18
|
readonly max?: number;
|
|
20
|
-
readonly validate?: (
|
|
21
|
-
value: ArgumentSingleValueType,
|
|
22
|
-
) => string | undefined;
|
|
19
|
+
readonly validate?: (value: ArgumentSingleValueType) => string | undefined;
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
export interface Prompt {
|
|
@@ -33,9 +30,7 @@ export interface Prompt {
|
|
|
33
30
|
|
|
34
31
|
export interface PromptResult {
|
|
35
32
|
readonly name: string;
|
|
36
|
-
readonly value:
|
|
37
|
-
| ArgumentSingleValueType
|
|
38
|
-
| ReadonlyArray<ArgumentSingleValueType>;
|
|
33
|
+
readonly value: ArgumentSingleValueType | ReadonlyArray<ArgumentSingleValueType>;
|
|
39
34
|
}
|
|
40
35
|
|
|
41
36
|
export default interface PrompterService {
|
|
@@ -43,7 +38,5 @@ export default interface PrompterService {
|
|
|
43
38
|
|
|
44
39
|
prompt(prompt: Prompt): Promise<PromptResult>;
|
|
45
40
|
|
|
46
|
-
promptAll(
|
|
47
|
-
prompts: ReadonlyArray<Prompt>,
|
|
48
|
-
): Promise<ReadonlyArray<PromptResult>>;
|
|
41
|
+
promptAll(prompts: ReadonlyArray<Prompt>): Promise<ReadonlyArray<PromptResult>>;
|
|
49
42
|
}
|
|
@@ -50,9 +50,5 @@ export default interface SyntaxHighlighterService {
|
|
|
50
50
|
* @param syntaxName the syntax to use.
|
|
51
51
|
* @param colorScheme the color scheme to use.
|
|
52
52
|
*/
|
|
53
|
-
highlight(
|
|
54
|
-
text: string,
|
|
55
|
-
syntaxName: string,
|
|
56
|
-
colorScheme?: ColorScheme,
|
|
57
|
-
): string;
|
|
53
|
+
highlight(text: string, syntaxName: string, colorScheme?: ColorScheme): string;
|
|
58
54
|
}
|
|
@@ -12,14 +12,9 @@ export default class Table {
|
|
|
12
12
|
|
|
13
13
|
readonly #columnOptions: Map<number, ColumnOptions> = new Map();
|
|
14
14
|
readonly #rowOptions: Map<number, RowOptions> = new Map();
|
|
15
|
-
readonly #cells: Map<string, { contents: string; options?: CellOptions }> =
|
|
16
|
-
new Map();
|
|
15
|
+
readonly #cells: Map<string, { contents: string; options?: CellOptions }> = new Map();
|
|
17
16
|
|
|
18
|
-
constructor(
|
|
19
|
-
rowCount: number,
|
|
20
|
-
columnCount: number,
|
|
21
|
-
options?: TableOptions,
|
|
22
|
-
) {
|
|
17
|
+
constructor(rowCount: number, columnCount: number, options?: TableOptions) {
|
|
23
18
|
this.rowCount = rowCount;
|
|
24
19
|
this.columnCount = columnCount;
|
|
25
20
|
this.options = options ?? {};
|
|
@@ -27,9 +22,7 @@ export default class Table {
|
|
|
27
22
|
|
|
28
23
|
row(rowIndex: number, rowOptions: RowOptions): Table {
|
|
29
24
|
if (rowIndex < 0 || rowIndex >= this.rowCount) {
|
|
30
|
-
throw new Error(
|
|
31
|
-
`Row index ${rowIndex} out of bounds [0, ${this.rowCount})`,
|
|
32
|
-
);
|
|
25
|
+
throw new Error(`Row index ${rowIndex} out of bounds [0, ${this.rowCount})`);
|
|
33
26
|
}
|
|
34
27
|
this.#rowOptions.set(rowIndex, rowOptions);
|
|
35
28
|
return this;
|
|
@@ -37,29 +30,18 @@ export default class Table {
|
|
|
37
30
|
|
|
38
31
|
column(columnIndex: number, columnOptions: ColumnOptions): Table {
|
|
39
32
|
if (columnIndex < 0 || columnIndex >= this.columnCount) {
|
|
40
|
-
throw new Error(
|
|
41
|
-
`Column index ${columnIndex} out of bounds [0, ${this.columnCount})`,
|
|
42
|
-
);
|
|
33
|
+
throw new Error(`Column index ${columnIndex} out of bounds [0, ${this.columnCount})`);
|
|
43
34
|
}
|
|
44
35
|
this.#columnOptions.set(columnIndex, columnOptions);
|
|
45
36
|
return this;
|
|
46
37
|
}
|
|
47
38
|
|
|
48
|
-
cell(
|
|
49
|
-
rowIndex: number,
|
|
50
|
-
columnIndex: number,
|
|
51
|
-
contents: string,
|
|
52
|
-
cellOptions?: CellOptions,
|
|
53
|
-
): Table {
|
|
39
|
+
cell(rowIndex: number, columnIndex: number, contents: string, cellOptions?: CellOptions): Table {
|
|
54
40
|
if (rowIndex < 0 || rowIndex >= this.rowCount) {
|
|
55
|
-
throw new Error(
|
|
56
|
-
`Row index ${rowIndex} out of bounds [0, ${this.rowCount})`,
|
|
57
|
-
);
|
|
41
|
+
throw new Error(`Row index ${rowIndex} out of bounds [0, ${this.rowCount})`);
|
|
58
42
|
}
|
|
59
43
|
if (columnIndex < 0 || columnIndex >= this.columnCount) {
|
|
60
|
-
throw new Error(
|
|
61
|
-
`Column index ${columnIndex} out of bounds [0, ${this.columnCount})`,
|
|
62
|
-
);
|
|
44
|
+
throw new Error(`Column index ${columnIndex} out of bounds [0, ${this.columnCount})`);
|
|
63
45
|
}
|
|
64
46
|
this.#cells.set(`${rowIndex},${columnIndex}`, {
|
|
65
47
|
contents,
|
package/src/cli/BaseCLI.ts
CHANGED
|
@@ -113,13 +113,10 @@ export default class BaseCLI implements CLI {
|
|
|
113
113
|
`Invalid CLI name starting with a digit or dash provided: '${cliConfig.name}'`,
|
|
114
114
|
);
|
|
115
115
|
}
|
|
116
|
-
if (
|
|
117
|
-
(cliConfig.description !== undefined) &&
|
|
118
|
-
(cliConfig.description.length === 0)
|
|
119
|
-
) {
|
|
116
|
+
if (cliConfig.description !== undefined && cliConfig.description.length === 0) {
|
|
120
117
|
throw new Error("Invalid empty CLI description provided");
|
|
121
118
|
}
|
|
122
|
-
if (
|
|
119
|
+
if (cliConfig.version !== undefined && cliConfig.version.length === 0) {
|
|
123
120
|
throw new Error("Invalid empty CLI version provided");
|
|
124
121
|
}
|
|
125
122
|
this.#cliConfig = cliConfig;
|
|
@@ -197,13 +194,11 @@ export default class BaseCLI implements CLI {
|
|
|
197
194
|
|
|
198
195
|
async run(args: ReadonlyArray<string>): Promise<RunResult> {
|
|
199
196
|
if (this.#addedNonModifierCommands.length === 0) {
|
|
200
|
-
throw new Error(
|
|
201
|
-
"No non-modifier commands added to the CLI, nothing to run!",
|
|
202
|
-
);
|
|
197
|
+
throw new Error("No non-modifier commands added to the CLI, nothing to run!");
|
|
203
198
|
}
|
|
204
199
|
|
|
205
200
|
if (
|
|
206
|
-
|
|
201
|
+
this.#addedNonModifierCommands.length === 1 &&
|
|
207
202
|
!isSubCommand(this.#addedNonModifierCommands[0]!) &&
|
|
208
203
|
!isGlobalCommand(this.#addedNonModifierCommands[0]!) &&
|
|
209
204
|
!isGroupCommand(this.#addedNonModifierCommands[0]!)
|
|
@@ -215,12 +210,7 @@ export default class BaseCLI implements CLI {
|
|
|
215
210
|
|
|
216
211
|
// create and add core services
|
|
217
212
|
this.addServiceProvider(new ShutdownServiceProvider(100));
|
|
218
|
-
this.addServiceProvider(
|
|
219
|
-
new PrinterServiceProvider(
|
|
220
|
-
80,
|
|
221
|
-
this.#printerService,
|
|
222
|
-
),
|
|
223
|
-
);
|
|
213
|
+
this.addServiceProvider(new PrinterServiceProvider(80, this.#printerService));
|
|
224
214
|
this.addServiceProvider(new TableGeneratorServiceProvider(70));
|
|
225
215
|
|
|
226
216
|
const prompterService = new DefaultPrompterService(
|
|
@@ -232,26 +222,18 @@ export default class BaseCLI implements CLI {
|
|
|
232
222
|
this.addServiceProvider(new PrompterServiceProvider(75, prompterService));
|
|
233
223
|
|
|
234
224
|
if (this.#options.argumentPrompterServiceEnabled) {
|
|
235
|
-
const argumentPrompterService = new DefaultArgumentPrompterService(
|
|
236
|
-
|
|
237
|
-
);
|
|
238
|
-
this.addServiceProvider(
|
|
239
|
-
new ArgumentPrompterServiceProvider(65, argumentPrompterService),
|
|
240
|
-
);
|
|
225
|
+
const argumentPrompterService = new DefaultArgumentPrompterService(prompterService);
|
|
226
|
+
this.addServiceProvider(new ArgumentPrompterServiceProvider(65, argumentPrompterService));
|
|
241
227
|
}
|
|
242
228
|
|
|
243
229
|
if (this.#options.imagePrinterServiceEnabled) {
|
|
244
|
-
this.addServiceProvider(
|
|
245
|
-
new ImagePrinterServiceProvider(55, this.#stdoutTerminal),
|
|
246
|
-
);
|
|
230
|
+
this.addServiceProvider(new ImagePrinterServiceProvider(55, this.#stdoutTerminal));
|
|
247
231
|
}
|
|
248
232
|
|
|
249
233
|
let completionService: DefaultCompletionService | undefined;
|
|
250
234
|
if (this.#options.completionServiceEnabled) {
|
|
251
235
|
completionService = new DefaultCompletionService();
|
|
252
|
-
this.addServiceProvider(
|
|
253
|
-
new CompletionServiceProvider(60, completionService),
|
|
254
|
-
);
|
|
236
|
+
this.addServiceProvider(new CompletionServiceProvider(60, completionService));
|
|
255
237
|
}
|
|
256
238
|
|
|
257
239
|
const configurationServiceProvider = new ConfigurationServiceProvider(
|
|
@@ -263,17 +245,11 @@ export default class BaseCLI implements CLI {
|
|
|
263
245
|
);
|
|
264
246
|
this.addServiceProvider(configurationServiceProvider);
|
|
265
247
|
|
|
266
|
-
for (
|
|
267
|
-
const serviceProvider of this.#serviceProviderRegistry
|
|
268
|
-
.getServiceProviders()
|
|
269
|
-
) {
|
|
248
|
+
for (const serviceProvider of this.#serviceProviderRegistry.getServiceProviders()) {
|
|
270
249
|
const serviceInfo = await serviceProvider.getServiceInfo(this.#cliConfig);
|
|
271
250
|
|
|
272
251
|
if (serviceInfo.service) {
|
|
273
|
-
this.#context.addServiceInstance(
|
|
274
|
-
serviceProvider.serviceId,
|
|
275
|
-
serviceInfo.service,
|
|
276
|
-
);
|
|
252
|
+
this.#context.addServiceInstance(serviceProvider.serviceId, serviceInfo.service);
|
|
277
253
|
}
|
|
278
254
|
|
|
279
255
|
serviceInfo.commands.forEach((command) => {
|
|
@@ -349,16 +325,13 @@ export default class BaseCLI implements CLI {
|
|
|
349
325
|
await new UsageCommand(helpGlobalCommand).execute(this.#context);
|
|
350
326
|
} else if (runResult.runState === RunState.PARSE_ERROR) {
|
|
351
327
|
if (
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
isGlobalCommand(runResult.command)
|
|
355
|
-
)
|
|
328
|
+
runResult.command !== undefined &&
|
|
329
|
+
(isSubCommand(runResult.command) || isGlobalCommand(runResult.command))
|
|
356
330
|
) {
|
|
357
331
|
// print help on specific command
|
|
358
|
-
await helpSubCommand.execute(
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
);
|
|
332
|
+
await helpSubCommand.execute(this.#context, {
|
|
333
|
+
command: runResult.command!.name,
|
|
334
|
+
});
|
|
362
335
|
} else {
|
|
363
336
|
// print usage
|
|
364
337
|
await new UsageCommand(helpGlobalCommand).execute(this.#context);
|
|
@@ -366,10 +339,7 @@ export default class BaseCLI implements CLI {
|
|
|
366
339
|
}
|
|
367
340
|
return runResult;
|
|
368
341
|
} catch (error) {
|
|
369
|
-
if (
|
|
370
|
-
shutdownState.shutdownRequested ||
|
|
371
|
-
(error as Error).message === "Interrupted"
|
|
372
|
-
) {
|
|
342
|
+
if (shutdownState.shutdownRequested || (error as Error).message === "Interrupted") {
|
|
373
343
|
return { runState: RunState.INTERRUPTED };
|
|
374
344
|
}
|
|
375
345
|
logger.error("Runtime error: %s", (error as Error).message);
|
|
@@ -15,10 +15,7 @@ import supportsHyperlinks from "../terminal/supportsHyperlinks.ts";
|
|
|
15
15
|
* Default Bun implementation of a {@link CLI} using `process.stdout`, `process.stderr` and `process.argv`.
|
|
16
16
|
*/
|
|
17
17
|
export default class DefaultRuntimeCLI extends BaseCLI {
|
|
18
|
-
constructor(
|
|
19
|
-
cliConfig: CLIConfig,
|
|
20
|
-
options?: BaseCLIFeatureOptions,
|
|
21
|
-
) {
|
|
18
|
+
constructor(cliConfig: CLIConfig, options?: BaseCLIFeatureOptions) {
|
|
22
19
|
super(
|
|
23
20
|
cliConfig,
|
|
24
21
|
Writable.toWeb(process.stdout),
|
|
@@ -3,19 +3,10 @@ import type SubCommand from "../api/command/SubCommand.ts";
|
|
|
3
3
|
import type Option from "../api/argument/Option.ts";
|
|
4
4
|
import type Positional from "../api/argument/Positional.ts";
|
|
5
5
|
import type Context from "../api/Context.ts";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
ArgumentValueTypeName,
|
|
9
|
-
} from "../api/argument/ArgumentValueTypes.ts";
|
|
10
|
-
import {
|
|
11
|
-
COMPLETION_SERVICE_ID,
|
|
12
|
-
ShellType,
|
|
13
|
-
} from "../api/service/core/CompletionService.ts";
|
|
6
|
+
import { type ArgumentValues, ArgumentValueTypeName } from "../api/argument/ArgumentValueTypes.ts";
|
|
7
|
+
import { COMPLETION_SERVICE_ID, ShellType } from "../api/service/core/CompletionService.ts";
|
|
14
8
|
import type DefaultCompletionService from "../service/completion/DefaultCompletionService.ts";
|
|
15
|
-
import {
|
|
16
|
-
Icon,
|
|
17
|
-
PRINTER_SERVICE_ID,
|
|
18
|
-
} from "../api/service/core/PrinterService.ts";
|
|
9
|
+
import { Icon, PRINTER_SERVICE_ID } from "../api/service/core/PrinterService.ts";
|
|
19
10
|
import type PrinterService from "../api/service/core/PrinterService.ts";
|
|
20
11
|
|
|
21
12
|
export class CompletionIntegrationSubCommand implements SubCommand {
|
|
@@ -41,16 +32,11 @@ export class CompletionIntegrationSubCommand implements SubCommand {
|
|
|
41
32
|
},
|
|
42
33
|
];
|
|
43
34
|
|
|
44
|
-
async execute(
|
|
45
|
-
context: Context,
|
|
46
|
-
argumentValues: ArgumentValues,
|
|
47
|
-
): Promise<void> {
|
|
35
|
+
async execute(context: Context, argumentValues: ArgumentValues): Promise<void> {
|
|
48
36
|
const completionService = context.getServiceById(
|
|
49
37
|
COMPLETION_SERVICE_ID,
|
|
50
38
|
) as DefaultCompletionService;
|
|
51
|
-
const printerService = context.getServiceById(
|
|
52
|
-
PRINTER_SERVICE_ID,
|
|
53
|
-
) as PrinterService;
|
|
39
|
+
const printerService = context.getServiceById(PRINTER_SERVICE_ID) as PrinterService;
|
|
54
40
|
|
|
55
41
|
const shellType = argumentValues.shell as ShellType;
|
|
56
42
|
const configPathArg = argumentValues["config-path"] as string | undefined;
|
|
@@ -63,13 +49,9 @@ export class CompletionIntegrationSubCommand implements SubCommand {
|
|
|
63
49
|
);
|
|
64
50
|
}
|
|
65
51
|
|
|
66
|
-
const configPath = configPathArg ||
|
|
67
|
-
completionService.getDefaultConfigPath(shellType);
|
|
52
|
+
const configPath = configPathArg || completionService.getDefaultConfigPath(shellType);
|
|
68
53
|
const cliName = context.cliConfig.name;
|
|
69
|
-
const bootstrapScript = completionService.getBootstrapScript(
|
|
70
|
-
shellType,
|
|
71
|
-
cliName,
|
|
72
|
-
);
|
|
54
|
+
const bootstrapScript = completionService.getBootstrapScript(shellType, cliName);
|
|
73
55
|
|
|
74
56
|
const beginMarker = `# BEGIN ${cliName} completion`;
|
|
75
57
|
const endMarker = `# END ${cliName} completion`;
|
|
@@ -86,16 +68,17 @@ export class CompletionIntegrationSubCommand implements SubCommand {
|
|
|
86
68
|
const beginIdx = existingContent.indexOf(beginMarker);
|
|
87
69
|
const endIdx = existingContent.indexOf(endMarker);
|
|
88
70
|
if (beginIdx !== -1 && endIdx !== -1) {
|
|
89
|
-
newContent =
|
|
71
|
+
newContent =
|
|
72
|
+
existingContent.substring(0, beginIdx) +
|
|
90
73
|
block +
|
|
91
74
|
existingContent.substring(endIdx + endMarker.length);
|
|
92
75
|
} else {
|
|
93
|
-
const separator =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
76
|
+
const separator =
|
|
77
|
+
existingContent.length > 0 && !existingContent.endsWith("\n")
|
|
78
|
+
? "\n\n"
|
|
79
|
+
: existingContent.length > 0
|
|
80
|
+
? "\n"
|
|
81
|
+
: "";
|
|
99
82
|
newContent = existingContent + separator + block + "\n";
|
|
100
83
|
}
|
|
101
84
|
|
|
@@ -130,24 +113,16 @@ export class CompletionCompleteSubCommand implements SubCommand {
|
|
|
130
113
|
},
|
|
131
114
|
];
|
|
132
115
|
|
|
133
|
-
async execute(
|
|
134
|
-
context: Context,
|
|
135
|
-
argumentValues: ArgumentValues,
|
|
136
|
-
): Promise<void> {
|
|
116
|
+
async execute(context: Context, argumentValues: ArgumentValues): Promise<void> {
|
|
137
117
|
const completionService = context.getServiceById(
|
|
138
118
|
COMPLETION_SERVICE_ID,
|
|
139
119
|
) as DefaultCompletionService;
|
|
140
|
-
const printerService = context.getServiceById(
|
|
141
|
-
PRINTER_SERVICE_ID,
|
|
142
|
-
) as PrinterService;
|
|
120
|
+
const printerService = context.getServiceById(PRINTER_SERVICE_ID) as PrinterService;
|
|
143
121
|
|
|
144
122
|
const shellType = argumentValues.shell as ShellType;
|
|
145
123
|
const args = (argumentValues.args || []) as string[];
|
|
146
124
|
|
|
147
|
-
const completionContext = completionService.parseCompletionContext(
|
|
148
|
-
shellType,
|
|
149
|
-
args,
|
|
150
|
-
);
|
|
125
|
+
const completionContext = completionService.parseCompletionContext(shellType, args);
|
|
151
126
|
const completions = await completionService.generateCompletions(
|
|
152
127
|
shellType,
|
|
153
128
|
completionContext.line,
|
|
@@ -174,6 +149,5 @@ export class CompletionGroupCommand implements GroupCommand {
|
|
|
174
149
|
this.memberSubCommands = [integrationCommand, completeCommand];
|
|
175
150
|
}
|
|
176
151
|
|
|
177
|
-
async execute(_context: Context): Promise<void> {
|
|
178
|
-
}
|
|
152
|
+
async execute(_context: Context): Promise<void> {}
|
|
179
153
|
}
|
|
@@ -22,10 +22,7 @@ import {
|
|
|
22
22
|
import type GlobalModifierCommand from "../api/command/GlobalModifierCommand.ts";
|
|
23
23
|
import type CommandRegistry from "../runtime/registry/CommandRegistry.ts";
|
|
24
24
|
import type PrinterService from "../api/service/core/PrinterService.ts";
|
|
25
|
-
import {
|
|
26
|
-
Icon,
|
|
27
|
-
PRINTER_SERVICE_ID,
|
|
28
|
-
} from "../api/service/core/PrinterService.ts";
|
|
25
|
+
import { Icon, PRINTER_SERVICE_ID } from "../api/service/core/PrinterService.ts";
|
|
29
26
|
import type TableGeneratorService from "../api/service/core/TableGeneratorService.ts";
|
|
30
27
|
import { TABLE_GENERATOR_SERVICE_ID } from "../api/service/core/TableGeneratorService.ts";
|
|
31
28
|
|
|
@@ -38,10 +35,7 @@ abstract class MultiCommandCliAbstractHelpCommand {
|
|
|
38
35
|
readonly #includeEnvVars: boolean;
|
|
39
36
|
readonly #commandRegistry: CommandRegistry;
|
|
40
37
|
|
|
41
|
-
constructor(
|
|
42
|
-
includeEnvVars: boolean,
|
|
43
|
-
commandRegistry: CommandRegistry,
|
|
44
|
-
) {
|
|
38
|
+
constructor(includeEnvVars: boolean, commandRegistry: CommandRegistry) {
|
|
45
39
|
this.#includeEnvVars = includeEnvVars;
|
|
46
40
|
this.#commandRegistry = commandRegistry;
|
|
47
41
|
}
|
|
@@ -72,9 +66,7 @@ abstract class MultiCommandCliAbstractHelpCommand {
|
|
|
72
66
|
});
|
|
73
67
|
}
|
|
74
68
|
});
|
|
75
|
-
globalCommandsSection.helpEntries.sort((a, b) =>
|
|
76
|
-
a.syntax.localeCompare(b.syntax)
|
|
77
|
-
);
|
|
69
|
+
globalCommandsSection.helpEntries.sort((a, b) => a.syntax.localeCompare(b.syntax));
|
|
78
70
|
return globalCommandsSection;
|
|
79
71
|
}
|
|
80
72
|
|
|
@@ -85,8 +77,7 @@ abstract class MultiCommandCliAbstractHelpCommand {
|
|
|
85
77
|
groupCommands: ReadonlyArray<GroupCommand>,
|
|
86
78
|
subCommands: ReadonlyArray<SubCommand>,
|
|
87
79
|
): Array<HelpSection> {
|
|
88
|
-
const globalPrefix =
|
|
89
|
-
((groupCommands.length > 0) || (subCommands.length > 0)) ? "Global " : "";
|
|
80
|
+
const globalPrefix = groupCommands.length > 0 || subCommands.length > 0 ? "Global " : "";
|
|
90
81
|
const helpSections: HelpSection[] = [];
|
|
91
82
|
if (globalModifierCommands.length > 0) {
|
|
92
83
|
helpSections.push(
|
|
@@ -99,18 +90,12 @@ abstract class MultiCommandCliAbstractHelpCommand {
|
|
|
99
90
|
}
|
|
100
91
|
if (globalCommands.length > 0) {
|
|
101
92
|
helpSections.push(
|
|
102
|
-
this.#getGlobalCommandsHelpSection(
|
|
103
|
-
context,
|
|
104
|
-
`${globalPrefix}Commands`,
|
|
105
|
-
globalCommands,
|
|
106
|
-
),
|
|
93
|
+
this.#getGlobalCommandsHelpSection(context, `${globalPrefix}Commands`, globalCommands),
|
|
107
94
|
);
|
|
108
95
|
}
|
|
109
96
|
groupCommands.forEach((groupCommand) => {
|
|
110
97
|
const topicSection: HelpSection = {
|
|
111
|
-
title: `${
|
|
112
|
-
groupCommand.name.charAt(0).toUpperCase() + groupCommand.name.slice(1)
|
|
113
|
-
} Commands`,
|
|
98
|
+
title: `${groupCommand.name.charAt(0).toUpperCase() + groupCommand.name.slice(1)} Commands`,
|
|
114
99
|
helpEntries: [],
|
|
115
100
|
};
|
|
116
101
|
groupCommand.memberSubCommands.forEach((memberCommand) => {
|
|
@@ -156,9 +141,10 @@ abstract class MultiCommandCliAbstractHelpCommand {
|
|
|
156
141
|
|
|
157
142
|
if (otherSubCommands.length > 0) {
|
|
158
143
|
const topicSection: HelpSection = {
|
|
159
|
-
title:
|
|
160
|
-
|
|
161
|
-
|
|
144
|
+
title:
|
|
145
|
+
subCommandsByTopic.size > 0 || groupCommands.length > 0
|
|
146
|
+
? "Other Commands"
|
|
147
|
+
: "Sub-Commands",
|
|
162
148
|
helpEntries: [],
|
|
163
149
|
};
|
|
164
150
|
otherSubCommands.sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -174,18 +160,13 @@ abstract class MultiCommandCliAbstractHelpCommand {
|
|
|
174
160
|
return helpSections;
|
|
175
161
|
}
|
|
176
162
|
|
|
177
|
-
protected async printGenericHelp(
|
|
178
|
-
context
|
|
179
|
-
): Promise<void> {
|
|
180
|
-
const printerService = context.getServiceById(
|
|
181
|
-
PRINTER_SERVICE_ID,
|
|
182
|
-
) as PrinterService;
|
|
163
|
+
protected async printGenericHelp(context: Context): Promise<void> {
|
|
164
|
+
const printerService = context.getServiceById(PRINTER_SERVICE_ID) as PrinterService;
|
|
183
165
|
const tableGeneratorService = context.getServiceById(
|
|
184
166
|
TABLE_GENERATOR_SERVICE_ID,
|
|
185
167
|
) as TableGeneratorService;
|
|
186
168
|
|
|
187
|
-
const globalModifierCommands = this.#commandRegistry
|
|
188
|
-
.getGlobalModifierCommands();
|
|
169
|
+
const globalModifierCommands = this.#commandRegistry.getGlobalModifierCommands();
|
|
189
170
|
const globalCommands = this.#commandRegistry.getGlobalCommands();
|
|
190
171
|
const groupCommands = this.#commandRegistry.getGroupCommands();
|
|
191
172
|
const subCommands = this.#commandRegistry.getSubCommands();
|
|
@@ -215,20 +196,11 @@ abstract class MultiCommandCliAbstractHelpCommand {
|
|
|
215
196
|
),
|
|
216
197
|
);
|
|
217
198
|
|
|
218
|
-
await printHelpSections(
|
|
219
|
-
printerService,
|
|
220
|
-
tableGeneratorService,
|
|
221
|
-
helpSections,
|
|
222
|
-
);
|
|
199
|
+
await printHelpSections(printerService, tableGeneratorService, helpSections);
|
|
223
200
|
}
|
|
224
201
|
|
|
225
|
-
protected async printUsageHelp(
|
|
226
|
-
context
|
|
227
|
-
commandName: string,
|
|
228
|
-
): Promise<void> {
|
|
229
|
-
const printerService = context.getServiceById(
|
|
230
|
-
PRINTER_SERVICE_ID,
|
|
231
|
-
) as PrinterService;
|
|
202
|
+
protected async printUsageHelp(context: Context, commandName: string): Promise<void> {
|
|
203
|
+
const printerService = context.getServiceById(PRINTER_SERVICE_ID) as PrinterService;
|
|
232
204
|
const tableGeneratorService = context.getServiceById(
|
|
233
205
|
TABLE_GENERATOR_SERVICE_ID,
|
|
234
206
|
) as TableGeneratorService;
|
|
@@ -242,8 +214,8 @@ abstract class MultiCommandCliAbstractHelpCommand {
|
|
|
242
214
|
let groupCommand: GroupCommand | undefined;
|
|
243
215
|
|
|
244
216
|
if (subCommand === undefined) {
|
|
245
|
-
const result =
|
|
246
|
-
.getGroupCommandAndMemberSubCommandByJoinedName(commandName);
|
|
217
|
+
const result =
|
|
218
|
+
this.#commandRegistry.getGroupCommandAndMemberSubCommandByJoinedName(commandName);
|
|
247
219
|
if (result !== undefined) {
|
|
248
220
|
groupCommand = result.groupCommand;
|
|
249
221
|
subCommand = result.command;
|
|
@@ -273,50 +245,39 @@ abstract class MultiCommandCliAbstractHelpCommand {
|
|
|
273
245
|
}
|
|
274
246
|
|
|
275
247
|
// display command help
|
|
276
|
-
const name =
|
|
277
|
-
? subCommand.name
|
|
278
|
-
: `${groupCommand.name}:${subCommand.name}`;
|
|
248
|
+
const name =
|
|
249
|
+
groupCommand === undefined ? subCommand.name : `${groupCommand.name}:${subCommand.name}`;
|
|
279
250
|
const helpSections: HelpSection[] = [];
|
|
280
251
|
|
|
281
|
-
if (
|
|
282
|
-
(subCommand.description !== undefined) &&
|
|
283
|
-
(subCommand.description.length > 0)
|
|
284
|
-
) {
|
|
252
|
+
if (subCommand.description !== undefined && subCommand.description.length > 0) {
|
|
285
253
|
helpSections.push({
|
|
286
254
|
title: "Command",
|
|
287
|
-
helpEntries: [
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
255
|
+
helpEntries: [
|
|
256
|
+
{
|
|
257
|
+
syntax: subCommand.name,
|
|
258
|
+
description: subCommand.description,
|
|
259
|
+
},
|
|
260
|
+
],
|
|
291
261
|
});
|
|
292
262
|
}
|
|
293
263
|
helpSections.push({
|
|
294
264
|
title: "Usage",
|
|
295
|
-
helpEntries: [
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
265
|
+
helpEntries: [
|
|
266
|
+
{
|
|
267
|
+
syntax: `${context.cliConfig.name}${
|
|
268
|
+
name.length > 0 ? ` ${name}` : ""
|
|
269
|
+
}${getSubCommandArgumentsSyntax(subCommand)}`,
|
|
270
|
+
},
|
|
271
|
+
],
|
|
300
272
|
});
|
|
301
273
|
|
|
302
274
|
helpSections.push(
|
|
303
|
-
...getCommandArgsHelpSections(
|
|
304
|
-
context.cliConfig,
|
|
305
|
-
this.#includeEnvVars,
|
|
306
|
-
subCommand,
|
|
307
|
-
false,
|
|
308
|
-
),
|
|
275
|
+
...getCommandArgsHelpSections(context.cliConfig, this.#includeEnvVars, subCommand, false),
|
|
309
276
|
);
|
|
310
277
|
|
|
311
|
-
helpSections.push(
|
|
312
|
-
...getCommandExamplesHelpSections(printerService, context, subCommand),
|
|
313
|
-
);
|
|
278
|
+
helpSections.push(...getCommandExamplesHelpSections(printerService, context, subCommand));
|
|
314
279
|
|
|
315
|
-
await printHelpSections(
|
|
316
|
-
printerService,
|
|
317
|
-
tableGeneratorService,
|
|
318
|
-
helpSections,
|
|
319
|
-
);
|
|
280
|
+
await printHelpSections(printerService, tableGeneratorService, helpSections);
|
|
320
281
|
}
|
|
321
282
|
}
|
|
322
283
|
|
|
@@ -325,7 +286,8 @@ abstract class MultiCommandCliAbstractHelpCommand {
|
|
|
325
286
|
*/
|
|
326
287
|
export class MultiCommandCliHelpGlobalCommand
|
|
327
288
|
extends MultiCommandCliAbstractHelpCommand
|
|
328
|
-
implements GlobalCommand
|
|
289
|
+
implements GlobalCommand
|
|
290
|
+
{
|
|
329
291
|
readonly shortAlias = "h";
|
|
330
292
|
|
|
331
293
|
readonly argument = {
|
|
@@ -334,13 +296,8 @@ export class MultiCommandCliHelpGlobalCommand
|
|
|
334
296
|
isOptional: true,
|
|
335
297
|
};
|
|
336
298
|
|
|
337
|
-
public async execute(
|
|
338
|
-
|
|
339
|
-
argumentValue?: ArgumentSingleValueType,
|
|
340
|
-
): Promise<void> {
|
|
341
|
-
const commandName = argumentValue as
|
|
342
|
-
| string
|
|
343
|
-
| undefined;
|
|
299
|
+
public async execute(context: Context, argumentValue?: ArgumentSingleValueType): Promise<void> {
|
|
300
|
+
const commandName = argumentValue as string | undefined;
|
|
344
301
|
if (commandName !== undefined) {
|
|
345
302
|
await this.printUsageHelp(context, commandName);
|
|
346
303
|
} else {
|
|
@@ -354,7 +311,8 @@ export class MultiCommandCliHelpGlobalCommand
|
|
|
354
311
|
*/
|
|
355
312
|
export class MultiCommandCliHelpSubCommand
|
|
356
313
|
extends MultiCommandCliAbstractHelpCommand
|
|
357
|
-
implements SubCommand
|
|
314
|
+
implements SubCommand
|
|
315
|
+
{
|
|
358
316
|
public readonly options: ReadonlyArray<Option> = [];
|
|
359
317
|
|
|
360
318
|
public readonly positionals: ReadonlyArray<Positional> = [
|
|
@@ -366,13 +324,8 @@ export class MultiCommandCliHelpSubCommand
|
|
|
366
324
|
},
|
|
367
325
|
];
|
|
368
326
|
|
|
369
|
-
public async execute(
|
|
370
|
-
|
|
371
|
-
argumentValues: ArgumentValues,
|
|
372
|
-
): Promise<void> {
|
|
373
|
-
const commandName = argumentValues["command"] as
|
|
374
|
-
| string
|
|
375
|
-
| undefined;
|
|
327
|
+
public async execute(context: Context, argumentValues: ArgumentValues): Promise<void> {
|
|
328
|
+
const commandName = argumentValues["command"] as string | undefined;
|
|
376
329
|
if (commandName !== undefined) {
|
|
377
330
|
await this.printUsageHelp(context, commandName);
|
|
378
331
|
} else {
|