@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
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import type DataDumpGeneratorService from "../../api/service/core/DataDumpGeneratorService.ts";
|
|
3
|
+
import {
|
|
4
|
+
type ByteRangeColor,
|
|
5
|
+
DumpFormat,
|
|
6
|
+
type HexDumpGenerateOptions,
|
|
7
|
+
} from "../../api/service/core/DataDumpGeneratorService.ts";
|
|
8
|
+
|
|
9
|
+
export default class DefaultDataDumpGeneratorService
|
|
10
|
+
implements DataDumpGeneratorService {
|
|
11
|
+
colorEnabled = true;
|
|
12
|
+
colorFunction: (text: string, hexFormattedColor: string) => string = (text) =>
|
|
13
|
+
text;
|
|
14
|
+
|
|
15
|
+
#colorByte(
|
|
16
|
+
text: string,
|
|
17
|
+
byteValue: number,
|
|
18
|
+
colorScheme?: ByteRangeColor[],
|
|
19
|
+
): string {
|
|
20
|
+
if (!this.colorEnabled || !colorScheme) {
|
|
21
|
+
return text;
|
|
22
|
+
}
|
|
23
|
+
for (const range of colorScheme) {
|
|
24
|
+
if (byteValue >= range.start && byteValue <= range.end) {
|
|
25
|
+
return this.colorFunction(text, range.color);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return text;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
generate(data: Buffer, options?: HexDumpGenerateOptions): string {
|
|
32
|
+
if (data.length === 0) {
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const format = options?.format ?? DumpFormat.HEX;
|
|
37
|
+
const bytesPerGroup = options?.bytesPerGroup ?? 4;
|
|
38
|
+
const groupsPerRow = options?.groupsPerRow ?? 8;
|
|
39
|
+
const spacesBetweenGroups = options?.spacesBetweenGroups ?? 1;
|
|
40
|
+
const colorScheme = options?.colorScheme;
|
|
41
|
+
|
|
42
|
+
const bytesPerRow = bytesPerGroup * groupsPerRow;
|
|
43
|
+
const groupSeparator = " ".repeat(spacesBetweenGroups);
|
|
44
|
+
const rows: string[] = [];
|
|
45
|
+
|
|
46
|
+
for (let offset = 0; offset < data.length; offset += bytesPerRow) {
|
|
47
|
+
const groups: string[] = [];
|
|
48
|
+
|
|
49
|
+
for (let g = 0; g < groupsPerRow; g++) {
|
|
50
|
+
const groupStart = offset + g * bytesPerGroup;
|
|
51
|
+
let groupStr = "";
|
|
52
|
+
|
|
53
|
+
for (let b = 0; b < bytesPerGroup; b++) {
|
|
54
|
+
const byteIndex = groupStart + b;
|
|
55
|
+
if (byteIndex < data.length) {
|
|
56
|
+
const byteValue = data[byteIndex]!;
|
|
57
|
+
let rendered: string;
|
|
58
|
+
if (format === DumpFormat.ASCII) {
|
|
59
|
+
rendered = byteValue >= 0x20 && byteValue <= 0x7e
|
|
60
|
+
? String.fromCharCode(byteValue)
|
|
61
|
+
: ".";
|
|
62
|
+
} else {
|
|
63
|
+
rendered = byteValue.toString(16).toUpperCase().padStart(2, "0");
|
|
64
|
+
}
|
|
65
|
+
groupStr += this.#colorByte(rendered, byteValue, colorScheme);
|
|
66
|
+
} else {
|
|
67
|
+
// Pad partial group
|
|
68
|
+
groupStr += format === DumpFormat.ASCII ? " " : " ";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
groups.push(groupStr);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
rows.push(groups.join(groupSeparator));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return rows.join("\n");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import ImageRenderer from "../../terminal/ImageRenderer.ts";
|
|
2
|
+
import type ImagePrinterService from "../../api/service/core/ImagePrinterService.ts";
|
|
3
|
+
import type Terminal from "../../terminal/Terminal.ts";
|
|
4
|
+
|
|
5
|
+
export default class DefaultImagePrinterService implements ImagePrinterService {
|
|
6
|
+
readonly #renderer: ImageRenderer;
|
|
7
|
+
|
|
8
|
+
constructor(terminal: Terminal) {
|
|
9
|
+
this.#renderer = new ImageRenderer(terminal);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
image(
|
|
13
|
+
imageBuffer: Uint8Array,
|
|
14
|
+
widthPercentage: number = 100,
|
|
15
|
+
hexFormattedBackgroundColor?: string,
|
|
16
|
+
): Promise<string> {
|
|
17
|
+
return this.#renderer.renderImage(
|
|
18
|
+
imageBuffer,
|
|
19
|
+
widthPercentage,
|
|
20
|
+
hexFormattedBackgroundColor,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ServiceInfo,
|
|
3
|
+
ServiceProvider,
|
|
4
|
+
} from "../../api/service/ServiceProvider.ts";
|
|
5
|
+
import DefaultImagePrinterService from "./DefaultImagePrinterService.ts";
|
|
6
|
+
import { IMAGE_PRINTER_SERVICE_ID } from "../../api/service/core/ImagePrinterService.ts";
|
|
7
|
+
import type Context from "../../api/Context.ts";
|
|
8
|
+
import type CLIConfig from "../../api/CLIConfig.ts";
|
|
9
|
+
import type Terminal from "../../terminal/Terminal.ts";
|
|
10
|
+
|
|
11
|
+
export default class ImagePrinterServiceProvider implements ServiceProvider {
|
|
12
|
+
readonly serviceId: string = IMAGE_PRINTER_SERVICE_ID;
|
|
13
|
+
readonly #defaultImagePrinterService: DefaultImagePrinterService;
|
|
14
|
+
|
|
15
|
+
public constructor(
|
|
16
|
+
readonly servicePriority: number,
|
|
17
|
+
terminal: Terminal,
|
|
18
|
+
) {
|
|
19
|
+
this.#defaultImagePrinterService = new DefaultImagePrinterService(terminal);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public getServiceInfo(_cliConfig: CLIConfig): Promise<ServiceInfo> {
|
|
23
|
+
return Promise.resolve({
|
|
24
|
+
service: this.#defaultImagePrinterService,
|
|
25
|
+
commands: [],
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
initService(_context: Context): Promise<void> {
|
|
30
|
+
return Promise.resolve(undefined);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -27,7 +27,7 @@ export default class PrettyPrinterServiceProvider implements ServiceProvider {
|
|
|
27
27
|
this.#defaultPrettyPrinterService = new DefaultPrettyPrinterService();
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
public
|
|
30
|
+
public getServiceInfo(_cliConfig: CLIConfig): Promise<ServiceInfo> {
|
|
31
31
|
return Promise.resolve({
|
|
32
32
|
service: this.#defaultPrettyPrinterService,
|
|
33
33
|
commands: [],
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { default as Spinner } from "./terminal/Spinner.ts";
|
|
2
2
|
import { default as Progress } from "./terminal/Progress.ts";
|
|
3
3
|
import type PrinterService from "../../api/service/core/PrinterService.ts";
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
type Icon,
|
|
6
|
+
Level,
|
|
7
|
+
type ProgressStyle,
|
|
8
|
+
type SpinnerStyle,
|
|
9
|
+
} from "../../api/service/core/PrinterService.ts";
|
|
10
|
+
import type Terminal from "../../terminal/Terminal.ts";
|
|
6
11
|
import { Color } from "./terminal/Color.ts";
|
|
7
12
|
import { getDarkModeTheme, getLightModeTheme } from "./terminal/Theme.ts";
|
|
8
13
|
import { WritableStream } from "node:stream/web";
|
|
9
|
-
import Styler from "
|
|
10
|
-
|
|
14
|
+
import type Styler from "../../terminal/Styler.ts";
|
|
11
15
|
export default class DefaultPrinterService implements PrinterService {
|
|
12
16
|
readonly stdoutWritable: WritableStream;
|
|
13
17
|
readonly stderrWritable: WritableStream;
|
|
14
18
|
#stdoutIsColor: boolean;
|
|
19
|
+
#stdoutTerminal: Terminal;
|
|
15
20
|
#stderrTerminal: Terminal;
|
|
16
21
|
#styler: Styler;
|
|
17
22
|
#isDarkMode = true;
|
|
@@ -46,12 +51,14 @@ export default class DefaultPrinterService implements PrinterService {
|
|
|
46
51
|
stderrWritableStream: WritableStream,
|
|
47
52
|
stdoutIsColor: boolean,
|
|
48
53
|
stderrIsColor: boolean,
|
|
54
|
+
stdoutTerminal: Terminal,
|
|
49
55
|
stderrTerminal: Terminal,
|
|
50
56
|
styler: Styler,
|
|
51
57
|
) {
|
|
52
58
|
this.stdoutWritable = stdoutWritableStream;
|
|
53
59
|
this.stderrWritable = stderrWritableStream;
|
|
54
60
|
this.#stdoutIsColor = stdoutIsColor;
|
|
61
|
+
this.#stdoutTerminal = stdoutTerminal;
|
|
55
62
|
this.#stderrTerminal = stderrTerminal;
|
|
56
63
|
this.#styler = styler;
|
|
57
64
|
this.#styler.colorEnabled = stderrIsColor;
|
|
@@ -90,6 +97,26 @@ export default class DefaultPrinterService implements PrinterService {
|
|
|
90
97
|
return this.#styler.colorEnabled;
|
|
91
98
|
}
|
|
92
99
|
|
|
100
|
+
set hyperlinksEnabled(enabled: boolean) {
|
|
101
|
+
this.#styler.hyperlinksEnabled = enabled;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get hyperlinksEnabled(): boolean {
|
|
105
|
+
return this.#styler.hyperlinksEnabled;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public hyperlink(text: string, url: string): string {
|
|
109
|
+
return this.#styler.hyperlink(text, url);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
public stdoutColumns(): number {
|
|
113
|
+
return this.#stdoutTerminal.columns();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public stderrColumns(): number {
|
|
117
|
+
return this.#stderrTerminal.columns();
|
|
118
|
+
}
|
|
119
|
+
|
|
93
120
|
set darkMode(isDarkMode: boolean) {
|
|
94
121
|
this.#isDarkMode = isDarkMode;
|
|
95
122
|
if (isDarkMode) {
|
|
@@ -97,12 +124,12 @@ export default class DefaultPrinterService implements PrinterService {
|
|
|
97
124
|
} else {
|
|
98
125
|
this.#theme = getLightModeTheme();
|
|
99
126
|
}
|
|
100
|
-
this.#spinner.spinnerColor = this.#theme[Color.EMPHASISED]
|
|
101
|
-
this.#spinner.messageColor = this.#theme[Color.PRIMARY]
|
|
102
|
-
this.#progress.completeColor = this.#theme[Color.GREEN]
|
|
103
|
-
this.#progress.remainingColor = this.#theme[Color.SECONDARY]
|
|
104
|
-
this.#progress.labelColor = this.#theme[Color.SECONDARY]
|
|
105
|
-
this.#progress.valueColor = this.#theme[Color.PRIMARY]
|
|
127
|
+
this.#spinner.spinnerColor = this.#theme[Color.EMPHASISED]!;
|
|
128
|
+
this.#spinner.messageColor = this.#theme[Color.PRIMARY]!;
|
|
129
|
+
this.#progress.completeColor = this.#theme[Color.GREEN]!;
|
|
130
|
+
this.#progress.remainingColor = this.#theme[Color.SECONDARY]!;
|
|
131
|
+
this.#progress.labelColor = this.#theme[Color.SECONDARY]!;
|
|
132
|
+
this.#progress.valueColor = this.#theme[Color.PRIMARY]!;
|
|
106
133
|
}
|
|
107
134
|
|
|
108
135
|
get darkMode(): boolean {
|
|
@@ -110,19 +137,19 @@ export default class DefaultPrinterService implements PrinterService {
|
|
|
110
137
|
}
|
|
111
138
|
|
|
112
139
|
public primary(message: string): string {
|
|
113
|
-
return this.#styler.colorText(message, this.#theme[Color.PRIMARY]);
|
|
140
|
+
return this.#styler.colorText(message, this.#theme[Color.PRIMARY]!);
|
|
114
141
|
}
|
|
115
142
|
|
|
116
143
|
public secondary(message: string): string {
|
|
117
|
-
return this.#styler.colorText(message, this.#theme[Color.SECONDARY]);
|
|
144
|
+
return this.#styler.colorText(message, this.#theme[Color.SECONDARY]!);
|
|
118
145
|
}
|
|
119
146
|
|
|
120
147
|
public emphasised(message: string): string {
|
|
121
|
-
return this.#styler.colorText(message, this.#theme[Color.EMPHASISED]);
|
|
148
|
+
return this.#styler.colorText(message, this.#theme[Color.EMPHASISED]!);
|
|
122
149
|
}
|
|
123
150
|
|
|
124
151
|
public selected(message: string): string {
|
|
125
|
-
return this.#styler.colorText(message, this.#theme[Color.SELECTED]);
|
|
152
|
+
return this.#styler.colorText(message, this.#theme[Color.SELECTED]!);
|
|
126
153
|
}
|
|
127
154
|
|
|
128
155
|
public italic(message: string): string {
|
|
@@ -130,52 +157,135 @@ export default class DefaultPrinterService implements PrinterService {
|
|
|
130
157
|
}
|
|
131
158
|
|
|
132
159
|
public yellow(message: string): string {
|
|
133
|
-
return this.#styler.colorText(message, this.#theme[Color.YELLOW]);
|
|
160
|
+
return this.#styler.colorText(message, this.#theme[Color.YELLOW]!);
|
|
134
161
|
}
|
|
135
162
|
|
|
136
163
|
public orange(message: string): string {
|
|
137
|
-
return this.#styler.colorText(message, this.#theme[Color.ORANGE]);
|
|
164
|
+
return this.#styler.colorText(message, this.#theme[Color.ORANGE]!);
|
|
138
165
|
}
|
|
139
166
|
|
|
140
167
|
public red(message: string): string {
|
|
141
|
-
return this.#styler.colorText(message, this.#theme[Color.RED]);
|
|
168
|
+
return this.#styler.colorText(message, this.#theme[Color.RED]!);
|
|
142
169
|
}
|
|
143
170
|
|
|
144
171
|
public magenta(message: string): string {
|
|
145
|
-
return this.#styler.colorText(message, this.#theme[Color.MAGENTA]);
|
|
172
|
+
return this.#styler.colorText(message, this.#theme[Color.MAGENTA]!);
|
|
146
173
|
}
|
|
147
174
|
|
|
148
175
|
public violet(message: string): string {
|
|
149
|
-
return this.#styler.colorText(message, this.#theme[Color.VIOLET]);
|
|
176
|
+
return this.#styler.colorText(message, this.#theme[Color.VIOLET]!);
|
|
150
177
|
}
|
|
151
178
|
|
|
152
179
|
public blue(message: string): string {
|
|
153
|
-
return this.#styler.colorText(message, this.#theme[Color.BLUE]);
|
|
180
|
+
return this.#styler.colorText(message, this.#theme[Color.BLUE]!);
|
|
154
181
|
}
|
|
155
182
|
|
|
156
183
|
public cyan(message: string): string {
|
|
157
|
-
return this.#styler.colorText(message, this.#theme[Color.CYAN]);
|
|
184
|
+
return this.#styler.colorText(message, this.#theme[Color.CYAN]!);
|
|
158
185
|
}
|
|
159
186
|
|
|
160
187
|
public green(message: string): string {
|
|
161
|
-
return this.#styler.colorText(message, this.#theme[Color.GREEN]);
|
|
188
|
+
return this.#styler.colorText(message, this.#theme[Color.GREEN]!);
|
|
162
189
|
}
|
|
163
190
|
|
|
164
|
-
|
|
191
|
+
#parseHexColor(hexFormattedColor: string): number {
|
|
165
192
|
if (
|
|
166
193
|
(hexFormattedColor.length !== 7) ||
|
|
167
194
|
(!hexFormattedColor.toLowerCase().startsWith("#"))
|
|
168
195
|
) {
|
|
169
196
|
throw new Error(`Invalid color: ${hexFormattedColor}`);
|
|
170
197
|
}
|
|
171
|
-
|
|
172
198
|
const colorValue = parseInt(hexFormattedColor.slice(1), 16);
|
|
173
|
-
|
|
174
199
|
if (isNaN(colorValue) || (colorValue < 0 || colorValue > 0xffffff)) {
|
|
175
200
|
throw new Error(`Invalid color: ${hexFormattedColor}`);
|
|
176
201
|
}
|
|
202
|
+
return colorValue;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
public color(message: string, hexFormattedColor: string): string {
|
|
206
|
+
return this.#styler.colorText(
|
|
207
|
+
message,
|
|
208
|
+
this.#parseHexColor(hexFormattedColor),
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
public backgroundPrimary(message: string): string {
|
|
213
|
+
return this.#styler.backgroundColorText(
|
|
214
|
+
message,
|
|
215
|
+
this.#theme[Color.PRIMARY]!,
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public backgroundSecondary(message: string): string {
|
|
220
|
+
return this.#styler.backgroundColorText(
|
|
221
|
+
message,
|
|
222
|
+
this.#theme[Color.SECONDARY]!,
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
public backgroundEmphasised(message: string): string {
|
|
227
|
+
return this.#styler.backgroundColorText(
|
|
228
|
+
message,
|
|
229
|
+
this.#theme[Color.EMPHASISED]!,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
177
232
|
|
|
178
|
-
|
|
233
|
+
public backgroundSelected(message: string): string {
|
|
234
|
+
return this.#styler.backgroundColorText(
|
|
235
|
+
message,
|
|
236
|
+
this.#theme[Color.SELECTED]!,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
public backgroundYellow(message: string): string {
|
|
241
|
+
return this.#styler.backgroundColorText(
|
|
242
|
+
message,
|
|
243
|
+
this.#theme[Color.YELLOW]!,
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
public backgroundOrange(message: string): string {
|
|
248
|
+
return this.#styler.backgroundColorText(
|
|
249
|
+
message,
|
|
250
|
+
this.#theme[Color.ORANGE]!,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
public backgroundRed(message: string): string {
|
|
255
|
+
return this.#styler.backgroundColorText(message, this.#theme[Color.RED]!);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
public backgroundMagenta(message: string): string {
|
|
259
|
+
return this.#styler.backgroundColorText(
|
|
260
|
+
message,
|
|
261
|
+
this.#theme[Color.MAGENTA]!,
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
public backgroundViolet(message: string): string {
|
|
266
|
+
return this.#styler.backgroundColorText(
|
|
267
|
+
message,
|
|
268
|
+
this.#theme[Color.VIOLET]!,
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
public backgroundBlue(message: string): string {
|
|
273
|
+
return this.#styler.backgroundColorText(message, this.#theme[Color.BLUE]!);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
public backgroundCyan(message: string): string {
|
|
277
|
+
return this.#styler.backgroundColorText(message, this.#theme[Color.CYAN]!);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
public backgroundGreen(message: string): string {
|
|
281
|
+
return this.#styler.backgroundColorText(message, this.#theme[Color.GREEN]!);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
public backgroundColor(message: string, hexFormattedColor: string): string {
|
|
285
|
+
return this.#styler.backgroundColorText(
|
|
286
|
+
message,
|
|
287
|
+
this.#parseHexColor(hexFormattedColor),
|
|
288
|
+
);
|
|
179
289
|
}
|
|
180
290
|
|
|
181
291
|
public async debug(message: string, icon?: Icon): Promise<void> {
|
|
@@ -226,11 +336,17 @@ export default class DefaultPrinterService implements PrinterService {
|
|
|
226
336
|
return this.#threshold;
|
|
227
337
|
}
|
|
228
338
|
|
|
229
|
-
public async showSpinner(
|
|
339
|
+
public async showSpinner(
|
|
340
|
+
message?: string,
|
|
341
|
+
style?: SpinnerStyle,
|
|
342
|
+
): Promise<void> {
|
|
230
343
|
await this.#progress.hideAll();
|
|
231
344
|
if (this.#threshold > Level.INFO) {
|
|
232
345
|
return;
|
|
233
346
|
}
|
|
347
|
+
if (style != null) {
|
|
348
|
+
this.#spinner.spinnerStyle = style;
|
|
349
|
+
}
|
|
234
350
|
await this.#spinner.show(message);
|
|
235
351
|
}
|
|
236
352
|
|
|
@@ -243,11 +359,15 @@ export default class DefaultPrinterService implements PrinterService {
|
|
|
243
359
|
message = "",
|
|
244
360
|
total = 100,
|
|
245
361
|
current = 0,
|
|
362
|
+
style?: ProgressStyle,
|
|
246
363
|
): Promise<number> {
|
|
247
364
|
await this.#spinner.hide();
|
|
248
365
|
if (this.#threshold > Level.INFO) {
|
|
249
366
|
return -1;
|
|
250
367
|
}
|
|
368
|
+
if (style != null) {
|
|
369
|
+
this.#progress.progressStyle = style;
|
|
370
|
+
}
|
|
251
371
|
|
|
252
372
|
return this.#progress.add(units, message, total, current);
|
|
253
373
|
}
|
|
@@ -4,15 +4,14 @@ import type {
|
|
|
4
4
|
ServiceInfo,
|
|
5
5
|
ServiceProvider,
|
|
6
6
|
} from "../../api/service/ServiceProvider.ts";
|
|
7
|
-
import PrinterService
|
|
8
|
-
|
|
9
|
-
} from "../../api/service/core/PrinterService.ts";
|
|
7
|
+
import type PrinterService from "../../api/service/core/PrinterService.ts";
|
|
8
|
+
import { PRINTER_SERVICE_ID } from "../../api/service/core/PrinterService.ts";
|
|
10
9
|
import DarkModeCommand from "./command/DarkModeCommand.ts";
|
|
11
10
|
import NoColorCommand from "./command/NoColorCommand.ts";
|
|
11
|
+
import NoHyperlinksCommand from "./command/NoHyperlinksCommand.ts";
|
|
12
12
|
import type CLIConfig from "../../api/CLIConfig.ts";
|
|
13
|
-
import ShutdownService
|
|
14
|
-
|
|
15
|
-
} from "../../api/service/core/ShutdownService.ts";
|
|
13
|
+
import type ShutdownService from "../../api/service/core/ShutdownService.ts";
|
|
14
|
+
import { SHUTDOWN_SERVICE_ID } from "../../api/service/core/ShutdownService.ts";
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
17
|
* Provides a {@link PrinterService}.
|
|
@@ -36,10 +35,11 @@ export default class PrinterServiceProvider implements ServiceProvider {
|
|
|
36
35
|
this.printerService = printerService;
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
public
|
|
38
|
+
public getServiceInfo(_cliConfig: CLIConfig): Promise<ServiceInfo> {
|
|
40
39
|
return Promise.resolve({
|
|
41
40
|
service: this.printerService,
|
|
42
41
|
commands: [
|
|
42
|
+
new NoHyperlinksCommand(this, this.servicePriority + 3),
|
|
43
43
|
new DarkModeCommand(this, this.servicePriority + 2),
|
|
44
44
|
new NoColorCommand(this, this.servicePriority + 1),
|
|
45
45
|
new LogLevelCommand(this, this.servicePriority),
|
|
@@ -23,6 +23,7 @@ export default class LogLevelCommand implements GlobalModifierCommand {
|
|
|
23
23
|
"WARN",
|
|
24
24
|
"ERROR",
|
|
25
25
|
],
|
|
26
|
+
isCaseInsensitive: true,
|
|
26
27
|
defaultValue: "INFO",
|
|
27
28
|
configurationKey: "LOG_LEVEL",
|
|
28
29
|
};
|
|
@@ -44,7 +45,7 @@ export default class LogLevelCommand implements GlobalModifierCommand {
|
|
|
44
45
|
): Promise<void> {
|
|
45
46
|
const logLevel = argumentValue as string;
|
|
46
47
|
|
|
47
|
-
switch (logLevel) {
|
|
48
|
+
switch (logLevel.toUpperCase()) {
|
|
48
49
|
case "DEBUG":
|
|
49
50
|
this.#printerServiceProvider.printerService!.setLevel(
|
|
50
51
|
Level.DEBUG,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type GlobalModifierCommand from "../../../api/command/GlobalModifierCommand.ts";
|
|
2
|
+
import type GlobalCommandArgument from "../../../api/argument/GlobalCommandArgument.ts";
|
|
3
|
+
import {
|
|
4
|
+
type ArgumentSingleValueType,
|
|
5
|
+
ArgumentValueTypeName,
|
|
6
|
+
} from "../../../api/argument/ArgumentValueTypes.ts";
|
|
7
|
+
import type Context from "../../../api/Context.ts";
|
|
8
|
+
import type PrinterServiceProvider from "../PrinterServiceProvider.ts";
|
|
9
|
+
|
|
10
|
+
export default class NoHyperlinksCommand implements GlobalModifierCommand {
|
|
11
|
+
readonly name = "no-hyperlinks";
|
|
12
|
+
readonly description = "Disable hyperlinks for output";
|
|
13
|
+
readonly enableConfiguration = true;
|
|
14
|
+
readonly argument: GlobalCommandArgument = {
|
|
15
|
+
type: ArgumentValueTypeName.BOOLEAN,
|
|
16
|
+
defaultValue: false,
|
|
17
|
+
configurationKey: "NO_HYPERLINKS",
|
|
18
|
+
};
|
|
19
|
+
readonly executePriority: number;
|
|
20
|
+
|
|
21
|
+
readonly #printerServiceProvider: PrinterServiceProvider;
|
|
22
|
+
|
|
23
|
+
public constructor(
|
|
24
|
+
printerServiceProvider: PrinterServiceProvider,
|
|
25
|
+
executePriority: number,
|
|
26
|
+
) {
|
|
27
|
+
this.#printerServiceProvider = printerServiceProvider;
|
|
28
|
+
this.executePriority = executePriority;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public execute(
|
|
32
|
+
_context: Context,
|
|
33
|
+
argumentValue: ArgumentSingleValueType,
|
|
34
|
+
): Promise<void> {
|
|
35
|
+
this.#printerServiceProvider.printerService!.hyperlinksEnabled =
|
|
36
|
+
!argumentValue as boolean;
|
|
37
|
+
|
|
38
|
+
return Promise.resolve();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
import Styler from "
|
|
2
|
-
import type Terminal from "
|
|
1
|
+
import type Styler from "../../../terminal/Styler.ts";
|
|
2
|
+
import type Terminal from "../../../terminal/Terminal.ts";
|
|
3
3
|
|
|
4
4
|
const RATE_SMOOTHING_FACTOR = 0.005;
|
|
5
5
|
|
|
6
|
+
export { ProgressStyle } from "../../../api/service/core/PrinterService.ts";
|
|
7
|
+
import { ProgressStyle } from "../../../api/service/core/PrinterService.ts";
|
|
8
|
+
|
|
9
|
+
const STYLE_CHARS: Record<
|
|
10
|
+
ProgressStyle,
|
|
11
|
+
{ complete: string; remaining: string }
|
|
12
|
+
> = {
|
|
13
|
+
[ProgressStyle.STROKE]: { complete: "=", remaining: "-" },
|
|
14
|
+
[ProgressStyle.FILL]: { complete: "▰", remaining: "▱" },
|
|
15
|
+
};
|
|
16
|
+
|
|
6
17
|
interface Bar {
|
|
7
18
|
name: string;
|
|
8
19
|
current: number;
|
|
@@ -26,6 +37,7 @@ export default class Progress {
|
|
|
26
37
|
#remColor = 0x585858;
|
|
27
38
|
#labColor = 0x585858;
|
|
28
39
|
#valColor = 0x808080;
|
|
40
|
+
#style: ProgressStyle = ProgressStyle.STROKE;
|
|
29
41
|
|
|
30
42
|
public constructor(terminal: Terminal, styler: Styler) {
|
|
31
43
|
this.#terminal = terminal;
|
|
@@ -282,12 +294,13 @@ export default class Progress {
|
|
|
282
294
|
const completeLength = Math.floor(
|
|
283
295
|
totalLength * barInfo.bar.current / barInfo.bar.total,
|
|
284
296
|
);
|
|
297
|
+
const chars = STYLE_CHARS[this.#style];
|
|
285
298
|
const complete = this.#styler.colorText(
|
|
286
|
-
|
|
299
|
+
chars.complete.repeat(completeLength),
|
|
287
300
|
this.#comColor,
|
|
288
301
|
);
|
|
289
302
|
const remaining = this.#styler.colorText(
|
|
290
|
-
|
|
303
|
+
chars.remaining.repeat(totalLength - completeLength),
|
|
291
304
|
this.#remColor,
|
|
292
305
|
);
|
|
293
306
|
|
|
@@ -331,6 +344,10 @@ export default class Progress {
|
|
|
331
344
|
this.#valColor = color;
|
|
332
345
|
}
|
|
333
346
|
|
|
347
|
+
set progressStyle(style: ProgressStyle) {
|
|
348
|
+
this.#style = style;
|
|
349
|
+
}
|
|
350
|
+
|
|
334
351
|
#formatTime(millis: number): string {
|
|
335
352
|
let sec = millis / 1000;
|
|
336
353
|
if (sec < 60) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import Styler from "
|
|
2
|
-
import type Terminal from "
|
|
1
|
+
import type Styler from "../../../terminal/Styler.ts";
|
|
2
|
+
import type Terminal from "../../../terminal/Terminal.ts";
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const BOX_FRAMES = [
|
|
5
5
|
"⠋",
|
|
6
6
|
"⠙",
|
|
7
7
|
"⠹",
|
|
@@ -14,6 +14,20 @@ const FRAMES = [
|
|
|
14
14
|
"⠏",
|
|
15
15
|
];
|
|
16
16
|
|
|
17
|
+
const STAR_FRAMES = [
|
|
18
|
+
"★",
|
|
19
|
+
"✶",
|
|
20
|
+
"✷",
|
|
21
|
+
"✹",
|
|
22
|
+
"✷",
|
|
23
|
+
"✶",
|
|
24
|
+
"★",
|
|
25
|
+
"✦",
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export { SpinnerStyle } from "../../../api/service/core/PrinterService.ts";
|
|
29
|
+
import { SpinnerStyle } from "../../../api/service/core/PrinterService.ts";
|
|
30
|
+
|
|
17
31
|
export default class Spinner {
|
|
18
32
|
#isShown = false;
|
|
19
33
|
#message: string | undefined;
|
|
@@ -21,6 +35,7 @@ export default class Spinner {
|
|
|
21
35
|
#timer: Timer | undefined;
|
|
22
36
|
#spinColor = 0x8a8a8a;
|
|
23
37
|
#msgColor = 0x808080;
|
|
38
|
+
#style: SpinnerStyle = SpinnerStyle.BOX;
|
|
24
39
|
readonly #terminal: Terminal;
|
|
25
40
|
readonly #styler: Styler;
|
|
26
41
|
|
|
@@ -29,23 +44,28 @@ export default class Spinner {
|
|
|
29
44
|
this.#styler = styler;
|
|
30
45
|
}
|
|
31
46
|
|
|
47
|
+
get #frames(): string[] {
|
|
48
|
+
return this.#style === SpinnerStyle.STAR ? STAR_FRAMES : BOX_FRAMES;
|
|
49
|
+
}
|
|
50
|
+
|
|
32
51
|
async #nextFrame(): Promise<void> {
|
|
33
52
|
if (!this.#isShown) {
|
|
34
53
|
return;
|
|
35
54
|
}
|
|
55
|
+
const frames = this.#frames;
|
|
36
56
|
await this.#terminal.clearLine();
|
|
37
57
|
if (this.#message) {
|
|
38
58
|
await this.#terminal.write(
|
|
39
|
-
`${
|
|
40
|
-
this.#styler.colorText(this.#
|
|
41
|
-
}`,
|
|
59
|
+
`${
|
|
60
|
+
this.#styler.colorText(frames[this.#frameIndex]!, this.#spinColor)
|
|
61
|
+
} ${this.#styler.colorText(this.#message!, this.#msgColor)}`,
|
|
42
62
|
);
|
|
43
63
|
} else {
|
|
44
64
|
await this.#terminal.write(
|
|
45
|
-
this.#styler.colorText(
|
|
65
|
+
this.#styler.colorText(frames[this.#frameIndex]!, this.#spinColor),
|
|
46
66
|
);
|
|
47
67
|
}
|
|
48
|
-
this.#frameIndex = (this.#frameIndex + 1) %
|
|
68
|
+
this.#frameIndex = (this.#frameIndex + 1) % frames.length;
|
|
49
69
|
}
|
|
50
70
|
|
|
51
71
|
public async show(message?: string): Promise<void> {
|
|
@@ -97,4 +117,8 @@ export default class Spinner {
|
|
|
97
117
|
set messageColor(color: number) {
|
|
98
118
|
this.#msgColor = color;
|
|
99
119
|
}
|
|
120
|
+
|
|
121
|
+
set spinnerStyle(style: SpinnerStyle) {
|
|
122
|
+
this.#style = style;
|
|
123
|
+
}
|
|
100
124
|
}
|