@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,159 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { COMPLETION_SERVICE_ID } from "../../api/service/core/CompletionService.js";
|
|
3
|
+
import { ShellType } from "../../api/service/core/CompletionService.js";
|
|
4
|
+
import { PROMPTER_SERVICE_ID } from "../../api/service/core/PrompterService.js";
|
|
5
|
+
import { PromptType } from "../../api/service/core/PrompterService.js";
|
|
6
|
+
import { KEY_VALUE_SERVICE_ID } from "../../api/service/core/KeyValueService.js";
|
|
7
|
+
import { Icon, PRINTER_SERVICE_ID } from "../../api/service/core/PrinterService.js";
|
|
8
|
+
import getLogger from "../../util/logger.js";
|
|
9
|
+
import { CompletionIntegrationSubCommand } from "./command/CompletionIntegrationSubCommand.js";
|
|
10
|
+
import { CompletionCompleteSubCommand } from "./command/CompletionCompleteSubCommand.js";
|
|
11
|
+
import { CompletionGroupCommand } from "./command/CompletionGroupCommand.js";
|
|
12
|
+
const logger = getLogger("CompletionServiceProvider");
|
|
13
|
+
export default class CompletionServiceProvider {
|
|
14
|
+
serviceId = COMPLETION_SERVICE_ID;
|
|
15
|
+
servicePriority;
|
|
16
|
+
#completionService;
|
|
17
|
+
#cliName = "";
|
|
18
|
+
constructor(servicePriority, completionService, commandRegistry) {
|
|
19
|
+
this.servicePriority = servicePriority;
|
|
20
|
+
this.#completionService = completionService;
|
|
21
|
+
this.#completionService.setCommandRegistry(commandRegistry);
|
|
22
|
+
}
|
|
23
|
+
getServiceInfo(cliConfig) {
|
|
24
|
+
this.#cliName = cliConfig.name;
|
|
25
|
+
return Promise.resolve({
|
|
26
|
+
service: this.#completionService,
|
|
27
|
+
commands: [
|
|
28
|
+
new CompletionGroupCommand(new CompletionIntegrationSubCommand(), new CompletionCompleteSubCommand()),
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async initService(context) {
|
|
33
|
+
if (!context.doesServiceExist(PROMPTER_SERVICE_ID)) {
|
|
34
|
+
logger.debug(() => "PrompterService not available, skipping auto-prompt");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (!context.doesServiceExist(KEY_VALUE_SERVICE_ID)) {
|
|
38
|
+
logger.debug(() => "KeyValueService not available, skipping auto-prompt");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const keyValueService = context.getServiceById(KEY_VALUE_SERVICE_ID);
|
|
42
|
+
if (await keyValueService.hasKey("completion-status")) {
|
|
43
|
+
const status = await keyValueService.getKey("completion-status");
|
|
44
|
+
if (status === "installed" || status === "declined") {
|
|
45
|
+
logger.debug(() => `Completion status is '${status}', skipping auto-prompt`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const prompterService = context.getServiceById(PROMPTER_SERVICE_ID);
|
|
50
|
+
if (!prompterService.promptEnabled) {
|
|
51
|
+
logger.debug(() => "Prompting is disabled, skipping auto-prompt");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const detectedShells = await this.#detectAvailableShells();
|
|
55
|
+
if (detectedShells.length === 0) {
|
|
56
|
+
logger.debug(() => "No supported shells detected, skipping auto-prompt");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let enableResult;
|
|
60
|
+
try {
|
|
61
|
+
enableResult = await prompterService.prompt({
|
|
62
|
+
name: "enable-completion",
|
|
63
|
+
promptText: "Would you like to enable autocompletion?",
|
|
64
|
+
description: "This will set up your terminal so that pressing TAB while typing commands will show possible options and autocomplete arguments.\n(Enabling autocompletion will modify configuration files in your home directory.)",
|
|
65
|
+
type: PromptType.TOGGLE,
|
|
66
|
+
options: [
|
|
67
|
+
{ displayValue: "Yes", returnedValue: true },
|
|
68
|
+
{ displayValue: "No", returnedValue: false },
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (enableResult.value !== true) {
|
|
76
|
+
await keyValueService.setKey("completion-status", "declined");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
let shellType;
|
|
80
|
+
if (detectedShells.length === 1) {
|
|
81
|
+
shellType = detectedShells[0];
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const shellOptions = detectedShells.map((shell) => ({
|
|
85
|
+
displayValue: shell,
|
|
86
|
+
returnedValue: shell,
|
|
87
|
+
}));
|
|
88
|
+
let shellResult;
|
|
89
|
+
try {
|
|
90
|
+
shellResult = await prompterService.prompt({
|
|
91
|
+
name: "shell-type",
|
|
92
|
+
promptText: "Which shell would you like to configure?",
|
|
93
|
+
type: PromptType.SINGLE_SELECT,
|
|
94
|
+
defaultOption: shellOptions[0],
|
|
95
|
+
options: shellOptions,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
shellType = shellResult.value;
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
await this.#installCompletion(context, shellType);
|
|
105
|
+
await keyValueService.setKey("completion-status", "installed");
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (context.doesServiceExist(PRINTER_SERVICE_ID)) {
|
|
109
|
+
const printerService = context.getServiceById(PRINTER_SERVICE_ID);
|
|
110
|
+
await printerService.error(`Failed to install completion: ${error.message}`, Icon.FAILURE);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async #detectAvailableShells() {
|
|
115
|
+
const available = [];
|
|
116
|
+
for (const shell of Object.values(ShellType)) {
|
|
117
|
+
if (await this.#completionService.validateShellEnvironment(shell)) {
|
|
118
|
+
available.push(shell);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return available;
|
|
122
|
+
}
|
|
123
|
+
async #installCompletion(context, shellType) {
|
|
124
|
+
const configPath = this.#completionService.getDefaultConfigPath(shellType);
|
|
125
|
+
const bootstrapScript = this.#completionService.getBootstrapScript(shellType, this.#cliName, process.execPath);
|
|
126
|
+
const beginMarker = `# BEGIN ${this.#cliName} completion`;
|
|
127
|
+
const endMarker = `# END ${this.#cliName} completion`;
|
|
128
|
+
const block = `${beginMarker}\n${bootstrapScript}\n${endMarker}`;
|
|
129
|
+
let existingContent = "";
|
|
130
|
+
try {
|
|
131
|
+
existingContent = await Bun.file(configPath).text();
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// File doesn't exist yet
|
|
135
|
+
}
|
|
136
|
+
let newContent;
|
|
137
|
+
const beginIdx = existingContent.indexOf(beginMarker);
|
|
138
|
+
const endIdx = existingContent.indexOf(endMarker);
|
|
139
|
+
if (beginIdx !== -1 && endIdx !== -1) {
|
|
140
|
+
newContent =
|
|
141
|
+
existingContent.substring(0, beginIdx) +
|
|
142
|
+
block +
|
|
143
|
+
existingContent.substring(endIdx + endMarker.length);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const separator = existingContent.length > 0 && !existingContent.endsWith("\n")
|
|
147
|
+
? "\n\n"
|
|
148
|
+
: existingContent.length > 0
|
|
149
|
+
? "\n"
|
|
150
|
+
: "";
|
|
151
|
+
newContent = existingContent + separator + block + "\n";
|
|
152
|
+
}
|
|
153
|
+
await Bun.write(configPath, newContent);
|
|
154
|
+
if (context.doesServiceExist(PRINTER_SERVICE_ID)) {
|
|
155
|
+
const printerService = context.getServiceById(PRINTER_SERVICE_ID);
|
|
156
|
+
await printerService.info(`Shell completion installed for ${shellType}. Restart your shell or run 'source ${configPath}' to activate.`, Icon.SUCCESS);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { ShellType } from "../../api/service/core/CompletionService.js";
|
|
2
|
+
import BashShellHandler from "./shell/bash.js";
|
|
3
|
+
import ZshShellHandler from "./shell/zsh.js";
|
|
4
|
+
import FishShellHandler from "./shell/fish.js";
|
|
5
|
+
import PowerShellShellHandler from "./shell/powershell.js";
|
|
6
|
+
export default class DefaultCompletionService {
|
|
7
|
+
#commandRegistry;
|
|
8
|
+
#shellHandlers = new Map([
|
|
9
|
+
[ShellType.BASH, new BashShellHandler()],
|
|
10
|
+
[ShellType.ZSH, new ZshShellHandler()],
|
|
11
|
+
[ShellType.FISH, new FishShellHandler()],
|
|
12
|
+
[ShellType.POWERSHELL, new PowerShellShellHandler()],
|
|
13
|
+
]);
|
|
14
|
+
setCommandRegistry(registry) {
|
|
15
|
+
this.#commandRegistry = registry;
|
|
16
|
+
}
|
|
17
|
+
getBootstrapScript(shellType, cliName, executablePath) {
|
|
18
|
+
return this.#getHandler(shellType).getBootstrapScript(cliName, executablePath);
|
|
19
|
+
}
|
|
20
|
+
getDefaultConfigPath(shellType) {
|
|
21
|
+
return this.#getHandler(shellType).getDefaultConfigPath();
|
|
22
|
+
}
|
|
23
|
+
validateShellEnvironment(shellType) {
|
|
24
|
+
return this.#getHandler(shellType).validateEnvironment();
|
|
25
|
+
}
|
|
26
|
+
formatCompletions(shellType, completions) {
|
|
27
|
+
return this.#getHandler(shellType).formatCompletions(completions);
|
|
28
|
+
}
|
|
29
|
+
parseCompletionContext(shell, args) {
|
|
30
|
+
return this.#getHandler(shell).parseCompletionContext(args);
|
|
31
|
+
}
|
|
32
|
+
generateCompletions(_shellType, line, cursorPosition) {
|
|
33
|
+
if (!this.#commandRegistry) {
|
|
34
|
+
return Promise.resolve([]);
|
|
35
|
+
}
|
|
36
|
+
const beforeCursor = line.substring(0, cursorPosition);
|
|
37
|
+
const words = this.#tokenize(beforeCursor);
|
|
38
|
+
// Remove CLI name (first word)
|
|
39
|
+
const relevantWords = words.slice(1);
|
|
40
|
+
const currentWord = relevantWords[relevantWords.length - 1] ?? "";
|
|
41
|
+
const previousWords = relevantWords.slice(0, -1);
|
|
42
|
+
const endsWithSpace = beforeCursor.endsWith(" ");
|
|
43
|
+
if (relevantWords.length === 0 || (relevantWords.length === 1 && !endsWithSpace)) {
|
|
44
|
+
return Promise.resolve(this.#completeCommandName(currentWord));
|
|
45
|
+
}
|
|
46
|
+
if (endsWithSpace) {
|
|
47
|
+
const commandWord = relevantWords[0];
|
|
48
|
+
return Promise.resolve(this.#completeAfterCommand(commandWord, relevantWords.slice(1), ""));
|
|
49
|
+
}
|
|
50
|
+
const commandWord = previousWords[0];
|
|
51
|
+
if (commandWord) {
|
|
52
|
+
return Promise.resolve(this.#completeAfterCommand(commandWord, previousWords.slice(1), currentWord));
|
|
53
|
+
}
|
|
54
|
+
return Promise.resolve(this.#completeCommandName(currentWord));
|
|
55
|
+
}
|
|
56
|
+
#completeAfterCommand(commandWord, intermediateWords, currentWord) {
|
|
57
|
+
// Check for group:member pattern
|
|
58
|
+
if (commandWord.includes(":")) {
|
|
59
|
+
const result = this.#commandRegistry.getGroupCommandAndMemberSubCommandByJoinedName(commandWord);
|
|
60
|
+
if (result) {
|
|
61
|
+
return this.#completeSubCommandArgs(result.command, intermediateWords, currentWord);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Check if partial group:member (e.g. "completions:" completing member)
|
|
65
|
+
if (currentWord.includes(":")) {
|
|
66
|
+
const colonIdx = currentWord.indexOf(":");
|
|
67
|
+
const groupPart = currentWord.substring(0, colonIdx);
|
|
68
|
+
const groupCommand = this.#commandRegistry.getGroupCommandByName(groupPart);
|
|
69
|
+
if (groupCommand) {
|
|
70
|
+
return groupCommand.memberSubCommands
|
|
71
|
+
.filter((sc) => `${groupPart}:${sc.name}`.startsWith(currentWord))
|
|
72
|
+
.map((sc) => ({
|
|
73
|
+
value: `${groupPart}:${sc.name}`,
|
|
74
|
+
description: sc.description,
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Check global command (--name pattern)
|
|
79
|
+
if (commandWord.startsWith("--")) {
|
|
80
|
+
const globalCommandName = commandWord.substring(2);
|
|
81
|
+
const globalCommand = this.#commandRegistry.getGlobalCommandByName(globalCommandName);
|
|
82
|
+
if (globalCommand) {
|
|
83
|
+
if (globalCommand.argument?.allowableValues) {
|
|
84
|
+
return globalCommand.argument.allowableValues
|
|
85
|
+
.filter((v) => String(v).startsWith(currentWord))
|
|
86
|
+
.map((v) => ({ value: String(v) }));
|
|
87
|
+
}
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Check sub-command
|
|
92
|
+
const subCommand = this.#commandRegistry.getSubCommandByName(commandWord);
|
|
93
|
+
if (subCommand) {
|
|
94
|
+
return this.#completeSubCommandArgs(subCommand, intermediateWords, currentWord);
|
|
95
|
+
}
|
|
96
|
+
// Check group command (suggest members)
|
|
97
|
+
const groupCommand = this.#commandRegistry.getGroupCommandByName(commandWord);
|
|
98
|
+
if (groupCommand) {
|
|
99
|
+
return groupCommand.memberSubCommands
|
|
100
|
+
.filter((sc) => sc.name.startsWith(currentWord))
|
|
101
|
+
.map((sc) => ({
|
|
102
|
+
value: `${commandWord}:${sc.name}`,
|
|
103
|
+
description: sc.description,
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
return this.#completeCommandName(currentWord);
|
|
107
|
+
}
|
|
108
|
+
#completeCommandName(prefix) {
|
|
109
|
+
const completions = [];
|
|
110
|
+
// Sub-commands
|
|
111
|
+
const subCommands = this.#commandRegistry.getSubCommands();
|
|
112
|
+
for (const cmd of subCommands) {
|
|
113
|
+
if (cmd.name.startsWith(prefix)) {
|
|
114
|
+
completions.push({ value: cmd.name, description: cmd.description });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Group:member joined names
|
|
118
|
+
const groupAndMembers = this.#commandRegistry.getGroupAndMemberCommandsByJoinedName();
|
|
119
|
+
for (const [joinedName, entry] of groupAndMembers) {
|
|
120
|
+
if (joinedName.startsWith(prefix)) {
|
|
121
|
+
completions.push({
|
|
122
|
+
value: joinedName,
|
|
123
|
+
description: entry.command.description,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Group command names (to suggest further typing "group:")
|
|
128
|
+
const groupCommands = this.#commandRegistry.getGroupCommands();
|
|
129
|
+
for (const cmd of groupCommands) {
|
|
130
|
+
if (cmd.name.startsWith(prefix) && !prefix.includes(":")) {
|
|
131
|
+
completions.push({
|
|
132
|
+
value: cmd.name,
|
|
133
|
+
description: cmd.description,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Global commands (with -- prefix)
|
|
138
|
+
const globalCommands = this.#commandRegistry.getGlobalCommands();
|
|
139
|
+
for (const cmd of globalCommands) {
|
|
140
|
+
const prefixed = `--${cmd.name}`;
|
|
141
|
+
if (prefixed.startsWith(prefix)) {
|
|
142
|
+
completions.push({ value: prefixed, description: cmd.description });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Global modifier commands (with -- prefix)
|
|
146
|
+
const modifierCommands = this.#commandRegistry.getGlobalModifierCommands();
|
|
147
|
+
for (const cmd of modifierCommands) {
|
|
148
|
+
const prefixed = `--${cmd.name}`;
|
|
149
|
+
if (prefixed.startsWith(prefix)) {
|
|
150
|
+
completions.push({ value: prefixed, description: cmd.description });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return completions;
|
|
154
|
+
}
|
|
155
|
+
#completeSubCommandArgs(subCommand, previousArgs, currentWord) {
|
|
156
|
+
const completions = [];
|
|
157
|
+
// If current word starts with --, complete option names
|
|
158
|
+
if (currentWord.startsWith("--")) {
|
|
159
|
+
const prefix = currentWord.substring(2);
|
|
160
|
+
for (const opt of subCommand.options) {
|
|
161
|
+
if ("name" in opt && opt.name.startsWith(prefix)) {
|
|
162
|
+
completions.push({
|
|
163
|
+
value: `--${opt.name}`,
|
|
164
|
+
description: opt.description,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return completions;
|
|
169
|
+
}
|
|
170
|
+
// If current word starts with -, complete short aliases
|
|
171
|
+
if (currentWord.startsWith("-") && currentWord.length <= 2) {
|
|
172
|
+
for (const opt of subCommand.options) {
|
|
173
|
+
if ("shortAlias" in opt && opt.shortAlias) {
|
|
174
|
+
const alias = `-${opt.shortAlias}`;
|
|
175
|
+
if (alias.startsWith(currentWord)) {
|
|
176
|
+
completions.push({
|
|
177
|
+
value: alias,
|
|
178
|
+
description: opt.description,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return completions;
|
|
184
|
+
}
|
|
185
|
+
// Check if previous word was an option expecting a value
|
|
186
|
+
const lastPrevWord = previousArgs[previousArgs.length - 1];
|
|
187
|
+
if (lastPrevWord && lastPrevWord.startsWith("--")) {
|
|
188
|
+
const optName = lastPrevWord.substring(2);
|
|
189
|
+
const option = subCommand.options.find((o) => "name" in o && o.name === optName);
|
|
190
|
+
if (option && option.allowableValues) {
|
|
191
|
+
return option.allowableValues
|
|
192
|
+
.filter((v) => String(v).startsWith(currentWord))
|
|
193
|
+
.map((v) => ({ value: String(v) }));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Suggest options that haven't been used
|
|
197
|
+
for (const opt of subCommand.options) {
|
|
198
|
+
if ("name" in opt) {
|
|
199
|
+
const optName = `--${opt.name}`;
|
|
200
|
+
if (!previousArgs.includes(optName) && optName.startsWith(currentWord)) {
|
|
201
|
+
completions.push({
|
|
202
|
+
value: optName,
|
|
203
|
+
description: opt.description,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Suggest positional allowable values
|
|
209
|
+
const positionalIndex = this.#countPositionalArgs(previousArgs, subCommand);
|
|
210
|
+
if (positionalIndex < subCommand.positionals.length) {
|
|
211
|
+
const positional = subCommand.positionals[positionalIndex];
|
|
212
|
+
if (positional.allowableValues) {
|
|
213
|
+
for (const v of positional.allowableValues) {
|
|
214
|
+
if (String(v).startsWith(currentWord)) {
|
|
215
|
+
completions.push({ value: String(v) });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return completions;
|
|
221
|
+
}
|
|
222
|
+
#countPositionalArgs(args, subCommand) {
|
|
223
|
+
let count = 0;
|
|
224
|
+
let i = 0;
|
|
225
|
+
while (i < args.length) {
|
|
226
|
+
const arg = args[i];
|
|
227
|
+
if (arg.startsWith("-")) {
|
|
228
|
+
// Skip option and its value
|
|
229
|
+
const optName = arg.startsWith("--") ? arg.substring(2) : undefined;
|
|
230
|
+
const option = optName
|
|
231
|
+
? subCommand.options.find((o) => "name" in o && o.name === optName)
|
|
232
|
+
: undefined;
|
|
233
|
+
if (option && option.type !== undefined) {
|
|
234
|
+
i++; // skip the option value
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
count++;
|
|
239
|
+
}
|
|
240
|
+
i++;
|
|
241
|
+
}
|
|
242
|
+
return count;
|
|
243
|
+
}
|
|
244
|
+
#tokenize(input) {
|
|
245
|
+
const words = [];
|
|
246
|
+
let current = "";
|
|
247
|
+
let inSingleQuote = false;
|
|
248
|
+
let inDoubleQuote = false;
|
|
249
|
+
for (let i = 0; i < input.length; i++) {
|
|
250
|
+
const ch = input[i];
|
|
251
|
+
if (ch === "'" && !inDoubleQuote) {
|
|
252
|
+
inSingleQuote = !inSingleQuote;
|
|
253
|
+
}
|
|
254
|
+
else if (ch === '"' && !inSingleQuote) {
|
|
255
|
+
inDoubleQuote = !inDoubleQuote;
|
|
256
|
+
}
|
|
257
|
+
else if (ch === " " && !inSingleQuote && !inDoubleQuote) {
|
|
258
|
+
if (current.length > 0) {
|
|
259
|
+
words.push(current);
|
|
260
|
+
current = "";
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
current += ch;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (current.length > 0) {
|
|
268
|
+
words.push(current);
|
|
269
|
+
}
|
|
270
|
+
return words;
|
|
271
|
+
}
|
|
272
|
+
#getHandler(shellType) {
|
|
273
|
+
const handler = this.#shellHandlers.get(shellType);
|
|
274
|
+
if (!handler) {
|
|
275
|
+
throw new Error(`Unsupported shell type: ${shellType}`);
|
|
276
|
+
}
|
|
277
|
+
return handler;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type SubCommand from "../../../api/command/SubCommand.ts";
|
|
2
|
+
import type Option from "../../../api/argument/Option.ts";
|
|
3
|
+
import type Positional from "../../../api/argument/Positional.ts";
|
|
4
|
+
import type Context from "../../../api/Context.ts";
|
|
5
|
+
import { type ArgumentValues } from "../../../api/argument/ArgumentValueTypes.ts";
|
|
6
|
+
export declare class CompletionCompleteSubCommand implements SubCommand {
|
|
7
|
+
readonly name = "complete";
|
|
8
|
+
readonly description = "Generate completions for shell integration";
|
|
9
|
+
readonly enableConfiguration = false;
|
|
10
|
+
readonly disableGenericHelpDisplay = true;
|
|
11
|
+
readonly options: ReadonlyArray<Option>;
|
|
12
|
+
readonly positionals: ReadonlyArray<Positional>;
|
|
13
|
+
execute(context: Context, argumentValues: ArgumentValues): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=CompletionCompleteSubCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompletionCompleteSubCommand.d.ts","sourceRoot":"","sources":["../../../../../src/service/completion/command/CompletionCompleteSubCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,oCAAoC,CAAC;AACjE,OAAO,KAAK,MAAM,MAAM,iCAAiC,CAAC;AAC1D,OAAO,KAAK,UAAU,MAAM,qCAAqC,CAAC;AAClE,OAAO,KAAK,OAAO,MAAM,yBAAyB,CAAC;AACnD,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,6CAA6C,CAAC;AAMrD,qBAAa,4BAA6B,YAAW,UAAU;IAC7D,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,WAAW,gDAAgD;IACpE,QAAQ,CAAC,mBAAmB,SAAS;IACrC,QAAQ,CAAC,yBAAyB,QAAQ;IAE1C,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAM;IAE7C,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAc7C;IAEI,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAqB/E"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ArgumentValueTypeName, } from "../../../api/argument/ArgumentValueTypes.js";
|
|
2
|
+
import { COMPLETION_SERVICE_ID, ShellType } from "../../../api/service/core/CompletionService.js";
|
|
3
|
+
import { PRINTER_SERVICE_ID } from "../../../api/service/core/PrinterService.js";
|
|
4
|
+
export class CompletionCompleteSubCommand {
|
|
5
|
+
name = "complete";
|
|
6
|
+
description = "Generate completions for shell integration";
|
|
7
|
+
enableConfiguration = false;
|
|
8
|
+
disableGenericHelpDisplay = true;
|
|
9
|
+
options = [];
|
|
10
|
+
positionals = [
|
|
11
|
+
{
|
|
12
|
+
name: "shell",
|
|
13
|
+
type: ArgumentValueTypeName.STRING,
|
|
14
|
+
allowableValues: Object.values(ShellType),
|
|
15
|
+
description: "Shell type",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "args",
|
|
19
|
+
type: ArgumentValueTypeName.STRING,
|
|
20
|
+
isVarargMultiple: true,
|
|
21
|
+
isVarargOptional: true,
|
|
22
|
+
description: "Shell-specific completion context arguments",
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
async execute(context, argumentValues) {
|
|
26
|
+
const completionService = context.getServiceById(COMPLETION_SERVICE_ID);
|
|
27
|
+
const printerService = context.getServiceById(PRINTER_SERVICE_ID);
|
|
28
|
+
const shellType = argumentValues.shell;
|
|
29
|
+
const args = (argumentValues.args || []);
|
|
30
|
+
const completionContext = completionService.parseCompletionContext(shellType, args);
|
|
31
|
+
const completions = await completionService.generateCompletions(shellType, completionContext.line, completionContext.cursorPosition);
|
|
32
|
+
const output = completionService.formatCompletions(shellType, completions);
|
|
33
|
+
if (output.length > 0) {
|
|
34
|
+
await printerService.print(output + "\n");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type GroupCommand from "../../../api/command/GroupCommand.ts";
|
|
2
|
+
import type SubCommand from "../../../api/command/SubCommand.ts";
|
|
3
|
+
import type Context from "../../../api/Context.ts";
|
|
4
|
+
import type { CompletionIntegrationSubCommand } from "./CompletionIntegrationSubCommand.ts";
|
|
5
|
+
import type { CompletionCompleteSubCommand } from "./CompletionCompleteSubCommand.ts";
|
|
6
|
+
export declare class CompletionGroupCommand implements GroupCommand {
|
|
7
|
+
readonly name = "completion";
|
|
8
|
+
readonly description = "Manage shell auto-completion";
|
|
9
|
+
readonly enableConfiguration = false;
|
|
10
|
+
readonly memberSubCommands: ReadonlyArray<SubCommand>;
|
|
11
|
+
constructor(integrationCommand: CompletionIntegrationSubCommand, completeCommand: CompletionCompleteSubCommand);
|
|
12
|
+
execute(_context: Context): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=CompletionGroupCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompletionGroupCommand.d.ts","sourceRoot":"","sources":["../../../../../src/service/completion/command/CompletionGroupCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,YAAY,MAAM,sCAAsC,CAAC;AACrE,OAAO,KAAK,UAAU,MAAM,oCAAoC,CAAC;AACjE,OAAO,KAAK,OAAO,MAAM,yBAAyB,CAAC;AACnD,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,sCAAsC,CAAC;AAC5F,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AAEtF,qBAAa,sBAAuB,YAAW,YAAY;IACzD,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,QAAQ,CAAC,WAAW,kCAAkC;IACtD,QAAQ,CAAC,mBAAmB,SAAS;IACrC,QAAQ,CAAC,iBAAiB,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;gBAGpD,kBAAkB,EAAE,+BAA+B,EACnD,eAAe,EAAE,4BAA4B;IAKzC,OAAO,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAChD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export class CompletionGroupCommand {
|
|
2
|
+
name = "completion";
|
|
3
|
+
description = "Manage shell auto-completion";
|
|
4
|
+
enableConfiguration = false;
|
|
5
|
+
memberSubCommands;
|
|
6
|
+
constructor(integrationCommand, completeCommand) {
|
|
7
|
+
this.memberSubCommands = [integrationCommand, completeCommand];
|
|
8
|
+
}
|
|
9
|
+
async execute(_context) { }
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type SubCommand from "../../../api/command/SubCommand.ts";
|
|
2
|
+
import type Option from "../../../api/argument/Option.ts";
|
|
3
|
+
import type Positional from "../../../api/argument/Positional.ts";
|
|
4
|
+
import type Context from "../../../api/Context.ts";
|
|
5
|
+
import { type ArgumentValues } from "../../../api/argument/ArgumentValueTypes.ts";
|
|
6
|
+
export declare class CompletionIntegrationSubCommand implements SubCommand {
|
|
7
|
+
readonly name = "integration";
|
|
8
|
+
readonly description = "Install shell completion integration";
|
|
9
|
+
readonly enableConfiguration = false;
|
|
10
|
+
readonly options: ReadonlyArray<Option>;
|
|
11
|
+
readonly positionals: ReadonlyArray<Positional>;
|
|
12
|
+
execute(context: Context, argumentValues: ArgumentValues): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=CompletionIntegrationSubCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompletionIntegrationSubCommand.d.ts","sourceRoot":"","sources":["../../../../../src/service/completion/command/CompletionIntegrationSubCommand.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,UAAU,MAAM,oCAAoC,CAAC;AACjE,OAAO,KAAK,MAAM,MAAM,iCAAiC,CAAC;AAC1D,OAAO,KAAK,UAAU,MAAM,qCAAqC,CAAC;AAClE,OAAO,KAAK,OAAO,MAAM,yBAAyB,CAAC;AACnD,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,6CAA6C,CAAC;AAMrD,qBAAa,+BAAgC,YAAW,UAAU;IAChE,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,0CAA0C;IAC9D,QAAQ,CAAC,mBAAmB,SAAS;IAErC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAOrC;IAEF,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAO7C;IAEI,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CA4D/E"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { ArgumentValueTypeName, } from "../../../api/argument/ArgumentValueTypes.js";
|
|
3
|
+
import { COMPLETION_SERVICE_ID, ShellType } from "../../../api/service/core/CompletionService.js";
|
|
4
|
+
import { Icon, PRINTER_SERVICE_ID } from "../../../api/service/core/PrinterService.js";
|
|
5
|
+
export class CompletionIntegrationSubCommand {
|
|
6
|
+
name = "integration";
|
|
7
|
+
description = "Install shell completion integration";
|
|
8
|
+
enableConfiguration = false;
|
|
9
|
+
options = [
|
|
10
|
+
{
|
|
11
|
+
name: "config-path",
|
|
12
|
+
type: ArgumentValueTypeName.STRING,
|
|
13
|
+
isOptional: true,
|
|
14
|
+
description: "Path to shell configuration file",
|
|
15
|
+
},
|
|
16
|
+
];
|
|
17
|
+
positionals = [
|
|
18
|
+
{
|
|
19
|
+
name: "shell",
|
|
20
|
+
type: ArgumentValueTypeName.STRING,
|
|
21
|
+
allowableValues: Object.values(ShellType),
|
|
22
|
+
description: "Shell type to configure",
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
async execute(context, argumentValues) {
|
|
26
|
+
const completionService = context.getServiceById(COMPLETION_SERVICE_ID);
|
|
27
|
+
const printerService = context.getServiceById(PRINTER_SERVICE_ID);
|
|
28
|
+
const shellType = argumentValues.shell;
|
|
29
|
+
const configPathArg = argumentValues["config-path"];
|
|
30
|
+
const isValid = await completionService.validateShellEnvironment(shellType);
|
|
31
|
+
if (!isValid) {
|
|
32
|
+
await printerService.warn(`Shell '${shellType}' was not detected in the current environment. Proceeding anyway.\n`, Icon.ALERT);
|
|
33
|
+
}
|
|
34
|
+
const configPath = configPathArg || completionService.getDefaultConfigPath(shellType);
|
|
35
|
+
const cliName = context.cliConfig.name;
|
|
36
|
+
const bootstrapScript = completionService.getBootstrapScript(shellType, cliName, process.execPath);
|
|
37
|
+
const beginMarker = `# BEGIN ${cliName} completion`;
|
|
38
|
+
const endMarker = `# END ${cliName} completion`;
|
|
39
|
+
const block = `${beginMarker}\n${bootstrapScript}\n${endMarker}`;
|
|
40
|
+
let existingContent = "";
|
|
41
|
+
try {
|
|
42
|
+
existingContent = await Bun.file(configPath).text();
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// File doesn't exist yet
|
|
46
|
+
}
|
|
47
|
+
let newContent;
|
|
48
|
+
const beginIdx = existingContent.indexOf(beginMarker);
|
|
49
|
+
const endIdx = existingContent.indexOf(endMarker);
|
|
50
|
+
if (beginIdx !== -1 && endIdx !== -1) {
|
|
51
|
+
newContent =
|
|
52
|
+
existingContent.substring(0, beginIdx) +
|
|
53
|
+
block +
|
|
54
|
+
existingContent.substring(endIdx + endMarker.length);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const separator = existingContent.length > 0 && !existingContent.endsWith("\n")
|
|
58
|
+
? "\n\n"
|
|
59
|
+
: existingContent.length > 0
|
|
60
|
+
? "\n"
|
|
61
|
+
: "";
|
|
62
|
+
newContent = existingContent + separator + block + "\n";
|
|
63
|
+
}
|
|
64
|
+
await Bun.write(configPath, newContent);
|
|
65
|
+
await printerService.info(`Shell completion installed for ${shellType}. Restart your shell or run 'source ${configPath}' to activate.\n`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
// Reference: https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html
|
|
5
|
+
export default class BashShellHandler {
|
|
6
|
+
getDefaultConfigPath() {
|
|
7
|
+
return join(homedir(), ".bashrc");
|
|
8
|
+
}
|
|
9
|
+
getBootstrapScript(cliName, executablePath) {
|
|
10
|
+
return [
|
|
11
|
+
`_${cliName}_completions() {`,
|
|
12
|
+
` local IFS=$'\\n'`,
|
|
13
|
+
` COMPREPLY=( $("${executablePath}" completion:complete bash "\${COMP_LINE}" "\${COMP_POINT}" 2>/dev/null) )`,
|
|
14
|
+
`}`,
|
|
15
|
+
`complete -F _${cliName}_completions ${cliName}`,
|
|
16
|
+
].join("\n");
|
|
17
|
+
}
|
|
18
|
+
validateEnvironment() {
|
|
19
|
+
const shell = process.env.SHELL || "";
|
|
20
|
+
if (shell.endsWith("/bash")) {
|
|
21
|
+
return Promise.resolve(true);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const result = Bun.spawnSync(["bash", "--version"]);
|
|
25
|
+
return Promise.resolve(result.exitCode === 0);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return Promise.resolve(false);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
formatCompletions(completions) {
|
|
32
|
+
return completions.map((c) => c.value).join("\n");
|
|
33
|
+
}
|
|
34
|
+
parseCompletionContext(args) {
|
|
35
|
+
const line = args[0] || "";
|
|
36
|
+
const cursorPosition = parseInt(args[1] || "0", 10) || line.length;
|
|
37
|
+
return { line, cursorPosition };
|
|
38
|
+
}
|
|
39
|
+
}
|