@flowscripter/dynamic-cli-framework 1.7.3 → 1.7.5
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/cli-plugin.ts +1 -1
- package/dist/cli-plugin.d.ts +1 -1
- package/dist/cli-plugin.d.ts.map +1 -1
- package/dist/cli-plugin.js +25 -247
- package/dist/index.js +70 -105754
- package/dist/src/api/BaseCLIFeatureOptions.js +0 -0
- package/dist/src/api/CLI.js +0 -0
- package/dist/src/api/CLIConfig.js +0 -0
- package/dist/src/api/Context.js +0 -0
- package/dist/src/api/RunResult.js +73 -0
- package/dist/src/api/argument/Argument.js +0 -0
- package/dist/src/api/argument/ArgumentValueTypes.js +18 -0
- package/dist/src/api/argument/ComplexOption.js +1 -0
- package/dist/src/api/argument/GlobalCommandArgument.js +0 -0
- package/dist/src/api/argument/Option.js +0 -0
- package/dist/src/api/argument/Positional.js +0 -0
- package/dist/src/api/argument/SubCommandArgument.js +1 -0
- package/dist/src/api/command/Command.js +0 -0
- package/dist/src/api/command/GlobalCommand.js +0 -0
- package/dist/src/api/command/GlobalModifierCommand.js +0 -0
- package/dist/src/api/command/GroupCommand.js +0 -0
- package/dist/src/api/command/SubCommand.js +0 -0
- package/dist/src/api/command/UsageExample.js +0 -0
- package/dist/src/api/plugin/CLIPlugin.js +2 -0
- package/dist/src/api/plugin/CommandFactory.js +7 -0
- package/dist/src/api/plugin/ServiceProviderFactory.js +7 -0
- package/dist/src/api/plugin/createCLIPlugin.js +30 -0
- package/dist/src/api/service/ServiceProvider.js +0 -0
- package/dist/src/api/service/core/ArgumentPrompterService.js +1 -0
- package/dist/src/api/service/core/AsciiBannerGeneratorService.js +1 -0
- package/dist/src/api/service/core/CompletionService.js +8 -0
- package/dist/src/api/service/core/DataDumpGeneratorService.js +7 -0
- package/dist/src/api/service/core/ImagePrinterService.js +1 -0
- package/dist/src/api/service/core/KeyValueService.js +7 -0
- package/dist/src/api/service/core/PluginService.js +6 -0
- package/dist/src/api/service/core/PrettyPrinterService.js +1 -0
- package/dist/src/api/service/core/PrinterService.js +42 -0
- package/dist/src/api/service/core/PrompterService.js +10 -0
- package/dist/src/api/service/core/SecretService.js +0 -0
- package/dist/src/api/service/core/ShutdownService.js +1 -0
- package/dist/src/api/service/core/SyntaxHighlighterService.js +1 -0
- package/dist/src/api/service/core/Table.js +49 -0
- package/dist/src/api/service/core/TableGeneratorService.d.ts +1 -0
- package/dist/src/api/service/core/TableGeneratorService.d.ts.map +1 -1
- package/dist/src/api/service/core/TableGeneratorService.js +7 -0
- package/dist/src/api/service/core/TreePrinterService.js +1 -0
- package/dist/src/cli/BaseCLI.d.ts.map +1 -1
- package/dist/src/cli/BaseCLI.js +232 -0
- package/dist/src/cli/DefaultRuntimeCLI.js +20 -0
- package/dist/src/cli/DynamicPluginRuntimeCLI.js +50 -0
- package/dist/src/command/MultiCommandCliHelpCommand.js +238 -0
- package/dist/src/command/SingleCommandCliHelpCommand.js +104 -0
- package/dist/src/command/UsageCommand.js +16 -0
- package/dist/src/command/VersionCommand.js +13 -0
- package/dist/src/launcher.js +61 -0
- package/dist/src/runtime/DefaultContext.js +25 -0
- package/dist/src/runtime/argument/ArgumentTypeGuards.js +3 -0
- package/dist/src/runtime/command/CommandTypeGuards.js +12 -0
- package/dist/src/runtime/command/CommandValidator.js +371 -0
- package/dist/src/runtime/parser.js +105 -0
- package/dist/src/runtime/registry/CommandRegistry.js +0 -0
- package/dist/src/runtime/registry/DefaultCommandRegistry.js +190 -0
- package/dist/src/runtime/registry/DefaultServiceProviderRegistry.js +20 -0
- package/dist/src/runtime/registry/ServiceProviderRegistry.js +0 -0
- package/dist/src/runtime/runner.js +507 -0
- package/dist/src/runtime/scanner.js +244 -0
- package/dist/src/runtime/values/ValuePopulationResult.js +0 -0
- package/dist/src/runtime/values/argumentValueMerge.js +122 -0
- package/dist/src/runtime/values/argumentValueValidation.js +505 -0
- package/dist/src/runtime/values/globalCommandValuePopulation.js +67 -0
- package/dist/src/runtime/values/subCommandValuePopulation.js +549 -0
- package/dist/src/service/argumentPrompter/ArgumentPrompterServiceProvider.js +19 -0
- package/dist/src/service/argumentPrompter/DefaultArgumentPrompterService.js +197 -0
- package/dist/src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.js +28 -0
- package/dist/src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.js +233 -0
- package/dist/src/service/asciiBannerGenerator/standard.flf.json +3 -0
- package/dist/src/service/banner/BannerServiceProvider.js +60 -0
- package/dist/src/service/banner/command/NoBannerCommand.js +24 -0
- package/dist/src/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.js +51 -0
- package/dist/src/service/chiselAsciiBannerGenerator/chisel.flf.json +3 -0
- package/dist/src/service/completion/CompletionServiceProvider.d.ts +2 -1
- package/dist/src/service/completion/CompletionServiceProvider.d.ts.map +1 -1
- package/dist/src/service/completion/CompletionServiceProvider.js +159 -0
- package/dist/src/service/completion/DefaultCompletionService.js +279 -0
- package/dist/src/service/completion/command/CompletionCompleteSubCommand.d.ts +15 -0
- package/dist/src/service/completion/command/CompletionCompleteSubCommand.d.ts.map +1 -0
- package/dist/src/service/completion/command/CompletionCompleteSubCommand.js +37 -0
- package/dist/src/service/completion/command/CompletionGroupCommand.d.ts +14 -0
- package/dist/src/service/completion/command/CompletionGroupCommand.d.ts.map +1 -0
- package/dist/src/service/completion/command/CompletionGroupCommand.js +10 -0
- package/dist/src/service/completion/command/CompletionIntegrationSubCommand.d.ts +14 -0
- package/dist/src/service/completion/command/CompletionIntegrationSubCommand.d.ts.map +1 -0
- package/dist/src/service/completion/command/CompletionIntegrationSubCommand.js +67 -0
- package/dist/src/service/completion/shell/ShellHandler.js +0 -0
- package/dist/src/service/completion/shell/bash.js +39 -0
- package/dist/src/service/completion/shell/fish.js +35 -0
- package/dist/src/service/completion/shell/powershell.js +51 -0
- package/dist/src/service/completion/shell/zsh.js +42 -0
- package/dist/src/service/configuration/ConfigurationServiceProvider.js +482 -0
- package/dist/src/service/configuration/DefaultKeyValueService.js +80 -0
- package/dist/src/service/configuration/DefaultSecretService.js +60 -0
- package/dist/src/service/configuration/command/ConfigCommand.js +24 -0
- package/dist/src/service/configuration/command/DumpConfigCommand.js +18 -0
- package/dist/src/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.js +24 -0
- package/dist/src/service/dataDumpGenerator/DefaultDataDumpGeneratorService.js +59 -0
- package/dist/src/service/imagePrinter/DefaultImagePrinterService.js +10 -0
- package/dist/src/service/imagePrinter/ImagePrinterServiceProvider.js +20 -0
- package/dist/src/service/plugin/DefaultPluginService.js +21 -0
- package/dist/src/service/plugin/DefaultPluginServiceProvider.d.ts +1 -1
- package/dist/src/service/plugin/DefaultPluginServiceProvider.d.ts.map +1 -1
- package/dist/src/service/plugin/DefaultPluginServiceProvider.js +21 -0
- package/dist/src/service/plugin/command/PluginAddSubCommand.d.ts +17 -0
- package/dist/src/service/plugin/command/PluginAddSubCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginAddSubCommand.js +49 -0
- package/dist/src/service/plugin/command/PluginGroupCommand.d.ts +12 -0
- package/dist/src/service/plugin/command/PluginGroupCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginGroupCommand.js +21 -0
- package/dist/src/service/plugin/command/PluginListSubCommand.d.ts +12 -0
- package/dist/src/service/plugin/command/PluginListSubCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginListSubCommand.js +25 -0
- package/dist/src/service/plugin/command/PluginRemoveSubCommand.d.ts +17 -0
- package/dist/src/service/plugin/command/PluginRemoveSubCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginRemoveSubCommand.js +24 -0
- package/dist/src/service/plugin/command/PluginSearchSubCommand.d.ts +18 -0
- package/dist/src/service/plugin/command/PluginSearchSubCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginSearchSubCommand.js +34 -0
- package/dist/src/service/plugin/command/PluginUpgradeSubCommand.d.ts +12 -0
- package/dist/src/service/plugin/command/PluginUpgradeSubCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginUpgradeSubCommand.js +25 -0
- package/dist/src/service/plugin/command/getPluginId.d.ts +3 -0
- package/dist/src/service/plugin/command/getPluginId.d.ts.map +1 -0
- package/dist/src/service/plugin/command/getPluginId.js +3 -0
- package/dist/src/service/prettyPrinter/DefaultPrettyPrinterService.js +45 -0
- package/dist/src/service/prettyPrinter/PrettyPrinterServiceProvider.js +28 -0
- package/dist/src/service/printer/DefaultPrinterService.js +250 -0
- package/dist/src/service/printer/PrinterServiceProvider.js +43 -0
- package/dist/src/service/printer/command/DarkModeCommand.js +24 -0
- package/dist/src/service/printer/command/LogLevelCommand.js +41 -0
- package/dist/src/service/printer/command/NoColorCommand.js +24 -0
- package/dist/src/service/printer/command/NoHyperlinksCommand.js +21 -0
- package/dist/src/service/printer/terminal/Color.js +15 -0
- package/dist/src/service/printer/terminal/Progress.js +271 -0
- package/dist/src/service/printer/terminal/Spinner.js +83 -0
- package/dist/src/service/printer/terminal/Theme.js +26 -0
- package/dist/src/service/prompter/DefaultPrompterService.js +52 -0
- package/dist/src/service/prompter/PrompterServiceProvider.js +20 -0
- package/dist/src/service/prompter/command/NoPromptCommand.js +21 -0
- package/dist/src/service/prompter/prompt/PromptContext.js +22 -0
- package/dist/src/service/prompter/prompt/promptAcknowledge.js +19 -0
- package/dist/src/service/prompter/prompt/promptMultiSelect.js +74 -0
- package/dist/src/service/prompter/prompt/promptOpenUrl.js +70 -0
- package/dist/src/service/prompter/prompt/promptSingleSelect.js +73 -0
- package/dist/src/service/prompter/prompt/promptText.js +75 -0
- package/dist/src/service/prompter/prompt/promptToggle.js +21 -0
- package/dist/src/service/shutdown/DefaultShutdownService.js +16 -0
- package/dist/src/service/shutdown/ShutdownServiceProvider.js +60 -0
- package/dist/src/service/shutdown/ShutdownState.js +5 -0
- package/dist/src/service/syntaxHighlighter/DefaultSyntaxHighlighterService.js +54 -0
- package/dist/src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.js +32 -0
- package/dist/src/service/tableGenerator/DefaultTableGeneratorService.d.ts +3 -1
- package/dist/src/service/tableGenerator/DefaultTableGeneratorService.d.ts.map +1 -1
- package/dist/src/service/tableGenerator/DefaultTableGeneratorService.js +344 -0
- package/dist/src/service/tableGenerator/TableGeneratorServiceProvider.js +26 -0
- package/dist/src/service/treePrinter/DefaultTreePrinterService.js +35 -0
- package/dist/src/service/treePrinter/TreePrinterServiceProvider.js +24 -0
- package/dist/src/terminal/Ansi.js +23 -0
- package/dist/src/terminal/ImageRenderer.d.ts.map +1 -1
- package/dist/src/terminal/ImageRenderer.js +166 -0
- package/dist/src/terminal/KeyReader.js +13 -0
- package/dist/src/terminal/PngDecoder.js +115 -0
- package/dist/src/terminal/Styler.js +0 -0
- package/dist/src/terminal/Terminal.js +0 -0
- package/dist/src/terminal/TtyKeyReader.js +87 -0
- package/dist/src/terminal/TtyStyler.js +55 -0
- package/dist/src/terminal/TtyTerminal.js +52 -0
- package/dist/src/terminal/supportsHyperlinks.js +95 -0
- package/dist/src/util/configHelper.js +61 -0
- package/dist/src/util/envVarHelper.js +216 -0
- package/dist/src/util/helpHelper.d.ts.map +1 -1
- package/dist/src/util/helpHelper.js +497 -0
- package/dist/src/util/logger.js +81 -0
- package/dist/src/util/runnerHelper.js +80 -0
- package/package.json +2 -2
- package/src/api/service/core/TableGeneratorService.ts +1 -0
- package/src/cli/BaseCLI.ts +4 -19
- package/src/service/completion/CompletionServiceProvider.ts +16 -3
- package/src/service/completion/command/CompletionCompleteSubCommand.ts +59 -0
- package/src/service/completion/command/CompletionGroupCommand.ts +21 -0
- package/src/{command/CompletionCommand.ts → service/completion/command/CompletionIntegrationSubCommand.ts} +12 -73
- package/src/service/completion/shell/bash.ts +1 -1
- package/src/service/completion/shell/fish.ts +1 -1
- package/src/service/completion/shell/powershell.ts +1 -1
- package/src/service/completion/shell/zsh.ts +1 -1
- package/src/service/plugin/DefaultPluginServiceProvider.ts +2 -2
- package/src/service/plugin/command/PluginAddSubCommand.ts +64 -0
- package/src/service/plugin/command/PluginGroupCommand.ts +27 -0
- package/src/service/plugin/command/PluginListSubCommand.ts +33 -0
- package/src/service/plugin/command/PluginRemoveSubCommand.ts +32 -0
- package/src/service/plugin/command/PluginSearchSubCommand.ts +42 -0
- package/src/service/plugin/command/PluginUpgradeSubCommand.ts +36 -0
- package/src/service/plugin/command/getPluginId.ts +5 -0
- package/src/service/tableGenerator/DefaultTableGeneratorService.ts +6 -1
- package/src/terminal/ImageRenderer.ts +7 -5
- package/src/util/helpHelper.ts +1 -2
- package/dist/src/command/CompletionCommand.d.ts +0 -32
- package/dist/src/command/CompletionCommand.d.ts.map +0 -1
- package/dist/src/command/PluginCommand.d.ts +0 -67
- package/dist/src/command/PluginCommand.d.ts.map +0 -1
- package/dist/tests/cli/BaseCLI.test.d.ts +0 -2
- package/dist/tests/cli/BaseCLI.test.d.ts.map +0 -1
- package/dist/tests/cli/DynamicPluginRuntimeCLI.test.d.ts +0 -2
- package/dist/tests/cli/DynamicPluginRuntimeCLI.test.d.ts.map +0 -1
- package/dist/tests/command/CompletionCommand.test.d.ts +0 -2
- package/dist/tests/command/CompletionCommand.test.d.ts.map +0 -1
- package/dist/tests/command/MultiCommandCliHelpCommand.test.d.ts +0 -2
- package/dist/tests/command/MultiCommandCliHelpCommand.test.d.ts.map +0 -1
- package/dist/tests/command/PluginCommand.test.d.ts +0 -2
- package/dist/tests/command/PluginCommand.test.d.ts.map +0 -1
- package/dist/tests/command/SingleCommandCliHelpCommand.test.d.ts +0 -2
- package/dist/tests/command/SingleCommandCliHelpCommand.test.d.ts.map +0 -1
- package/dist/tests/command/UsageCommand.test.d.ts +0 -2
- package/dist/tests/command/UsageCommand.test.d.ts.map +0 -1
- package/dist/tests/command/VersionCommand.test.d.ts +0 -2
- package/dist/tests/command/VersionCommand.test.d.ts.map +0 -1
- package/dist/tests/fixtures/CLIConfig.d.ts +0 -3
- package/dist/tests/fixtures/CLIConfig.d.ts.map +0 -1
- package/dist/tests/fixtures/Command.d.ts +0 -20
- package/dist/tests/fixtures/Command.d.ts.map +0 -1
- package/dist/tests/fixtures/CommandRegistry.d.ts +0 -4
- package/dist/tests/fixtures/CommandRegistry.d.ts.map +0 -1
- package/dist/tests/fixtures/ConfigurationServiceProvider.d.ts +0 -10
- package/dist/tests/fixtures/ConfigurationServiceProvider.d.ts.map +0 -1
- package/dist/tests/fixtures/Context.d.ts +0 -4
- package/dist/tests/fixtures/Context.d.ts.map +0 -1
- package/dist/tests/fixtures/ServiceProviderRegistry.d.ts +0 -4
- package/dist/tests/fixtures/ServiceProviderRegistry.d.ts.map +0 -1
- package/dist/tests/fixtures/StreamString.d.ts +0 -10
- package/dist/tests/fixtures/StreamString.d.ts.map +0 -1
- package/dist/tests/fixtures/prettierPluginFoo.d.ts +0 -4
- package/dist/tests/fixtures/prettierPluginFoo.d.ts.map +0 -1
- package/dist/tests/fixtures/util.d.ts +0 -8
- package/dist/tests/fixtures/util.d.ts.map +0 -1
- package/dist/tests/runtime/DefaultContext.test.d.ts +0 -2
- package/dist/tests/runtime/DefaultContext.test.d.ts.map +0 -1
- package/dist/tests/runtime/argument/ArgumentTypeGuards.test.d.ts +0 -2
- package/dist/tests/runtime/argument/ArgumentTypeGuards.test.d.ts.map +0 -1
- package/dist/tests/runtime/command/CommandTypeGuards.test.d.ts +0 -2
- package/dist/tests/runtime/command/CommandTypeGuards.test.d.ts.map +0 -1
- package/dist/tests/runtime/command/CommandValidator.test.d.ts +0 -2
- package/dist/tests/runtime/command/CommandValidator.test.d.ts.map +0 -1
- package/dist/tests/runtime/parser.test.d.ts +0 -2
- package/dist/tests/runtime/parser.test.d.ts.map +0 -1
- package/dist/tests/runtime/registry/DefaultCommandRegistry.test.d.ts +0 -2
- package/dist/tests/runtime/registry/DefaultCommandRegistry.test.d.ts.map +0 -1
- package/dist/tests/runtime/registry/DefaultServiceProviderRegistry.test.d.ts +0 -2
- package/dist/tests/runtime/registry/DefaultServiceProviderRegistry.test.d.ts.map +0 -1
- package/dist/tests/runtime/runner.test.d.ts +0 -2
- package/dist/tests/runtime/runner.test.d.ts.map +0 -1
- package/dist/tests/runtime/scanner.test.d.ts +0 -2
- package/dist/tests/runtime/scanner.test.d.ts.map +0 -1
- package/dist/tests/runtime/values/argumentValueMerge.test.d.ts +0 -2
- package/dist/tests/runtime/values/argumentValueMerge.test.d.ts.map +0 -1
- package/dist/tests/runtime/values/argumentValueValidation.test.d.ts +0 -2
- package/dist/tests/runtime/values/argumentValueValidation.test.d.ts.map +0 -1
- package/dist/tests/runtime/values/globalCommandValuePopulation.test.d.ts +0 -2
- package/dist/tests/runtime/values/globalCommandValuePopulation.test.d.ts.map +0 -1
- package/dist/tests/runtime/values/subCommandValuePopulation.test.d.ts +0 -2
- package/dist/tests/runtime/values/subCommandValuePopulation.test.d.ts.map +0 -1
- package/dist/tests/service/argumentPrompter/ArgumentPrompterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/argumentPrompter/ArgumentPrompterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/argumentPrompter/DefaultArgumentPrompterService.test.d.ts +0 -2
- package/dist/tests/service/argumentPrompter/DefaultArgumentPrompterService.test.d.ts.map +0 -1
- package/dist/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.d.ts +0 -2
- package/dist/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.d.ts.map +0 -1
- package/dist/tests/service/banner/BannerServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/banner/BannerServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/banner/command/NoBannerCommand.test.d.ts +0 -2
- package/dist/tests/service/banner/command/NoBannerCommand.test.d.ts.map +0 -1
- package/dist/tests/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.test.d.ts +0 -2
- package/dist/tests/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.test.d.ts.map +0 -1
- package/dist/tests/service/completion/CompletionServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/completion/CompletionServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/completion/DefaultCompletionService.test.d.ts +0 -2
- package/dist/tests/service/completion/DefaultCompletionService.test.d.ts.map +0 -1
- package/dist/tests/service/completion/shell/bash.test.d.ts +0 -2
- package/dist/tests/service/completion/shell/bash.test.d.ts.map +0 -1
- package/dist/tests/service/completion/shell/fish.test.d.ts +0 -2
- package/dist/tests/service/completion/shell/fish.test.d.ts.map +0 -1
- package/dist/tests/service/completion/shell/powershell.test.d.ts +0 -2
- package/dist/tests/service/completion/shell/powershell.test.d.ts.map +0 -1
- package/dist/tests/service/completion/shell/zsh.test.d.ts +0 -2
- package/dist/tests/service/completion/shell/zsh.test.d.ts.map +0 -1
- package/dist/tests/service/configuration/ConfigurationServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/configuration/ConfigurationServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/configuration/DefaultKeyValueService.test.d.ts +0 -2
- package/dist/tests/service/configuration/DefaultKeyValueService.test.d.ts.map +0 -1
- package/dist/tests/service/configuration/DefaultSecretService.test.d.ts +0 -2
- package/dist/tests/service/configuration/DefaultSecretService.test.d.ts.map +0 -1
- package/dist/tests/service/configuration/command/ConfigCommand.test.d.ts +0 -2
- package/dist/tests/service/configuration/command/ConfigCommand.test.d.ts.map +0 -1
- package/dist/tests/service/configuration/command/DumpConfigCommand.test.d.ts +0 -2
- package/dist/tests/service/configuration/command/DumpConfigCommand.test.d.ts.map +0 -1
- package/dist/tests/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/dataDumpGenerator/DefaultDataDumpGeneratorService.test.d.ts +0 -2
- package/dist/tests/service/dataDumpGenerator/DefaultDataDumpGeneratorService.test.d.ts.map +0 -1
- package/dist/tests/service/imagePrinter/DefaultImagePrinterService.test.d.ts +0 -2
- package/dist/tests/service/imagePrinter/DefaultImagePrinterService.test.d.ts.map +0 -1
- package/dist/tests/service/imagePrinter/ImagePrinterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/imagePrinter/ImagePrinterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/plugin/DefaultPluginServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/plugin/DefaultPluginServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/prettyPrinter/DefaultPrettyPrinterService.test.d.ts +0 -2
- package/dist/tests/service/prettyPrinter/DefaultPrettyPrinterService.test.d.ts.map +0 -1
- package/dist/tests/service/prettyPrinter/PrettyPrinterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/prettyPrinter/PrettyPrinterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/printer/DefaultPrinterService.test.d.ts +0 -2
- package/dist/tests/service/printer/DefaultPrinterService.test.d.ts.map +0 -1
- package/dist/tests/service/printer/PrinterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/printer/PrinterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/printer/command/DarkModeCommand.test.d.ts +0 -2
- package/dist/tests/service/printer/command/DarkModeCommand.test.d.ts.map +0 -1
- package/dist/tests/service/printer/command/LogLevelCommand.test.d.ts +0 -2
- package/dist/tests/service/printer/command/LogLevelCommand.test.d.ts.map +0 -1
- package/dist/tests/service/printer/command/NoColorCommand.test.d.ts +0 -2
- package/dist/tests/service/printer/command/NoColorCommand.test.d.ts.map +0 -1
- package/dist/tests/service/printer/command/NoHyperlinksCommand.test.d.ts +0 -2
- package/dist/tests/service/printer/command/NoHyperlinksCommand.test.d.ts.map +0 -1
- package/dist/tests/service/printer/terminal/Progress.test.d.ts +0 -2
- package/dist/tests/service/printer/terminal/Progress.test.d.ts.map +0 -1
- package/dist/tests/service/printer/terminal/Spinner.test.d.ts +0 -2
- package/dist/tests/service/printer/terminal/Spinner.test.d.ts.map +0 -1
- package/dist/tests/service/prompter/DefaultPrompterService.test.d.ts +0 -2
- package/dist/tests/service/prompter/DefaultPrompterService.test.d.ts.map +0 -1
- package/dist/tests/service/prompter/PrompterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/prompter/PrompterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/prompter/command/NoPromptCommand.test.d.ts +0 -2
- package/dist/tests/service/prompter/command/NoPromptCommand.test.d.ts.map +0 -1
- package/dist/tests/service/prompter/prompt/PromptContext.test.d.ts +0 -2
- package/dist/tests/service/prompter/prompt/PromptContext.test.d.ts.map +0 -1
- package/dist/tests/service/shutdown/ShutdownServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/shutdown/ShutdownServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.d.ts +0 -2
- package/dist/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.d.ts.map +0 -1
- package/dist/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/tableGenerator/DefaultTableGeneratorService.test.d.ts +0 -2
- package/dist/tests/service/tableGenerator/DefaultTableGeneratorService.test.d.ts.map +0 -1
- package/dist/tests/service/tableGenerator/TableGeneratorServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/tableGenerator/TableGeneratorServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/treePrinter/DefaultTreePrinterService.test.d.ts +0 -2
- package/dist/tests/service/treePrinter/DefaultTreePrinterService.test.d.ts.map +0 -1
- package/dist/tests/service/treePrinter/TreePrinterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/treePrinter/TreePrinterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/terminal/ImageRenderer.test.d.ts +0 -2
- package/dist/tests/terminal/ImageRenderer.test.d.ts.map +0 -1
- package/dist/tests/terminal/PngDecoder.test.d.ts +0 -2
- package/dist/tests/terminal/PngDecoder.test.d.ts.map +0 -1
- package/dist/tests/terminal/supportsHyperlinks.test.d.ts +0 -2
- package/dist/tests/terminal/supportsHyperlinks.test.d.ts.map +0 -1
- package/dist/tests/util/configHelper.test.d.ts +0 -2
- package/dist/tests/util/configHelper.test.d.ts.map +0 -1
- package/dist/tests/util/envVarHelper.test.d.ts +0 -2
- package/dist/tests/util/envVarHelper.test.d.ts.map +0 -1
- package/dist/tests/util/logger.test.d.ts +0 -2
- package/dist/tests/util/logger.test.d.ts.map +0 -1
- package/src/command/PluginCommand.ts +0 -197
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
const RATE_SMOOTHING_FACTOR = 0.005;
|
|
2
|
+
export { ProgressStyle } from "../../../api/service/core/PrinterService.js";
|
|
3
|
+
import { ProgressStyle } from "../../../api/service/core/PrinterService.js";
|
|
4
|
+
const STYLE_CHARS = {
|
|
5
|
+
[ProgressStyle.STROKE]: { complete: "=", remaining: "-" },
|
|
6
|
+
[ProgressStyle.FILL]: { complete: "▰", remaining: "▱" },
|
|
7
|
+
};
|
|
8
|
+
export default class Progress {
|
|
9
|
+
#terminal;
|
|
10
|
+
#styler;
|
|
11
|
+
#bars = new Map();
|
|
12
|
+
#timer;
|
|
13
|
+
#isDirty = false;
|
|
14
|
+
#currentRenderedBarCount = 0;
|
|
15
|
+
#lastRenderTime = 0;
|
|
16
|
+
#comColor = 0x5f8700;
|
|
17
|
+
#remColor = 0x585858;
|
|
18
|
+
#labColor = 0x585858;
|
|
19
|
+
#valColor = 0x808080;
|
|
20
|
+
#style = ProgressStyle.STROKE;
|
|
21
|
+
constructor(terminal, styler) {
|
|
22
|
+
this.#terminal = terminal;
|
|
23
|
+
this.#styler = styler;
|
|
24
|
+
}
|
|
25
|
+
add(units, message, total, current) {
|
|
26
|
+
if (total < 0) {
|
|
27
|
+
total = 100;
|
|
28
|
+
}
|
|
29
|
+
if (current < 0) {
|
|
30
|
+
current = 0;
|
|
31
|
+
}
|
|
32
|
+
if (current > total) {
|
|
33
|
+
current = total;
|
|
34
|
+
}
|
|
35
|
+
this.#bars.set(this.#bars.size + 1, {
|
|
36
|
+
name: message,
|
|
37
|
+
current,
|
|
38
|
+
total,
|
|
39
|
+
units,
|
|
40
|
+
startMillis: Date.now(),
|
|
41
|
+
});
|
|
42
|
+
// force render on next timeout
|
|
43
|
+
this.#isDirty = true;
|
|
44
|
+
// start rendering timer
|
|
45
|
+
if (this.#timer === undefined) {
|
|
46
|
+
this.#timer = setInterval(async () => {
|
|
47
|
+
await this.#renderBars();
|
|
48
|
+
}, 100);
|
|
49
|
+
}
|
|
50
|
+
return this.#bars.size;
|
|
51
|
+
}
|
|
52
|
+
#updateRate(bar, current) {
|
|
53
|
+
const now = Date.now();
|
|
54
|
+
if (bar.lastMillis === undefined) {
|
|
55
|
+
bar.rate = ((current - bar.current) * 1000) / (now - bar.startMillis);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
let currentRate = ((current - bar.current) * 1000) / (now - bar.lastMillis);
|
|
59
|
+
if (!isFinite(currentRate)) {
|
|
60
|
+
currentRate = 0;
|
|
61
|
+
}
|
|
62
|
+
bar.rate = currentRate * RATE_SMOOTHING_FACTOR + bar.rate * (1 - RATE_SMOOTHING_FACTOR);
|
|
63
|
+
}
|
|
64
|
+
bar.lastMillis = now;
|
|
65
|
+
}
|
|
66
|
+
update(handle, current, message) {
|
|
67
|
+
if (!this.#bars.has(handle)) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const bar = this.#bars.get(handle);
|
|
71
|
+
if (current < 0) {
|
|
72
|
+
current = 0;
|
|
73
|
+
}
|
|
74
|
+
if (current > bar.total) {
|
|
75
|
+
current = bar.total;
|
|
76
|
+
}
|
|
77
|
+
if (current === bar.total && bar.endMillis === undefined) {
|
|
78
|
+
bar.endMillis = Date.now();
|
|
79
|
+
}
|
|
80
|
+
this.#updateRate(bar, current);
|
|
81
|
+
bar.current = current;
|
|
82
|
+
if (message !== undefined) {
|
|
83
|
+
bar.name = message;
|
|
84
|
+
}
|
|
85
|
+
// force render on next timeout
|
|
86
|
+
this.#isDirty = true;
|
|
87
|
+
}
|
|
88
|
+
async hide(handle) {
|
|
89
|
+
// clear specified bar
|
|
90
|
+
if (this.#bars.has(handle)) {
|
|
91
|
+
this.#bars.delete(handle);
|
|
92
|
+
}
|
|
93
|
+
// if no more bars, effectively this is a pause
|
|
94
|
+
if (this.#bars.size === 0) {
|
|
95
|
+
await this.pause();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// otherwise, force render on next timeout
|
|
99
|
+
this.#isDirty = true;
|
|
100
|
+
}
|
|
101
|
+
async hideAll() {
|
|
102
|
+
// clear all bars
|
|
103
|
+
this.#bars.clear();
|
|
104
|
+
await this.pause();
|
|
105
|
+
}
|
|
106
|
+
async pause() {
|
|
107
|
+
if (this.#timer === undefined) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
this.#isDirty = false;
|
|
111
|
+
// stop rendering timer
|
|
112
|
+
clearInterval(this.#timer);
|
|
113
|
+
this.#timer = undefined;
|
|
114
|
+
// clear the previously rendered bars
|
|
115
|
+
await this.#terminal.clearUpLines(this.#currentRenderedBarCount * 2);
|
|
116
|
+
this.#currentRenderedBarCount = 0;
|
|
117
|
+
// restore the cursor
|
|
118
|
+
await this.#terminal.showCursor();
|
|
119
|
+
}
|
|
120
|
+
resume() {
|
|
121
|
+
// don't resume if nothing to render
|
|
122
|
+
if (this.#bars.size === 0) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// force render on next timeout
|
|
126
|
+
this.#isDirty = true;
|
|
127
|
+
// start rendering timer
|
|
128
|
+
if (this.#timer === undefined) {
|
|
129
|
+
this.#timer = setInterval(async () => {
|
|
130
|
+
await this.#renderBars();
|
|
131
|
+
}, 100);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async #renderBars() {
|
|
135
|
+
const now = Date.now();
|
|
136
|
+
// force render after one second to update newly calculated eta
|
|
137
|
+
if (now - this.#lastRenderTime >= 1000 && !this.#isDirty) {
|
|
138
|
+
this.#bars.forEach((bar) => this.#updateRate(bar, bar.current));
|
|
139
|
+
this.#isDirty = true;
|
|
140
|
+
}
|
|
141
|
+
// don't render if we don't need to
|
|
142
|
+
if (!this.#isDirty) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
this.#lastRenderTime = now;
|
|
146
|
+
const consoleWidth = this.#terminal.columns();
|
|
147
|
+
const lines = [];
|
|
148
|
+
const barInfo = [];
|
|
149
|
+
this.#bars.forEach((bar) => {
|
|
150
|
+
const name = `${this.#styler.colorText(bar.name, this.#valColor)}${this.#styler.colorText(":", this.#labColor)}`;
|
|
151
|
+
const prefix = `${this.#styler.colorText("[", this.#labColor)}`;
|
|
152
|
+
let visibleWidth = 1;
|
|
153
|
+
const percentString = ((bar.current / bar.total) * 100).toFixed(2);
|
|
154
|
+
const percent = this.#styler.colorText(percentString, this.#valColor) +
|
|
155
|
+
this.#styler.colorText("%,", this.#labColor);
|
|
156
|
+
visibleWidth += percentString.length + 1;
|
|
157
|
+
const rateText = bar.rate === undefined ? "-" : bar.rate.toFixed(2) + "";
|
|
158
|
+
const rate = `${this.#styler.colorText(rateText, this.#valColor)}`;
|
|
159
|
+
let suffix = `${this.#styler.colorText("]", this.#labColor)} ${percent} `;
|
|
160
|
+
visibleWidth += 3;
|
|
161
|
+
if (bar.current === bar.total) {
|
|
162
|
+
const taken = this.#formatTime(bar.endMillis - bar.startMillis);
|
|
163
|
+
const totalString = bar.total + "";
|
|
164
|
+
suffix += `${this.#styler.colorText(totalString, this.#valColor)}${this.#styler.colorText(bar.units + ", rate:", this.#labColor)} ${rate}${this.#styler.colorText(bar.units + "/s, time taken:", this.#labColor)} ${taken}`;
|
|
165
|
+
visibleWidth +=
|
|
166
|
+
totalString.length +
|
|
167
|
+
bar.units.length +
|
|
168
|
+
7 +
|
|
169
|
+
1 +
|
|
170
|
+
rateText.length +
|
|
171
|
+
bar.units.length +
|
|
172
|
+
15 +
|
|
173
|
+
1 +
|
|
174
|
+
taken.length;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
const remaining = bar.rate === undefined || bar.rate === 0
|
|
178
|
+
? "-"
|
|
179
|
+
: this.#formatTime(((bar.total - bar.current) / bar.rate) * 1000);
|
|
180
|
+
const currentString = bar.current + "";
|
|
181
|
+
const totalString = bar.total + "";
|
|
182
|
+
suffix += `${this.#styler.colorText(currentString, this.#valColor)}${this.#styler.colorText("/", this.#labColor)}${this.#styler.colorText(totalString, this.#valColor)}${this.#styler.colorText(bar.units + ", rate:", this.#labColor)} ${rate}${this.#styler.colorText(bar.units + "/s, time remaining:", this.#labColor)} ${remaining}`;
|
|
183
|
+
visibleWidth +=
|
|
184
|
+
currentString.length +
|
|
185
|
+
1 +
|
|
186
|
+
totalString.length +
|
|
187
|
+
bar.units.length +
|
|
188
|
+
7 +
|
|
189
|
+
1 +
|
|
190
|
+
rateText.length +
|
|
191
|
+
bar.units.length +
|
|
192
|
+
19 +
|
|
193
|
+
1 +
|
|
194
|
+
remaining.length;
|
|
195
|
+
}
|
|
196
|
+
let available = consoleWidth - visibleWidth;
|
|
197
|
+
if (available < 0) {
|
|
198
|
+
available = 0;
|
|
199
|
+
}
|
|
200
|
+
barInfo.push({
|
|
201
|
+
name,
|
|
202
|
+
prefix,
|
|
203
|
+
available,
|
|
204
|
+
suffix,
|
|
205
|
+
bar,
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
let totalLength = consoleWidth;
|
|
209
|
+
barInfo.forEach((barInfo) => {
|
|
210
|
+
if (barInfo.available < totalLength) {
|
|
211
|
+
totalLength = barInfo.available;
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
totalLength = Math.min(50, totalLength);
|
|
215
|
+
barInfo.forEach((barInfo) => {
|
|
216
|
+
const completeLength = Math.floor((totalLength * barInfo.bar.current) / barInfo.bar.total);
|
|
217
|
+
const chars = STYLE_CHARS[this.#style];
|
|
218
|
+
const complete = this.#styler.colorText(chars.complete.repeat(completeLength), this.#comColor);
|
|
219
|
+
const remaining = this.#styler.colorText(chars.remaining.repeat(totalLength - completeLength), this.#remColor);
|
|
220
|
+
lines.push(barInfo.name);
|
|
221
|
+
lines.push(barInfo.prefix + complete + remaining + barInfo.suffix);
|
|
222
|
+
});
|
|
223
|
+
// hide the cursor before rendering
|
|
224
|
+
await this.#terminal.hideCursor();
|
|
225
|
+
// clear the previously rendered bars
|
|
226
|
+
await this.#terminal.clearUpLines(this.#currentRenderedBarCount * 2);
|
|
227
|
+
// rendere the new bars
|
|
228
|
+
await this.#terminal.write(lines.join("\n") + "\n");
|
|
229
|
+
// save count rendered bars so we can clear on the next render cycle
|
|
230
|
+
this.#currentRenderedBarCount = barInfo.length;
|
|
231
|
+
// show the cursor if there are no bars or the timer is not running
|
|
232
|
+
if (this.#bars.size === 0 || this.#timer === undefined) {
|
|
233
|
+
await this.#terminal.showCursor();
|
|
234
|
+
}
|
|
235
|
+
this.#isDirty = false;
|
|
236
|
+
}
|
|
237
|
+
set completeColor(color) {
|
|
238
|
+
this.#comColor = color;
|
|
239
|
+
}
|
|
240
|
+
set remainingColor(color) {
|
|
241
|
+
this.#remColor = color;
|
|
242
|
+
}
|
|
243
|
+
set labelColor(color) {
|
|
244
|
+
this.#labColor = color;
|
|
245
|
+
}
|
|
246
|
+
set valueColor(color) {
|
|
247
|
+
this.#valColor = color;
|
|
248
|
+
}
|
|
249
|
+
set progressStyle(style) {
|
|
250
|
+
this.#style = style;
|
|
251
|
+
}
|
|
252
|
+
#formatTime(millis) {
|
|
253
|
+
let sec = millis / 1000;
|
|
254
|
+
if (sec < 60) {
|
|
255
|
+
return `${this.#styler.colorText(sec.toFixed(0), this.#valColor)}${this.#styler.colorText("s", this.#labColor)}`;
|
|
256
|
+
}
|
|
257
|
+
let min = Math.floor(sec / 60);
|
|
258
|
+
sec %= 60;
|
|
259
|
+
if (min < 60) {
|
|
260
|
+
return `${this.#styler.colorText(min.toFixed(0), this.#valColor)}${this.#styler.colorText("m", this.#labColor)} ${this.#styler.colorText(sec.toFixed(0), this.#valColor)}${this.#styler.colorText("s", this.#labColor)}`;
|
|
261
|
+
}
|
|
262
|
+
let hour = Math.floor(min / 60);
|
|
263
|
+
min %= 60;
|
|
264
|
+
if (hour < 24) {
|
|
265
|
+
return `${this.#styler.colorText(hour.toFixed(0), this.#valColor)}${this.#styler.colorText("h", this.#labColor)} ${this.#styler.colorText(min.toFixed(0), this.#valColor)}${this.#styler.colorText("m", this.#labColor)} ${this.#styler.colorText(sec.toFixed(0), this.#valColor)}${this.#styler.colorText("s", this.#labColor)}`;
|
|
266
|
+
}
|
|
267
|
+
const day = Math.floor(hour / 24);
|
|
268
|
+
hour %= 24;
|
|
269
|
+
return `${this.#styler.colorText(day.toFixed(0), this.#valColor)}${this.#styler.colorText("d", this.#labColor)} ${this.#styler.colorText(hour.toFixed(0), this.#valColor)}${this.#styler.colorText("h", this.#labColor)} ${this.#styler.colorText(min.toFixed(0), this.#valColor)}${this.#styler.colorText("m", this.#labColor)} ${this.#styler.colorText(sec.toFixed(0), this.#valColor)}${this.#styler.colorText("s", this.#labColor)}`;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const BOX_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
2
|
+
const STAR_FRAMES = ["★", "✶", "✷", "✹", "✷", "✶", "★", "✦"];
|
|
3
|
+
export { SpinnerStyle } from "../../../api/service/core/PrinterService.js";
|
|
4
|
+
import { SpinnerStyle } from "../../../api/service/core/PrinterService.js";
|
|
5
|
+
export default class Spinner {
|
|
6
|
+
#isShown = false;
|
|
7
|
+
#message;
|
|
8
|
+
#frameIndex = 0;
|
|
9
|
+
#timer;
|
|
10
|
+
#spinColor = 0x8a8a8a;
|
|
11
|
+
#msgColor = 0x808080;
|
|
12
|
+
#style = SpinnerStyle.BOX;
|
|
13
|
+
#terminal;
|
|
14
|
+
#styler;
|
|
15
|
+
constructor(terminal, styler) {
|
|
16
|
+
this.#terminal = terminal;
|
|
17
|
+
this.#styler = styler;
|
|
18
|
+
}
|
|
19
|
+
get #frames() {
|
|
20
|
+
return this.#style === SpinnerStyle.STAR ? STAR_FRAMES : BOX_FRAMES;
|
|
21
|
+
}
|
|
22
|
+
async #nextFrame() {
|
|
23
|
+
if (!this.#isShown) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const frames = this.#frames;
|
|
27
|
+
await this.#terminal.clearLine();
|
|
28
|
+
if (this.#message) {
|
|
29
|
+
await this.#terminal.write(`${this.#styler.colorText(frames[this.#frameIndex], this.#spinColor)} ${this.#styler.colorText(this.#message, this.#msgColor)}`);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
await this.#terminal.write(this.#styler.colorText(frames[this.#frameIndex], this.#spinColor));
|
|
33
|
+
}
|
|
34
|
+
this.#frameIndex = (this.#frameIndex + 1) % frames.length;
|
|
35
|
+
}
|
|
36
|
+
async show(message) {
|
|
37
|
+
this.#message = message;
|
|
38
|
+
if (this.#isShown) {
|
|
39
|
+
return Promise.resolve();
|
|
40
|
+
}
|
|
41
|
+
this.#isShown = true;
|
|
42
|
+
this.#frameIndex = 0;
|
|
43
|
+
this.#timer = setInterval(async () => {
|
|
44
|
+
await this.#nextFrame();
|
|
45
|
+
}, 100);
|
|
46
|
+
await this.#terminal.hideCursor();
|
|
47
|
+
}
|
|
48
|
+
async hide() {
|
|
49
|
+
if (!this.#isShown) {
|
|
50
|
+
return Promise.resolve();
|
|
51
|
+
}
|
|
52
|
+
this.#isShown = false;
|
|
53
|
+
clearInterval(this.#timer);
|
|
54
|
+
await this.#terminal.clearLine();
|
|
55
|
+
await this.#terminal.showCursor();
|
|
56
|
+
this.#message = undefined;
|
|
57
|
+
}
|
|
58
|
+
async pause() {
|
|
59
|
+
if (!this.#isShown) {
|
|
60
|
+
return Promise.resolve();
|
|
61
|
+
}
|
|
62
|
+
clearInterval(this.#timer);
|
|
63
|
+
this.#timer = undefined;
|
|
64
|
+
await this.#terminal.clearLine();
|
|
65
|
+
}
|
|
66
|
+
resume() {
|
|
67
|
+
if (!this.#isShown || this.#timer !== undefined) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
this.#timer = setInterval(async () => {
|
|
71
|
+
await this.#nextFrame();
|
|
72
|
+
}, 100);
|
|
73
|
+
}
|
|
74
|
+
set spinnerColor(color) {
|
|
75
|
+
this.#spinColor = color;
|
|
76
|
+
}
|
|
77
|
+
set messageColor(color) {
|
|
78
|
+
this.#msgColor = color;
|
|
79
|
+
}
|
|
80
|
+
set spinnerStyle(style) {
|
|
81
|
+
this.#style = style;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Color } from "./Color.js";
|
|
2
|
+
const commonTheme = [];
|
|
3
|
+
commonTheme[Color.YELLOW] = 0xb58900;
|
|
4
|
+
commonTheme[Color.ORANGE] = 0xcb4b16;
|
|
5
|
+
commonTheme[Color.RED] = 0xdc322f;
|
|
6
|
+
commonTheme[Color.MAGENTA] = 0xd33682;
|
|
7
|
+
commonTheme[Color.VIOLET] = 0x6c71c4;
|
|
8
|
+
commonTheme[Color.BLUE] = 0x268bd2;
|
|
9
|
+
commonTheme[Color.CYAN] = 0x2aa198;
|
|
10
|
+
commonTheme[Color.GREEN] = 0x859900;
|
|
11
|
+
export function getLightModeTheme() {
|
|
12
|
+
const lightModeTheme = [...commonTheme];
|
|
13
|
+
lightModeTheme[Color.PRIMARY] = 0x657b83;
|
|
14
|
+
lightModeTheme[Color.SECONDARY] = 0x93a1a1;
|
|
15
|
+
lightModeTheme[Color.EMPHASISED] = 0x586e75;
|
|
16
|
+
lightModeTheme[Color.SELECTED] = 0xeee8d5;
|
|
17
|
+
return lightModeTheme;
|
|
18
|
+
}
|
|
19
|
+
export function getDarkModeTheme() {
|
|
20
|
+
const darkModeTheme = [...commonTheme];
|
|
21
|
+
darkModeTheme[Color.PRIMARY] = 0x839496;
|
|
22
|
+
darkModeTheme[Color.SECONDARY] = 0x586e75;
|
|
23
|
+
darkModeTheme[Color.EMPHASISED] = 0x93a1a1;
|
|
24
|
+
darkModeTheme[Color.SELECTED] = 0x073642;
|
|
25
|
+
return darkModeTheme;
|
|
26
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { PromptType, } from "../../api/service/core/PrompterService.js";
|
|
2
|
+
import promptSingleSelect from "./prompt/promptSingleSelect.js";
|
|
3
|
+
import promptMultiSelect from "./prompt/promptMultiSelect.js";
|
|
4
|
+
import promptAcknowledge from "./prompt/promptAcknowledge.js";
|
|
5
|
+
import promptToggle from "./prompt/promptToggle.js";
|
|
6
|
+
import promptText from "./prompt/promptText.js";
|
|
7
|
+
import promptOpenUrl from "./prompt/promptOpenUrl.js";
|
|
8
|
+
export const DEFAULT_PROMPTER_CONFIG = {
|
|
9
|
+
inputPromptCharacters: "> ",
|
|
10
|
+
checkboxCheckedChars: "[x]",
|
|
11
|
+
checkboxUncheckedChars: "[ ]",
|
|
12
|
+
scrollVisibleOptions: 8,
|
|
13
|
+
};
|
|
14
|
+
export default class DefaultPrompterService {
|
|
15
|
+
promptEnabled = true;
|
|
16
|
+
#ctx;
|
|
17
|
+
constructor(config, terminal, keyReader, printerService) {
|
|
18
|
+
this.#ctx = { config, terminal, keyReader, printerService };
|
|
19
|
+
}
|
|
20
|
+
prompt(promptDef) {
|
|
21
|
+
if (!this.promptEnabled) {
|
|
22
|
+
if (promptDef.defaultOption) {
|
|
23
|
+
return Promise.resolve({
|
|
24
|
+
name: promptDef.name,
|
|
25
|
+
value: promptDef.defaultOption.returnedValue,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return Promise.reject(new Error(`Prompting is disabled and no default for prompt: ${promptDef.name}`));
|
|
29
|
+
}
|
|
30
|
+
switch (promptDef.type) {
|
|
31
|
+
case PromptType.SINGLE_SELECT:
|
|
32
|
+
return promptSingleSelect(this.#ctx, promptDef);
|
|
33
|
+
case PromptType.MULTI_SELECT:
|
|
34
|
+
return promptMultiSelect(this.#ctx, promptDef);
|
|
35
|
+
case PromptType.ACKNOWLEDGE:
|
|
36
|
+
return promptAcknowledge(this.#ctx, promptDef);
|
|
37
|
+
case PromptType.TOGGLE:
|
|
38
|
+
return promptToggle(this.#ctx, promptDef);
|
|
39
|
+
case PromptType.TEXT:
|
|
40
|
+
return promptText(this.#ctx, promptDef);
|
|
41
|
+
case PromptType.OPEN_URL:
|
|
42
|
+
return promptOpenUrl(this.#ctx, promptDef);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async promptAll(prompts) {
|
|
46
|
+
const results = [];
|
|
47
|
+
for (const p of prompts) {
|
|
48
|
+
results.push(await this.prompt(p));
|
|
49
|
+
}
|
|
50
|
+
return results;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { PROMPTER_SERVICE_ID } from "../../api/service/core/PrompterService.js";
|
|
2
|
+
import NoPromptCommand from "./command/NoPromptCommand.js";
|
|
3
|
+
export default class PrompterServiceProvider {
|
|
4
|
+
serviceId = PROMPTER_SERVICE_ID;
|
|
5
|
+
servicePriority;
|
|
6
|
+
prompterService;
|
|
7
|
+
constructor(servicePriority, prompterService) {
|
|
8
|
+
this.servicePriority = servicePriority;
|
|
9
|
+
this.prompterService = prompterService;
|
|
10
|
+
}
|
|
11
|
+
getServiceInfo(_cliConfig) {
|
|
12
|
+
return Promise.resolve({
|
|
13
|
+
service: this.prompterService,
|
|
14
|
+
commands: [new NoPromptCommand(this, this.servicePriority)],
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
initService(_context) {
|
|
18
|
+
return Promise.resolve();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ArgumentValueTypeName, } from "../../../api/argument/ArgumentValueTypes.js";
|
|
2
|
+
export default class NoPromptCommand {
|
|
3
|
+
name = "no-prompt";
|
|
4
|
+
description = "Disable interactive prompting";
|
|
5
|
+
enableConfiguration = true;
|
|
6
|
+
argument = {
|
|
7
|
+
type: ArgumentValueTypeName.BOOLEAN,
|
|
8
|
+
defaultValue: false,
|
|
9
|
+
configurationKey: "NO_PROMPT",
|
|
10
|
+
};
|
|
11
|
+
executePriority;
|
|
12
|
+
#prompterServiceProvider;
|
|
13
|
+
constructor(prompterServiceProvider, executePriority) {
|
|
14
|
+
this.#prompterServiceProvider = prompterServiceProvider;
|
|
15
|
+
this.executePriority = executePriority;
|
|
16
|
+
}
|
|
17
|
+
execute(_context, argumentValue) {
|
|
18
|
+
this.#prompterServiceProvider.prompterService.promptEnabled = !argumentValue;
|
|
19
|
+
return Promise.resolve();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function physicalLineCount(terminal, text) {
|
|
2
|
+
const cols = terminal.columns();
|
|
3
|
+
if (cols <= 0)
|
|
4
|
+
return 1;
|
|
5
|
+
return text.split("\n").reduce((sum, segment) => {
|
|
6
|
+
const width = Bun.stringWidth(segment);
|
|
7
|
+
return sum + Math.max(1, Math.ceil(width / cols));
|
|
8
|
+
}, 0);
|
|
9
|
+
}
|
|
10
|
+
export function headerLineCount(terminal, promptDef) {
|
|
11
|
+
let count = physicalLineCount(terminal, promptDef.promptText);
|
|
12
|
+
if (promptDef.description) {
|
|
13
|
+
count += physicalLineCount(terminal, promptDef.description);
|
|
14
|
+
}
|
|
15
|
+
return count;
|
|
16
|
+
}
|
|
17
|
+
export async function renderPromptHeader(ctx, promptDef) {
|
|
18
|
+
await ctx.terminal.write(`${ctx.printerService.emphasised(promptDef.promptText)}\n`);
|
|
19
|
+
if (promptDef.description) {
|
|
20
|
+
await ctx.terminal.write(`${ctx.printerService.secondary(promptDef.description)}\n`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { PromptType, } from "../../../api/service/core/PrompterService.js";
|
|
2
|
+
import promptSingleSelect from "./promptSingleSelect.js";
|
|
3
|
+
export default function promptAcknowledge(ctx, promptDef) {
|
|
4
|
+
const yesNo = {
|
|
5
|
+
name: promptDef.name,
|
|
6
|
+
promptText: promptDef.promptText,
|
|
7
|
+
description: promptDef.description,
|
|
8
|
+
type: PromptType.SINGLE_SELECT,
|
|
9
|
+
defaultOption: promptDef.defaultOption ?? {
|
|
10
|
+
displayValue: "No",
|
|
11
|
+
returnedValue: false,
|
|
12
|
+
},
|
|
13
|
+
options: [
|
|
14
|
+
{ displayValue: "Yes", returnedValue: true },
|
|
15
|
+
{ displayValue: "No", returnedValue: false },
|
|
16
|
+
],
|
|
17
|
+
};
|
|
18
|
+
return promptSingleSelect(ctx, yesNo);
|
|
19
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { SpecialKey } from "../../../terminal/KeyReader.js";
|
|
2
|
+
import ShutdownServiceProvider from "../../shutdown/ShutdownServiceProvider.js";
|
|
3
|
+
import { headerLineCount, renderPromptHeader } from "./PromptContext.js";
|
|
4
|
+
export default async function promptMultiSelect(ctx, promptDef) {
|
|
5
|
+
const options = promptDef.options;
|
|
6
|
+
if (options.length === 0) {
|
|
7
|
+
throw new Error(`No options for prompt: ${promptDef.name}`);
|
|
8
|
+
}
|
|
9
|
+
let focusIndex = 0;
|
|
10
|
+
const checked = new Set();
|
|
11
|
+
let scrollOffset = 0;
|
|
12
|
+
const visibleCount = Math.min(ctx.config.scrollVisibleOptions, options.length);
|
|
13
|
+
ctx.keyReader.enableRawMode();
|
|
14
|
+
try {
|
|
15
|
+
await ctx.terminal.hideCursor();
|
|
16
|
+
let firstRender = true;
|
|
17
|
+
while (true) {
|
|
18
|
+
if (scrollOffset > focusIndex) {
|
|
19
|
+
scrollOffset = focusIndex;
|
|
20
|
+
}
|
|
21
|
+
else if (focusIndex >= scrollOffset + visibleCount) {
|
|
22
|
+
scrollOffset = focusIndex - visibleCount + 1;
|
|
23
|
+
}
|
|
24
|
+
const headerLines = headerLineCount(ctx.terminal, promptDef);
|
|
25
|
+
if (!firstRender) {
|
|
26
|
+
await ctx.terminal.clearUpLines(visibleCount + headerLines);
|
|
27
|
+
}
|
|
28
|
+
firstRender = false;
|
|
29
|
+
await renderPromptHeader(ctx, promptDef);
|
|
30
|
+
for (let i = scrollOffset; i < scrollOffset + visibleCount; i++) {
|
|
31
|
+
const option = options[i];
|
|
32
|
+
const isFocused = i === focusIndex;
|
|
33
|
+
const isChecked = checked.has(i);
|
|
34
|
+
const checkbox = isChecked
|
|
35
|
+
? ctx.printerService.green(ctx.config.checkboxCheckedChars)
|
|
36
|
+
: ctx.printerService.secondary(ctx.config.checkboxUncheckedChars);
|
|
37
|
+
const text = option.displayValue;
|
|
38
|
+
await ctx.terminal.write(`${checkbox} ${isFocused ? ctx.printerService.cyan(text) : ctx.printerService.secondary(text)}\n`);
|
|
39
|
+
}
|
|
40
|
+
const keyEvent = await ctx.keyReader.readKey();
|
|
41
|
+
if (keyEvent.specialKey === SpecialKey.UP && focusIndex > 0) {
|
|
42
|
+
focusIndex--;
|
|
43
|
+
}
|
|
44
|
+
else if (keyEvent.specialKey === SpecialKey.DOWN && focusIndex < options.length - 1) {
|
|
45
|
+
focusIndex++;
|
|
46
|
+
}
|
|
47
|
+
else if (keyEvent.specialKey === SpecialKey.SPACE) {
|
|
48
|
+
if (checked.has(focusIndex)) {
|
|
49
|
+
checked.delete(focusIndex);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
checked.add(focusIndex);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (keyEvent.specialKey === SpecialKey.ENTER) {
|
|
56
|
+
await ctx.terminal.showCursor();
|
|
57
|
+
const values = [...checked].sort().map((i) => options[i].returnedValue);
|
|
58
|
+
return { name: promptDef.name, value: values };
|
|
59
|
+
}
|
|
60
|
+
else if (keyEvent.specialKey === SpecialKey.ESCAPE) {
|
|
61
|
+
await ctx.terminal.showCursor();
|
|
62
|
+
throw new Error("Prompt cancelled");
|
|
63
|
+
}
|
|
64
|
+
else if (keyEvent.specialKey === SpecialKey.INTERRUPT) {
|
|
65
|
+
await ctx.terminal.showCursor();
|
|
66
|
+
ShutdownServiceProvider.onInterrupt();
|
|
67
|
+
throw new Error("Interrupted");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
ctx.keyReader.disableRawMode();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { SpecialKey } from "../../../terminal/KeyReader.js";
|
|
2
|
+
import ShutdownServiceProvider from "../../shutdown/ShutdownServiceProvider.js";
|
|
3
|
+
import { renderPromptHeader } from "./PromptContext.js";
|
|
4
|
+
function isRemoteSession() {
|
|
5
|
+
return !!(process.env.SSH_CONNECTION || process.env.SSH_CLIENT || process.env.SSH_TTY);
|
|
6
|
+
}
|
|
7
|
+
async function defaultOpenUrl(url) {
|
|
8
|
+
const parsed = new URL(url);
|
|
9
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
10
|
+
throw new Error(`Unsupported URL protocol: ${parsed.protocol}`);
|
|
11
|
+
}
|
|
12
|
+
const platform = process.platform;
|
|
13
|
+
let cmd;
|
|
14
|
+
if (platform === "darwin") {
|
|
15
|
+
cmd = ["open", url];
|
|
16
|
+
}
|
|
17
|
+
else if (platform === "win32") {
|
|
18
|
+
cmd = ["cmd", "/c", "start", "", url];
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
cmd = ["xdg-open", url];
|
|
22
|
+
}
|
|
23
|
+
const proc = Bun.spawn(cmd, { stdout: "ignore", stderr: "ignore" });
|
|
24
|
+
const exitCode = await proc.exited;
|
|
25
|
+
if (exitCode !== 0) {
|
|
26
|
+
throw new Error(`Failed to open URL (exit code ${exitCode})`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export default async function promptOpenUrl(ctx, promptDef) {
|
|
30
|
+
if (promptDef.options.length === 0) {
|
|
31
|
+
throw new Error(`No URL option for prompt: ${promptDef.name}`);
|
|
32
|
+
}
|
|
33
|
+
const url = String(promptDef.options[0].returnedValue);
|
|
34
|
+
const displayLabel = promptDef.options[0].displayValue;
|
|
35
|
+
const openUrlFn = ctx.config.openUrl ?? defaultOpenUrl;
|
|
36
|
+
const canOpenBrowser = !isRemoteSession();
|
|
37
|
+
ctx.keyReader.enableRawMode();
|
|
38
|
+
try {
|
|
39
|
+
await renderPromptHeader(ctx, promptDef);
|
|
40
|
+
await ctx.terminal.write(`${displayLabel}: ${ctx.printerService.cyan(url)}\n`);
|
|
41
|
+
const instruction = canOpenBrowser
|
|
42
|
+
? "Press ENTER to open in the browser..."
|
|
43
|
+
: "Copy the URL above and open it in your local browser, then press ENTER to continue...";
|
|
44
|
+
await ctx.terminal.write(`${ctx.printerService.secondary(instruction)}\n`);
|
|
45
|
+
while (true) {
|
|
46
|
+
const keyEvent = await ctx.keyReader.readKey();
|
|
47
|
+
if (keyEvent.specialKey === SpecialKey.ENTER) {
|
|
48
|
+
if (canOpenBrowser) {
|
|
49
|
+
try {
|
|
50
|
+
await openUrlFn(url);
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
await ctx.terminal.write(`${ctx.printerService.red(`Failed to open URL: ${e instanceof Error ? e.message : String(e)}`)}\n`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { name: promptDef.name, value: url };
|
|
57
|
+
}
|
|
58
|
+
else if (keyEvent.specialKey === SpecialKey.ESCAPE) {
|
|
59
|
+
throw new Error("Prompt cancelled");
|
|
60
|
+
}
|
|
61
|
+
else if (keyEvent.specialKey === SpecialKey.INTERRUPT) {
|
|
62
|
+
ShutdownServiceProvider.onInterrupt();
|
|
63
|
+
throw new Error("Interrupted");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
ctx.keyReader.disableRawMode();
|
|
69
|
+
}
|
|
70
|
+
}
|