@flowscripter/dynamic-cli-framework 1.1.5 → 1.2.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/.github/workflows/release-bun-library.yml +1 -0
- package/README/core-commands.md +40 -0
- package/README/core-service-providers.md +198 -0
- package/README/development.md +60 -0
- package/README/implementation-details.md +474 -0
- package/README/key-concepts.md +751 -0
- package/README.md +12 -1413
- package/bun.lock +20 -18
- package/index.ts +98 -1
- package/package.json +8 -7
- package/src/api/BaseCLIFeatureOptions.ts +10 -0
- package/src/api/CLIConfig.ts +5 -0
- package/src/api/RunResult.ts +16 -0
- package/src/api/argument/Argument.ts +40 -1
- package/src/api/argument/ArgumentValueTypes.ts +1 -1
- package/src/api/command/SubCommand.ts +1 -1
- package/src/api/service/ServiceProvider.ts +3 -3
- package/src/api/service/core/ArgumentPrompterService.ts +10 -0
- package/src/api/service/core/AsciiBannerGeneratorService.ts +44 -7
- package/src/api/service/core/CompletionService.ts +36 -0
- package/src/api/service/core/DataDumpGeneratorService.ts +27 -0
- package/src/api/service/core/ImagePrinterService.ts +26 -0
- package/src/api/service/core/KeyValueService.ts +22 -5
- package/src/api/service/core/PrinterService.ts +127 -1
- package/src/api/service/core/PrompterService.ts +49 -0
- package/src/api/service/core/SecretService.ts +27 -0
- package/src/api/service/core/ShutdownService.ts +17 -1
- package/src/api/service/core/Table.ts +85 -0
- package/src/api/service/core/TableGeneratorService.ts +38 -0
- package/src/api/service/core/TreePrinterService.ts +11 -0
- package/src/cli/BaseCLI.ts +116 -44
- package/src/cli/DefaultRuntimeCLI.ts +10 -18
- package/src/command/CompletionCommand.ts +179 -0
- package/src/command/MultiCommandCliHelpCommand.ts +20 -32
- package/src/command/SingleCommandCliHelpCommand.ts +10 -1
- package/src/launcher.ts +16 -58
- package/src/runtime/command/CommandValidator.ts +70 -6
- package/src/runtime/runner.ts +112 -31
- package/src/runtime/scanner.ts +18 -15
- package/src/runtime/values/argumentValueValidation.ts +93 -10
- package/src/runtime/values/globalCommandValuePopulation.ts +1 -1
- package/src/runtime/values/subCommandValuePopulation.ts +9 -8
- package/src/service/argumentPrompter/ArgumentPrompterServiceProvider.ts +34 -0
- package/src/service/argumentPrompter/DefaultArgumentPrompterService.ts +330 -0
- package/src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.ts +1 -1
- package/src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.ts +254 -17
- package/src/service/banner/BannerServiceProvider.ts +2 -2
- package/src/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.ts +85 -0
- package/src/service/chiselAsciiBannerGenerator/chisel.flf.json +3 -0
- package/src/service/completion/CompletionServiceProvider.ts +212 -0
- package/src/service/completion/DefaultCompletionService.ts +364 -0
- package/src/service/completion/shell/ShellHandler.ts +16 -0
- package/src/service/completion/shell/bash.ts +47 -0
- package/src/service/completion/shell/fish.ts +43 -0
- package/src/service/completion/shell/powershell.ts +66 -0
- package/src/service/completion/shell/zsh.ts +50 -0
- package/src/service/configuration/ConfigurationServiceProvider.ts +138 -42
- package/src/service/configuration/DefaultKeyValueService.ts +53 -7
- package/src/service/configuration/DefaultSecretService.ts +85 -0
- package/src/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.ts +41 -0
- package/src/service/dataDumpGenerator/DefaultDataDumpGeneratorService.ts +80 -0
- package/src/service/imagePrinter/DefaultImagePrinterService.ts +23 -0
- package/src/service/imagePrinter/ImagePrinterServiceProvider.ts +32 -0
- package/src/service/prettyPrinter/PrettyPrinterServiceProvider.ts +1 -1
- package/src/service/printer/DefaultPrinterService.ts +147 -27
- package/src/service/printer/PrinterServiceProvider.ts +7 -7
- package/src/service/printer/command/LogLevelCommand.ts +2 -1
- package/src/service/printer/command/NoHyperlinksCommand.ts +40 -0
- package/src/service/printer/terminal/Progress.ts +21 -4
- package/src/service/printer/terminal/Spinner.ts +32 -8
- package/src/service/printer/terminal/Theme.ts +1 -1
- package/src/service/prompter/DefaultPrompterService.ts +87 -0
- package/src/service/prompter/PrompterServiceProvider.ts +36 -0
- package/src/service/prompter/command/NoPromptCommand.ts +40 -0
- package/src/service/prompter/prompt/PromptContext.ts +47 -0
- package/src/service/prompter/prompt/promptAcknowledge.ts +28 -0
- package/src/service/prompter/prompt/promptMultiSelect.ts +99 -0
- package/src/service/prompter/prompt/promptOpenUrl.ts +97 -0
- package/src/service/prompter/prompt/promptSingleSelect.ts +102 -0
- package/src/service/prompter/prompt/promptText.ts +107 -0
- package/src/service/prompter/prompt/promptToggle.ts +28 -0
- package/src/service/shutdown/DefaultShutdownService.ts +13 -0
- package/src/service/shutdown/ShutdownServiceProvider.ts +28 -9
- package/src/service/shutdown/ShutdownState.ts +5 -0
- package/src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.ts +1 -1
- package/src/service/tableGenerator/DefaultTableGeneratorService.ts +415 -0
- package/src/service/tableGenerator/TableGeneratorServiceProvider.ts +43 -0
- package/src/service/treePrinter/DefaultTreePrinterService.ts +49 -0
- package/src/service/treePrinter/TreePrinterServiceProvider.ts +40 -0
- package/src/terminal/Ansi.ts +27 -0
- package/src/terminal/ImageRenderer.ts +199 -0
- package/src/terminal/KeyReader.ts +23 -0
- package/src/terminal/PngDecoder.ts +143 -0
- package/src/{service/printer/terminal → terminal}/Styler.ts +3 -0
- package/src/{service/printer/terminal → terminal}/Terminal.ts +1 -0
- package/src/terminal/TtyKeyReader.ts +83 -0
- package/src/terminal/TtyStyler.ts +78 -0
- package/src/{service/printer/terminal → terminal}/TtyTerminal.ts +9 -1
- package/src/terminal/supportsHyperlinks.ts +110 -0
- package/src/util/configHelper.ts +2 -2
- package/src/util/envVarHelper.ts +2 -2
- package/src/util/helpHelper.ts +139 -123
- package/src/util/logger.ts +16 -14
- package/src/util/runnerHelper.ts +41 -0
- package/tests/cli/BaseCLI.test.ts +50 -54
- package/tests/command/CompletionCommand.test.ts +68 -0
- package/tests/command/UsageCommand.test.ts +3 -2
- package/tests/command/VersionCommand.test.ts +3 -2
- package/tests/fixtures/Context.ts +9 -2
- package/tests/fixtures/util.ts +1 -1
- package/tests/runtime/command/CommandValidator.test.ts +103 -0
- package/tests/runtime/parser.test.ts +9 -7
- package/tests/runtime/registry/DefaultServiceProviderRegistry.test.ts +3 -3
- package/tests/runtime/runner.test.ts +36 -0
- package/tests/runtime/values/argumentValueValidation.test.ts +215 -1
- package/tests/service/argumentPrompter/ArgumentPrompterServiceProvider.test.ts +47 -0
- package/tests/service/argumentPrompter/DefaultArgumentPrompterService.test.ts +754 -0
- package/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.ts +5 -4
- package/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.ts +163 -3
- package/tests/service/asciiBannerGenerator/__snapshots__/DefaultAsciiBannerGeneratorService.test.ts.snap +1 -1
- package/tests/service/banner/BannerServiceProvider.test.ts +8 -4
- package/tests/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.test.ts +52 -0
- package/tests/service/completion/CompletionServiceProvider.test.ts +404 -0
- package/tests/service/completion/DefaultCompletionService.test.ts +278 -0
- package/tests/service/completion/shell/bash.test.ts +73 -0
- package/tests/service/completion/shell/fish.test.ts +62 -0
- package/tests/service/completion/shell/powershell.test.ts +59 -0
- package/tests/service/completion/shell/zsh.test.ts +60 -0
- package/tests/service/configuration/ConfigurationServiceProvider.test.ts +24 -12
- package/tests/service/configuration/DefaultKeyValueService.test.ts +118 -16
- package/tests/service/configuration/DefaultSecretService.test.ts +148 -0
- package/tests/service/configuration/command/ConfigCommand.test.ts +29 -0
- package/tests/service/configuration/command/DumpConfigCommand.test.ts +60 -0
- package/tests/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.test.ts +57 -0
- package/tests/service/dataDumpGenerator/DefaultDataDumpGeneratorService.test.ts +217 -0
- package/tests/service/imagePrinter/DefaultImagePrinterService.test.ts +96 -0
- package/tests/service/imagePrinter/ImagePrinterServiceProvider.test.ts +17 -0
- package/tests/service/prettyPrinter/DefaultPrettyPrinterService.test.ts +2 -2
- package/tests/service/prettyPrinter/PrettyPrinterServiceProvider.test.ts +5 -4
- package/tests/service/printer/DefaultPrinterService.test.ts +233 -2
- package/tests/service/printer/PrinterServiceProvider.test.ts +6 -5
- package/tests/service/printer/command/DarkModeCommand.test.ts +83 -0
- package/tests/service/printer/command/LogLevelCommand.test.ts +8 -6
- package/tests/service/printer/command/NoColorCommand.test.ts +83 -0
- package/tests/service/printer/command/NoHyperlinksCommand.test.ts +89 -0
- package/tests/service/printer/terminal/Progress.test.ts +64 -4
- package/tests/service/printer/terminal/Spinner.test.ts +44 -3
- package/tests/service/prompter/DefaultPrompterService.test.ts +615 -0
- package/tests/service/prompter/PrompterServiceProvider.test.ts +47 -0
- package/tests/service/prompter/command/NoPromptCommand.test.ts +58 -0
- package/tests/service/shutdown/ShutdownServiceProvider.test.ts +4 -2
- package/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.ts +3 -2
- package/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.ts +5 -4
- package/tests/service/tableGenerator/DefaultTableGeneratorService.test.ts +363 -0
- package/tests/service/tableGenerator/TableGeneratorServiceProvider.test.ts +47 -0
- package/tests/service/treePrinter/DefaultTreePrinterService.test.ts +144 -0
- package/tests/service/treePrinter/TreePrinterServiceProvider.test.ts +55 -0
- package/tests/terminal/ImageRenderer.test.ts +161 -0
- package/tests/terminal/PngDecoder.test.ts +223 -0
- package/tests/terminal/supportsHyperlinks.test.ts +149 -0
- package/tests/util/configHelper.test.ts +4 -4
- package/tests/util/logger.test.ts +23 -1
- package/tsconfig.json +31 -0
- package/src/service/printer/terminal/Ansi.ts +0 -10
- package/src/service/printer/terminal/TtyStyler.ts +0 -39
package/src/util/envVarHelper.ts
CHANGED
|
@@ -21,7 +21,7 @@ import type ComplexOption from "../api/argument/ComplexOption.ts";
|
|
|
21
21
|
|
|
22
22
|
function getKeySegment(segment: string) {
|
|
23
23
|
let keySegment = segment.replace("-", "_").toUpperCase();
|
|
24
|
-
if (keySegment[0]
|
|
24
|
+
if (keySegment[0]!.match(/[0-9]/)) {
|
|
25
25
|
keySegment = `_${keySegment}`;
|
|
26
26
|
}
|
|
27
27
|
return keySegment;
|
|
@@ -152,7 +152,7 @@ function getOptionValuesFromEnvVars(
|
|
|
152
152
|
getOptionValuesFromEnvVars(
|
|
153
153
|
(envVarValues[option.name] as Array<PopulatedArgumentValues>)[
|
|
154
154
|
index
|
|
155
|
-
]
|
|
155
|
+
]!,
|
|
156
156
|
matches,
|
|
157
157
|
env,
|
|
158
158
|
property,
|
package/src/util/helpHelper.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { distance } from "fastest-levenshtein";
|
|
1
2
|
import type GlobalCommand from "../api/command/GlobalCommand.ts";
|
|
2
3
|
import type GlobalCommandArgument from "../api/argument/GlobalCommandArgument.ts";
|
|
3
4
|
import {
|
|
@@ -20,12 +21,12 @@ import type CLIConfig from "../api/CLIConfig.ts";
|
|
|
20
21
|
import type PrinterService from "../api/service/core/PrinterService.ts";
|
|
21
22
|
import type SubCommandArgument from "../api/argument/SubCommandArgument.ts";
|
|
22
23
|
import type ComplexOption from "../api/argument/ComplexOption.ts";
|
|
24
|
+
import type TableGeneratorService from "../api/service/core/TableGeneratorService.ts";
|
|
25
|
+
import Table from "../api/service/core/Table.ts";
|
|
23
26
|
|
|
24
27
|
const SYNTAX_INDENT_WIDTH = 2;
|
|
25
|
-
const SYNTAX_MIN_PADDING_WIDTH = 2;
|
|
26
28
|
const MINIMUM_SYNTAX_COLUMN_WIDTH = 15;
|
|
27
29
|
const HELP_SYNTAX_INDENT = " ".repeat(SYNTAX_INDENT_WIDTH);
|
|
28
|
-
const HELP_SYNTAX_PADDING = " ".repeat(SYNTAX_MIN_PADDING_WIDTH);
|
|
29
30
|
|
|
30
31
|
export interface HelpEntry {
|
|
31
32
|
readonly syntax: string;
|
|
@@ -39,169 +40,113 @@ export interface HelpSection {
|
|
|
39
40
|
readonly helpEntries: Array<HelpEntry>;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
interface FlattenedRow {
|
|
44
|
+
syntax: string;
|
|
45
|
+
description?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function flattenHelpEntry(
|
|
43
49
|
printerService: PrinterService,
|
|
44
50
|
helpEntry: HelpEntry,
|
|
45
|
-
syntaxWidth: number,
|
|
46
51
|
indentText: string,
|
|
47
52
|
isRoot: boolean,
|
|
48
53
|
isLastSibling: boolean,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
let syntaxTreeChars = "";
|
|
53
|
-
let totalSyntaxLength = 0;
|
|
54
|
-
|
|
54
|
+
rows: FlattenedRow[],
|
|
55
|
+
): void {
|
|
56
|
+
let syntax = "";
|
|
55
57
|
if (helpEntry.syntax) {
|
|
56
58
|
if (isRoot) {
|
|
57
|
-
|
|
58
|
-
totalSyntaxLength = SYNTAX_INDENT_WIDTH + helpEntry.syntax.length;
|
|
59
|
+
syntax = HELP_SYNTAX_INDENT + printerService.primary(helpEntry.syntax);
|
|
59
60
|
} else {
|
|
61
|
+
let syntaxTreeChars = "";
|
|
60
62
|
if (indentText.length > 0) {
|
|
61
63
|
syntaxTreeChars = isLastSibling ? "└╴" : "├╴";
|
|
62
64
|
}
|
|
63
|
-
|
|
65
|
+
syntax = HELP_SYNTAX_INDENT +
|
|
64
66
|
printerService.secondary(indentText + syntaxTreeChars) +
|
|
65
67
|
printerService.primary(helpEntry.syntax);
|
|
66
|
-
totalSyntaxLength = SYNTAX_INDENT_WIDTH + indentText.length +
|
|
67
|
-
syntaxTreeChars.length + helpEntry.syntax.length;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
if (helpEntry.description) {
|
|
71
|
-
if (helpEntry.syntax) {
|
|
72
|
-
if (totalSyntaxLength > notesIndent) {
|
|
73
|
-
text += HELP_SYNTAX_PADDING +
|
|
74
|
-
printerService.secondary(helpEntry.description);
|
|
75
|
-
} else {
|
|
76
|
-
text += " ".repeat(syntaxWidth - totalSyntaxLength) +
|
|
77
|
-
printerService.secondary(helpEntry.description);
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
text += HELP_SYNTAX_PADDING +
|
|
81
|
-
printerService.secondary(helpEntry.description);
|
|
82
68
|
}
|
|
83
69
|
}
|
|
84
|
-
text += "\n";
|
|
85
|
-
await printerService.print(text);
|
|
86
|
-
}
|
|
87
70
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (hasChildren) {
|
|
98
|
-
await printSingleHelpEntry(
|
|
99
|
-
printerService,
|
|
100
|
-
helpEntry,
|
|
101
|
-
syntaxWidth,
|
|
102
|
-
indentText,
|
|
103
|
-
isRoot,
|
|
104
|
-
isLastSibling,
|
|
105
|
-
);
|
|
106
|
-
indentText += (isLastSibling ? " " : "│ ") +
|
|
71
|
+
const description = helpEntry.description
|
|
72
|
+
? printerService.secondary(helpEntry.description)
|
|
73
|
+
: undefined;
|
|
74
|
+
|
|
75
|
+
rows.push({ syntax, description });
|
|
76
|
+
|
|
77
|
+
if (helpEntry.helpSubEntries !== undefined) {
|
|
78
|
+
const nextIndent = indentText +
|
|
79
|
+
(isLastSibling ? " " : "│ ") +
|
|
107
80
|
" ".repeat(helpEntry.subEntryIndent || 0);
|
|
108
|
-
for (let i = 0; i < helpEntry.helpSubEntries
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
const helpSubEntryIsLastSibling =
|
|
112
|
-
i === helpEntry.helpSubEntries!.length - 1;
|
|
113
|
-
await printHelpEntry(
|
|
81
|
+
for (let i = 0; i < helpEntry.helpSubEntries.length; i++) {
|
|
82
|
+
const sub = helpEntry.helpSubEntries[i]!;
|
|
83
|
+
flattenHelpEntry(
|
|
114
84
|
printerService,
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
indentText,
|
|
85
|
+
sub,
|
|
86
|
+
nextIndent,
|
|
118
87
|
false,
|
|
119
|
-
|
|
120
|
-
|
|
88
|
+
i === helpEntry.helpSubEntries.length - 1,
|
|
89
|
+
rows,
|
|
121
90
|
);
|
|
122
91
|
}
|
|
123
|
-
} else {
|
|
124
|
-
await printSingleHelpEntry(
|
|
125
|
-
printerService,
|
|
126
|
-
helpEntry,
|
|
127
|
-
syntaxWidth,
|
|
128
|
-
indentText,
|
|
129
|
-
isRoot,
|
|
130
|
-
isLastSibling,
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function getSyntaxWidth(helpEntry: HelpEntry, indent: number): number {
|
|
136
|
-
if (
|
|
137
|
-
(helpEntry.helpSubEntries === undefined) ||
|
|
138
|
-
(helpEntry.helpSubEntries.length === 0)
|
|
139
|
-
) {
|
|
140
|
-
// 2 is for the tree characters
|
|
141
|
-
let finalWidth = SYNTAX_INDENT_WIDTH + indent + 2 +
|
|
142
|
-
SYNTAX_MIN_PADDING_WIDTH;
|
|
143
|
-
if (helpEntry.syntax) {
|
|
144
|
-
finalWidth += helpEntry.syntax.length;
|
|
145
|
-
}
|
|
146
|
-
return finalWidth;
|
|
147
92
|
}
|
|
148
|
-
let maxSubIndent = 0;
|
|
149
|
-
helpEntry.helpSubEntries.forEach((helpSubEntry) => {
|
|
150
|
-
// 2 is for the tree characters
|
|
151
|
-
const subEntryWidth = getSyntaxWidth(
|
|
152
|
-
helpSubEntry,
|
|
153
|
-
(helpEntry.subEntryIndent ? helpEntry.subEntryIndent : 0) + 2,
|
|
154
|
-
);
|
|
155
|
-
if (subEntryWidth > maxSubIndent) {
|
|
156
|
-
maxSubIndent = subEntryWidth;
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
return indent + maxSubIndent;
|
|
160
93
|
}
|
|
161
94
|
|
|
162
95
|
export async function printHelpSections(
|
|
163
96
|
printerService: PrinterService,
|
|
97
|
+
tableGeneratorService: TableGeneratorService,
|
|
164
98
|
sections: Array<HelpSection>,
|
|
165
99
|
): Promise<void> {
|
|
166
|
-
|
|
167
|
-
let syntaxWidth = SYNTAX_INDENT_WIDTH + MINIMUM_SYNTAX_COLUMN_WIDTH +
|
|
168
|
-
SYNTAX_MIN_PADDING_WIDTH;
|
|
169
|
-
sections.forEach((section) => {
|
|
170
|
-
section.helpEntries.forEach((helpEntry) => {
|
|
171
|
-
const entrySyntaxWidth = getSyntaxWidth(helpEntry, 0);
|
|
172
|
-
// don't expand out if no description as we can overwrite that space on the line
|
|
173
|
-
if (
|
|
174
|
-
helpEntry.description && (helpEntry.description.length > 0) &&
|
|
175
|
-
(entrySyntaxWidth > syntaxWidth)
|
|
176
|
-
) {
|
|
177
|
-
syntaxWidth = entrySyntaxWidth;
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
});
|
|
100
|
+
const terminalWidth = printerService.stdoutColumns();
|
|
181
101
|
|
|
182
|
-
// print the help
|
|
183
102
|
for (let i = 0; i < sections.length; i++) {
|
|
184
|
-
const section = sections[i]
|
|
103
|
+
const section = sections[i]!;
|
|
185
104
|
if (section.title.length > 0) {
|
|
186
105
|
await printerService.print(
|
|
187
106
|
`${printerService.emphasised(section.title)}\n\n`,
|
|
188
107
|
);
|
|
189
108
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
109
|
+
|
|
110
|
+
if (section.helpEntries.length === 0) continue;
|
|
111
|
+
|
|
112
|
+
const rows: FlattenedRow[] = [];
|
|
113
|
+
for (const helpEntry of section.helpEntries) {
|
|
114
|
+
flattenHelpEntry(
|
|
193
115
|
printerService,
|
|
194
116
|
helpEntry,
|
|
195
|
-
syntaxWidth,
|
|
196
117
|
"",
|
|
197
118
|
true,
|
|
198
|
-
helpEntry.helpSubEntries !== undefined,
|
|
199
119
|
true,
|
|
120
|
+
rows,
|
|
200
121
|
);
|
|
201
122
|
}
|
|
202
|
-
|
|
203
|
-
|
|
123
|
+
|
|
124
|
+
const hasDescriptions = rows.some((r) => r.description !== undefined);
|
|
125
|
+
|
|
126
|
+
if (hasDescriptions) {
|
|
127
|
+
const table = new Table(rows.length, 2, {
|
|
128
|
+
border: false,
|
|
129
|
+
padding: 1,
|
|
130
|
+
maxWidth: terminalWidth,
|
|
131
|
+
});
|
|
132
|
+
table.column(0, { minWidth: MINIMUM_SYNTAX_COLUMN_WIDTH });
|
|
133
|
+
table.column(1, { flexWeight: 1 });
|
|
134
|
+
|
|
135
|
+
for (let r = 0; r < rows.length; r++) {
|
|
136
|
+
const row = rows[r]!;
|
|
137
|
+
table.cell(r, 0, row.syntax);
|
|
138
|
+
table.cell(r, 1, row.description ?? "");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const rendered = tableGeneratorService.render(table);
|
|
142
|
+
await printerService.print(rendered + "\n");
|
|
143
|
+
} else {
|
|
144
|
+
for (const row of rows) {
|
|
145
|
+
await printerService.print(row.syntax + "\n");
|
|
146
|
+
}
|
|
204
147
|
}
|
|
148
|
+
|
|
149
|
+
await printerService.print("\n");
|
|
205
150
|
}
|
|
206
151
|
}
|
|
207
152
|
|
|
@@ -267,6 +212,20 @@ export function getGlobalArgumentHelpEntry(
|
|
|
267
212
|
notesItems.push("number value");
|
|
268
213
|
break;
|
|
269
214
|
}
|
|
215
|
+
if (
|
|
216
|
+
(argument.minValueInclusive !== undefined) ||
|
|
217
|
+
(argument.maxValueInclusive !== undefined)
|
|
218
|
+
) {
|
|
219
|
+
let range = "..";
|
|
220
|
+
|
|
221
|
+
if (argument.minValueInclusive !== undefined) {
|
|
222
|
+
range = argument.minValueInclusive + range;
|
|
223
|
+
}
|
|
224
|
+
if (argument.maxValueInclusive !== undefined) {
|
|
225
|
+
range += argument.maxValueInclusive;
|
|
226
|
+
}
|
|
227
|
+
notesItems.push(range);
|
|
228
|
+
}
|
|
270
229
|
}
|
|
271
230
|
|
|
272
231
|
if (argument.defaultValue !== undefined) {
|
|
@@ -399,6 +358,21 @@ function getOptionHelpEntry(
|
|
|
399
358
|
}
|
|
400
359
|
}
|
|
401
360
|
}
|
|
361
|
+
if (
|
|
362
|
+
(option.minValueInclusive !== undefined) ||
|
|
363
|
+
(option.maxValueInclusive !== undefined)
|
|
364
|
+
) {
|
|
365
|
+
let range = "..";
|
|
366
|
+
|
|
367
|
+
if (option.minValueInclusive !== undefined) {
|
|
368
|
+
range = option.minValueInclusive + range;
|
|
369
|
+
}
|
|
370
|
+
if (option.maxValueInclusive !== undefined) {
|
|
371
|
+
range += option.maxValueInclusive;
|
|
372
|
+
}
|
|
373
|
+
notesItems.push(range);
|
|
374
|
+
}
|
|
375
|
+
|
|
402
376
|
if (option.defaultValue !== undefined) {
|
|
403
377
|
notesItems.push(
|
|
404
378
|
`default: ${
|
|
@@ -480,6 +454,20 @@ function getPositionalHelpEntry(
|
|
|
480
454
|
break;
|
|
481
455
|
}
|
|
482
456
|
}
|
|
457
|
+
if (
|
|
458
|
+
(positional.minValueInclusive !== undefined) ||
|
|
459
|
+
(positional.maxValueInclusive !== undefined)
|
|
460
|
+
) {
|
|
461
|
+
let range = "..";
|
|
462
|
+
|
|
463
|
+
if (positional.minValueInclusive !== undefined) {
|
|
464
|
+
range = positional.minValueInclusive + range;
|
|
465
|
+
}
|
|
466
|
+
if (positional.maxValueInclusive !== undefined) {
|
|
467
|
+
range += positional.maxValueInclusive;
|
|
468
|
+
}
|
|
469
|
+
notesItems.push(range);
|
|
470
|
+
}
|
|
483
471
|
|
|
484
472
|
if (positional.isVarargOptional) {
|
|
485
473
|
notesItems.push("optional");
|
|
@@ -633,7 +621,7 @@ export function getMultiCommandAppSyntax(
|
|
|
633
621
|
let argOptional = false;
|
|
634
622
|
let argValueOptional = false;
|
|
635
623
|
let multipleArg = false;
|
|
636
|
-
const commandClauses = [];
|
|
624
|
+
const commandClauses: string[] = [];
|
|
637
625
|
if (globalCommands.length > 0) {
|
|
638
626
|
commandClauses.push(`<${globalPrefix}command>`);
|
|
639
627
|
arg = globalCommands.some((
|
|
@@ -749,3 +737,31 @@ export function getMultiCommandAppSyntax(
|
|
|
749
737
|
}
|
|
750
738
|
return syntax;
|
|
751
739
|
}
|
|
740
|
+
|
|
741
|
+
export function findPossibleCommandNames(
|
|
742
|
+
commandName: string,
|
|
743
|
+
groupCommands: ReadonlyArray<GroupCommand>,
|
|
744
|
+
subCommands: ReadonlyArray<SubCommand>,
|
|
745
|
+
): string[] {
|
|
746
|
+
const levenCommandArray = new Array<[number, string]>();
|
|
747
|
+
subCommands.forEach((subCommand) => {
|
|
748
|
+
levenCommandArray.push([
|
|
749
|
+
distance(subCommand.name, commandName),
|
|
750
|
+
subCommand.name,
|
|
751
|
+
]);
|
|
752
|
+
});
|
|
753
|
+
groupCommands.forEach((groupCommand) => {
|
|
754
|
+
groupCommand.memberSubCommands.forEach((memberCommand) => {
|
|
755
|
+
const memberName = `${groupCommand.name}:${memberCommand.name}`;
|
|
756
|
+
levenCommandArray.push([
|
|
757
|
+
distance(memberName, commandName),
|
|
758
|
+
memberName,
|
|
759
|
+
]);
|
|
760
|
+
});
|
|
761
|
+
});
|
|
762
|
+
return levenCommandArray
|
|
763
|
+
.sort((a, b) => a[0] - b[0])
|
|
764
|
+
.slice(0, 2)
|
|
765
|
+
.filter((value) => value[0] < 3)
|
|
766
|
+
.map((value) => value[1]);
|
|
767
|
+
}
|
package/src/util/logger.ts
CHANGED
|
@@ -86,9 +86,11 @@ function wrapDefaultLogger(
|
|
|
86
86
|
* @returns A logger instance with the specified name.
|
|
87
87
|
*/
|
|
88
88
|
export default function getLogger(loggerName: string): Logger {
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
const g = globalThis as Record<string, unknown>;
|
|
90
|
+
if (g.defaultLogger === undefined) {
|
|
91
|
+
g.defaultLogger = getDefaultLogger();
|
|
91
92
|
}
|
|
93
|
+
const defaultLogger = g.defaultLogger as Logger;
|
|
92
94
|
|
|
93
95
|
if (loggerName.length > maxLoggerNameLength) {
|
|
94
96
|
maxLoggerNameLength = loggerName.length;
|
|
@@ -108,28 +110,28 @@ export default function getLogger(loggerName: string): Logger {
|
|
|
108
110
|
return {
|
|
109
111
|
trace: wrapDefaultLogger(
|
|
110
112
|
loggerName,
|
|
111
|
-
LEVEL_PADDINGS.TRACE
|
|
112
|
-
|
|
113
|
+
LEVEL_PADDINGS.TRACE!,
|
|
114
|
+
defaultLogger.trace,
|
|
113
115
|
),
|
|
114
116
|
debug: wrapDefaultLogger(
|
|
115
117
|
loggerName,
|
|
116
|
-
LEVEL_PADDINGS.DEBUG
|
|
117
|
-
|
|
118
|
+
LEVEL_PADDINGS.DEBUG!,
|
|
119
|
+
defaultLogger.debug,
|
|
118
120
|
),
|
|
119
121
|
info: wrapDefaultLogger(
|
|
120
122
|
loggerName,
|
|
121
|
-
LEVEL_PADDINGS.INFO
|
|
122
|
-
|
|
123
|
+
LEVEL_PADDINGS.INFO!,
|
|
124
|
+
defaultLogger.info,
|
|
123
125
|
),
|
|
124
126
|
warn: wrapDefaultLogger(
|
|
125
127
|
loggerName,
|
|
126
|
-
LEVEL_PADDINGS.WARN
|
|
127
|
-
|
|
128
|
+
LEVEL_PADDINGS.WARN!,
|
|
129
|
+
defaultLogger.warn,
|
|
128
130
|
),
|
|
129
131
|
error: wrapDefaultLogger(
|
|
130
132
|
loggerName,
|
|
131
|
-
LEVEL_PADDINGS.ERROR
|
|
132
|
-
|
|
133
|
+
LEVEL_PADDINGS.ERROR!,
|
|
134
|
+
defaultLogger.error,
|
|
133
135
|
),
|
|
134
136
|
};
|
|
135
137
|
}
|
|
@@ -140,8 +142,8 @@ export default function getLogger(loggerName: string): Logger {
|
|
|
140
142
|
warn: () => {},
|
|
141
143
|
error: wrapDefaultLogger(
|
|
142
144
|
loggerName,
|
|
143
|
-
LEVEL_PADDINGS.ERROR
|
|
144
|
-
|
|
145
|
+
LEVEL_PADDINGS.ERROR!,
|
|
146
|
+
defaultLogger.error,
|
|
145
147
|
),
|
|
146
148
|
};
|
|
147
149
|
}
|
package/src/util/runnerHelper.ts
CHANGED
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
} from "../runtime/command/CommandTypeGuards.ts";
|
|
11
11
|
import type Context from "../api/Context.ts";
|
|
12
12
|
import { getInvalidArgumentString } from "../runtime/values/argumentValueValidation.ts";
|
|
13
|
+
import type CommandRegistry from "../runtime/registry/CommandRegistry.ts";
|
|
14
|
+
import { findPossibleCommandNames } from "./helpHelper.ts";
|
|
13
15
|
|
|
14
16
|
function getCommandString(
|
|
15
17
|
printerService: PrinterService,
|
|
@@ -91,6 +93,45 @@ export async function printNoCommandSpecifiedError(context: Context) {
|
|
|
91
93
|
await printerService.error("No command specified\n\n");
|
|
92
94
|
}
|
|
93
95
|
|
|
96
|
+
export async function printNoCommandRecognisedError(
|
|
97
|
+
context: Context,
|
|
98
|
+
commandRegistry: CommandRegistry,
|
|
99
|
+
availableArgs: ReadonlyArray<string>,
|
|
100
|
+
) {
|
|
101
|
+
const printerService = context.getServiceById(
|
|
102
|
+
PRINTER_SERVICE_ID,
|
|
103
|
+
) as PrinterService;
|
|
104
|
+
await printerService.error("No command recognised\n\n");
|
|
105
|
+
|
|
106
|
+
if (availableArgs.length > 0) {
|
|
107
|
+
const groupCommands = commandRegistry.getGroupCommands();
|
|
108
|
+
const subCommands = commandRegistry.getSubCommands();
|
|
109
|
+
|
|
110
|
+
const allPossibleCommandNames: string[] = [];
|
|
111
|
+
for (const arg of availableArgs) {
|
|
112
|
+
// look for other possible matches
|
|
113
|
+
const possibleCommandNames = findPossibleCommandNames(
|
|
114
|
+
arg,
|
|
115
|
+
groupCommands,
|
|
116
|
+
subCommands,
|
|
117
|
+
);
|
|
118
|
+
// add the possible command names to the list if not already present
|
|
119
|
+
for (const possibleCommandName of possibleCommandNames) {
|
|
120
|
+
if (!allPossibleCommandNames.includes(possibleCommandName)) {
|
|
121
|
+
allPossibleCommandNames.push(possibleCommandName);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (allPossibleCommandNames.length > 0) {
|
|
127
|
+
await printerService.print(
|
|
128
|
+
`Possible matches: ${allPossibleCommandNames.join(", ")}\n\n`,
|
|
129
|
+
Icon.INFORMATION,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
94
135
|
export async function printUnusedArgsWarning(
|
|
95
136
|
context: Context,
|
|
96
137
|
overallUnusedArgs: ReadonlyArray<string>,
|