@shell-shock/plugin-completions 0.2.23 → 0.2.24

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.
@@ -1 +1 @@
1
- {"version":3,"file":"powershell-command.mjs","names":[],"sources":["../../src/components/powershell-command.tsx"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Shell Shock\n\n This code was released as part of the Shell Shock project. Shell Shock\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/shell-shock.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/shell-shock\n Documentation: https://docs.stormsoftware.com/projects/shell-shock\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { code } from \"@alloy-js/core\";\nimport {\n FunctionDeclaration,\n IfStatement,\n InterfaceDeclaration,\n VarDeclaration\n} from \"@alloy-js/typescript\";\nimport { ReflectionKind } from \"@powerlines/deepkit/vendor/type\";\nimport { Spacing } from \"@powerlines/plugin-alloy/core\";\nimport { usePowerlines } from \"@powerlines/plugin-alloy/core/contexts/context\";\nimport {\n InterfaceMember,\n TypescriptFile\n} from \"@powerlines/plugin-alloy/typescript\";\nimport {\n TSDoc,\n TSDocDefaultValue,\n TSDocRemarks\n} from \"@powerlines/plugin-alloy/typescript/components/tsdoc\";\nimport { getAppBin, getAppTitle } from \"@shell-shock/core/plugin-utils\";\nimport { joinPaths } from \"@stryke/path\";\nimport { camelCase } from \"@stryke/string-format/camel-case\";\nimport { snakeCase } from \"@stryke/string-format/snake-case\";\nimport { exec } from \"../helpers/complete-command\";\nimport { CompletionDirective } from \"../helpers/completion-directive-constants\";\nimport type { CompletionsPluginContext } from \"../types/plugin\";\n\n/**\n * The PowerShell Completions commands' handler wrapper for the Shell Shock project.\n */\nexport function PowerShellCompletionsCommand() {\n const context = usePowerlines<CompletionsPluginContext>();\n\n return (\n <TypescriptFile\n path={joinPaths(\n context.entryPath,\n \"completions\",\n \"powershell\",\n \"command.ts\"\n )}\n imports={{\n \"node:os\": [\"os\"],\n \"node:fs/promises\": [\"readFile\", \"writeFile\"]\n }}\n builtinImports={{\n \"shell-shock:console\": [\n \"colors\",\n \"writeLine\",\n \"success\",\n \"warn\",\n \"stripAnsi\"\n ]\n }}>\n <TSDoc heading=\"Options for the PowerShell completions command.\" />\n <InterfaceDeclaration export name=\"PowerShellCompletionsOptions\">\n <TSDoc heading=\"The path to write the completion script to.\">\n <TSDocRemarks>{`If no extension is provided, the \\`.ps1\\` extension will be used.`}</TSDocRemarks>\n <TSDocDefaultValue\n type={ReflectionKind.string}\n defaultValue={`${getAppBin(context)}-completions.ps1`}\n />\n </TSDoc>\n <InterfaceMember name=\"script\" optional type=\"string | true\" />\n <Spacing />\n <TSDoc heading=\"The PowerShell configuration file to append the completion script to.\">\n <TSDocRemarks>{`The generated completion script will be appended to the specified configuration file. Possible values for the PowerShell configuration file include: \\\\n- \\`~/.config/powershell/Microsoft.PowerShell_profile.ps1\\``}</TSDocRemarks>\n <TSDocDefaultValue\n type={ReflectionKind.string}\n defaultValue=\"~/.config/powershell/Microsoft.PowerShell_profile.ps1\"\n />\n </TSDoc>\n <InterfaceMember name=\"config\" optional type=\"string | true\" />\n </InterfaceDeclaration>\n <Spacing />\n <TSDoc heading=\"Handler logic for the \\`completions powershell\\` command.\"></TSDoc>\n <FunctionDeclaration\n export\n default\n async\n name=\"handler\"\n parameters={[\n { name: \"options\", type: \"PowerShellCompletionsOptions\" }\n ]}>\n <VarDeclaration\n const\n name=\"completions\"\n type=\"string\"\n initializer={code`# powershell completion for ${getAppTitle(context)} -*- shell-script -*-\n\n [Console]::OutputEncoding = [System.Text.Encoding]::UTF8\n function __${snakeCase(getAppBin(context))}_debug {\n if ($env:BASH_COMP_DEBUG_FILE) {\n \"$args\" | Out-File -Append -FilePath \"$env:BASH_COMP_DEBUG_FILE\"\n }\n }\n\n filter __${camelCase(getAppBin(context))}_escapeStringWithSpecialChars {\n $_ -replace '\\\\s|#|@|\\\\$|;|,|''|\\\\{|\\\\}|\\\\(|\\\\)|\"|\\\\||<|>|&','\\`$&'\n }\n\n[scriptblock]$__${camelCase(getAppBin(context))}CompleterBlock = {\n param(\n $WordToComplete,\n $CommandAst,\n $CursorPosition\n )\n\n # Get the current command-line and convert into a string\n $Command = $CommandAst.CommandElements\n $Command = \"$Command\"\n\n __${camelCase(getAppBin(context))}_debug \"\"\n __${camelCase(getAppBin(context))}_debug \"========= starting completion logic ==========\"\n __${camelCase(getAppBin(context))}_debug \"WordToComplete: $WordToComplete Command: $Command CursorPosition: $CursorPosition\"\n\n # The user could have moved the cursor backwards on the command-line.\n # We need to trigger completion from the $CursorPosition location, so we need\n # to truncate the command-line ($Command) up to the $CursorPosition location.\n # Make sure the $Command is longer then the $CursorPosition before we truncate.\n # This happens because the $Command does not include the last space.\n if ($Command.Length -gt $CursorPosition) {\n $Command = $Command.Substring(0, $CursorPosition)\n }\n __${camelCase(getAppBin(context))}_debug \"Truncated command: $Command\"\n\n $ShellCompDirectiveError=${CompletionDirective.CompletionDirectiveError}\n $ShellCompDirectiveNoSpace=${CompletionDirective.CompletionDirectiveNoSpace}\n $ShellCompDirectiveNoFileComp=${\n CompletionDirective.CompletionDirectiveNoFileComp\n }\n $ShellCompDirectiveFilterFileExt=${\n CompletionDirective.CompletionDirectiveFilterFileExt\n }\n $ShellCompDirectiveFilterDirs=${\n CompletionDirective.CompletionDirectiveFilterDirs\n }\n $ShellCompDirectiveKeepOrder=${\n CompletionDirective.CompletionDirectiveKeepOrder\n }\n\n # Prepare the command to request completions for the program.\n # Split the command at the first space to separate the program and arguments.\n $Program, $Arguments = $Command.Split(\" \", 2)\n\n $QuotedArgs = ($Arguments -split ' ' | ForEach-Object { \"'\" + ($_ -replace \"'\", \"''\") + \"'\" }) -join ' '\n __${camelCase(getAppBin(context))}_debug \"QuotedArgs: $QuotedArgs\"\n\n $RequestComp = \"& ${exec} complete '--' $QuotedArgs\"\n __${camelCase(getAppBin(context))}_debug \"RequestComp: $RequestComp\"\n\n # we cannot use $WordToComplete because it\n # has the wrong values if the cursor was moved\n # so use the last argument\n if ($WordToComplete -ne \"\" ) {\n $WordToComplete = $Arguments.Split(\" \")[-1]\n }\n __${camelCase(getAppBin(context))}_debug \"New WordToComplete: $WordToComplete\"\n\n\n # Check for flag with equal sign\n $IsEqualFlag = ($WordToComplete -Like \"--*=*\" )\n if ( $IsEqualFlag ) {\n __${camelCase(getAppBin(context))}_debug \"Completing equal sign flag\"\n # Remove the flag part\n $Flag, $WordToComplete = $WordToComplete.Split(\"=\", 2)\n }\n\n if ( $WordToComplete -eq \"\" -And ( -Not $IsEqualFlag )) {\n # If the last parameter is complete (there is a space following it)\n # We add an extra empty parameter so we can indicate this to the go method.\n __${camelCase(getAppBin(context))}_debug \"Adding extra empty parameter\"\n # PowerShell 7.2+ changed the way how the arguments are passed to executables,\n # so for pre-7.2 or when Legacy argument passing is enabled we need to use\n if ($PSVersionTable.PsVersion -lt [version]'7.2.0' -or\n ($PSVersionTable.PsVersion -lt [version]'7.3.0' -and -not [ExperimentalFeature]::IsEnabled(\"PSNativeCommandArgumentPassing\")) -or\n (($PSVersionTable.PsVersion -ge [version]'7.3.0' -or [ExperimentalFeature]::IsEnabled(\"PSNativeCommandArgumentPassing\")) -and\n $PSNativeCommandArgumentPassing -eq 'Legacy')) {\n $RequestComp=\"$RequestComp\" + ' \\`\"\\`\"'\n } else {\n $RequestComp = \"$RequestComp\" + ' \"\"'\n }\n }\n\n __${camelCase(getAppBin(context))}_debug \"Calling $RequestComp\"\n # First disable ActiveHelp which is not supported for Powershell\n $env:ActiveHelp = 0\n\n # call the command store the output in $out and redirect stderr and stdout to null\n # $Out is an array contains each line per element\n Invoke-Expression -OutVariable out \"$RequestComp\" 2>&1 | Out-Null\n\n # get directive from last line\n [int]$Directive = $Out[-1].TrimStart(':')\n if ($Directive -eq \"\") {\n # There is no directive specified\n $Directive = 0\n }\n __${camelCase(getAppBin(context))}_debug \"The completion directive is: $Directive\"\n\n # remove directive (last element) from out\n $Out = $Out | Where-Object { $_ -ne $Out[-1] }\n __${camelCase(getAppBin(context))}_debug \"The completions are: $Out\"\n if (($Directive -band $ShellCompDirectiveError) -ne 0 ) {\n # Error code. No completion.\n __${camelCase(getAppBin(context))}_debug \"Received error from custom completion go code\"\n return\n }\n\n $Longest = 0\n [Array]$Values = $Out | ForEach-Object {\n # Split the output in name and description\n $Name, $Description = $_.Split(\"\\`t\", 2)\n __${camelCase(getAppBin(context))}_debug \"Name: $Name Description: $Description\"\n\n # Look for the longest completion so that we can format things nicely\n if ($Longest -lt $Name.Length) {\n $Longest = $Name.Length\n }\n\n # Set the description to a one space string if there is none set.\n # This is needed because the CompletionResult does not accept an empty string as argument\n if (-Not $Description) {\n $Description = \" \"\n }\n @{ Name = \"$Name\"; Description = \"$Description\" }\n }\n\n\n $Space = \" \"\n if (($Directive -band $ShellCompDirectiveNoSpace) -ne 0 ) {\n # remove the space here\n __${camelCase(getAppBin(context))}_debug \"ShellCompDirectiveNoSpace is called\"\n $Space = \"\"\n }\n\n if ((($Directive -band $ShellCompDirectiveFilterFileExt) -ne 0 ) -or\n (($Directive -band $ShellCompDirectiveFilterDirs) -ne 0 )) {\n __${camelCase(getAppBin(context))}_debug \"ShellCompDirectiveFilterFileExt ShellCompDirectiveFilterDirs are not supported\"\n\n # return here to prevent the completion of the extensions\n return\n }\n\n $Values = $Values | Where-Object {\n # filter the result\n $_.Name -like \"$WordToComplete*\"\n\n # Join the flag back if we have an equal sign flag\n if ( $IsEqualFlag ) {\n __${camelCase(getAppBin(context))}_debug \"Join the equal sign flag back to the completion value\"\n $_.Name = $Flag + \"=\" + $_.Name\n }\n }\n\n # we sort the values in ascending order by name if keep order isn't passed\n if (($Directive -band $ShellCompDirectiveKeepOrder) -eq 0 ) {\n $Values = $Values | Sort-Object -Property Name\n }\n\n if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) {\n __${camelCase(getAppBin(context))}_debug \"ShellCompDirectiveNoFileComp is called\"\n\n if ($Values.Length -eq 0) {\n # Just print an empty string here so the\n # shell does not start to complete paths.\n # We cannot use CompletionResult here because\n # it does not accept an empty string as argument.\n \"\"\n return\n }\n }\n\n # Get the current mode\n $Mode = (Get-PSReadLineKeyHandler | Where-Object { $_.Key -eq \"Tab\" }).Function\n __${camelCase(getAppBin(context))}_debug \"Mode: $Mode\"\n\n $Values | ForEach-Object {\n\n # store temporary because switch will overwrite $_\n $comp = $_\n\n # PowerShell supports three different completion modes\n # - TabCompleteNext (default windows style - on each key press the next option is displayed)\n # - Complete (works like bash)\n # - MenuComplete (works like zsh)\n # You set the mode with Set-PSReadLineKeyHandler -Key Tab -Function <mode>\n\n # CompletionResult Arguments:\n # 1) CompletionText text to be used as the auto completion result\n # 2) ListItemText text to be displayed in the suggestion list\n # 3) ResultType type of completion result\n # 4) ToolTip text for the tooltip with details about the object\n\n switch ($Mode) {\n\n # bash like\n \"Complete\" {\n\n if ($Values.Length -eq 1) {\n __${camelCase(\n getAppBin(context)\n )}_debug \"Only one completion left\"\n\n # insert space after value\n [System.Management.Automation.CompletionResult]::new($($comp.Name | __${name}_escapeStringWithSpecialChars) + $Space, \"$($comp.Name)\", 'ParameterValue', \"$($comp.Description)\")\n\n } else {\n # Add the proper number of spaces to align the descriptions\n while($comp.Name.Length -lt $Longest) {\n $comp.Name = $comp.Name + \" \"\n }\n\n # Check for empty description and only add parentheses if needed\n if ($($comp.Description) -eq \" \" ) {\n $Description = \"\"\n } else {\n $Description = \" ($($comp.Description))\"\n }\n\n [System.Management.Automation.CompletionResult]::new(\"$($comp.Name)$Description\", \"$($comp.Name)$Description\", 'ParameterValue', \"$($comp.Description)\")\n }\n }\n\n # zsh like\n \"MenuComplete\" {\n # insert space after value\n # MenuComplete will automatically show the ToolTip of\n # the highlighted value at the bottom of the suggestions.\n [System.Management.Automation.CompletionResult]::new($($comp.Name | __${name}_escapeStringWithSpecialChars) + $Space, \"$($comp.Name)\", 'ParameterValue', \"$($comp.Description)\")\n }\n\n # TabCompleteNext and in case we get something unknown\n Default {\n # Like MenuComplete but we don't want to add a space here because\n # the user need to press space anyway to get the completion.\n # Description will not be shown because that's not possible with TabCompleteNext\n [System.Management.Automation.CompletionResult]::new($($comp.Name | __${name}_escapeStringWithSpecialChars), \"$($comp.Name)\", 'ParameterValue', \"$($comp.Description)\")\n }\n }\n\n }\n}\n\nRegister-ArgumentCompleter -CommandName '${getAppBin(\n context\n )}' -ScriptBlock $__${camelCase(getAppBin(context))}CompleterBlock\n\\`); `}\n />\n <Spacing />\n <IfStatement condition={code`options.config`}>\n <VarDeclaration\n let\n name=\"configFilePath\"\n type=\"string\"\n initializer={code`options.config === true ? \"~/.config/powershell/Microsoft.PowerShell_profile.ps1\" : options.config`}\n />\n <Spacing />\n <IfStatement condition={code`configFilePath.startsWith(\"~\")`}>\n {code`configFilePath = join(os.homedir(), configFilePath.replace(\"~\", \"\")); `}\n </IfStatement>\n <Spacing />\n <VarDeclaration\n let\n name=\"configFileContent\"\n type=\"string\"\n initializer={code`\"\";`}\n />\n <Spacing />\n {code`try {\n configFileContent = await readFile(configFilePath, \"utf8\");\n } catch (error) {\n if (error.code === \"ENOENT\") {\n // If the file doesn't exist, we can create it later when writing the completion script.\n warn(\\`Configuration file \\${colors.bold(configFilePath)} does not exist. It will be created when the completion script is written.\\`);\n } else {\n return { error };\n }\n }\n\n await writeFile(configFilePath, \\`\\${configFileContent}\\\\n\\\\n\\${stripAnsi(completions)}\\`);\n\n success(\\`${getAppTitle(context)} PowerShell completion script has been generated and appended to \\${colors.bold(configFilePath)}. Please restart your terminal or run \\`source \\${configFilePath}\\` to apply the changes.\\`); `}\n </IfStatement>\n <Spacing />\n <IfStatement condition={code`options.script`}>\n {code`const outputPath = options.script === true ? \"${getAppBin(context)}-completions.powershell\" : options.script;\n await writeFile(outputPath, stripAnsi(completions));\n\n success(\\`${getAppTitle(context)} PowerShell completion script has been generated at \\${colors.bold(outputPath)}.\\`);`}\n </IfStatement>\n <Spacing />\n <IfStatement condition={code`!options.config && !options.script`}>\n {code`writeLine(\" ------------------------------------------------- \");\n writeLine(completions);\n writeLine(\" ------------------------------------------------- \");`}\n </IfStatement>\n </FunctionDeclaration>\n </TypescriptFile>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"powershell-command.mjs","names":[],"sources":["../../src/components/powershell-command.tsx"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Shell Shock\n\n This code was released as part of the Shell Shock project. Shell Shock\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/shell-shock.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/shell-shock\n Documentation: https://docs.stormsoftware.com/projects/shell-shock\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { code, computed } from \"@alloy-js/core\";\nimport {\n FunctionDeclaration,\n IfStatement,\n InterfaceDeclaration,\n VarDeclaration\n} from \"@alloy-js/typescript\";\nimport { ReflectionKind } from \"@powerlines/deepkit/vendor/type\";\nimport { Spacing } from \"@powerlines/plugin-alloy/core\";\nimport { usePowerlines } from \"@powerlines/plugin-alloy/core/contexts/context\";\nimport {\n InterfaceMember,\n TypescriptFile\n} from \"@powerlines/plugin-alloy/typescript\";\nimport {\n TSDoc,\n TSDocDefaultValue,\n TSDocRemarks\n} from \"@powerlines/plugin-alloy/typescript/components/tsdoc\";\nimport { getAppBin, getAppTitle } from \"@shell-shock/core/plugin-utils\";\nimport { joinPaths } from \"@stryke/path\";\nimport { camelCase } from \"@stryke/string-format/camel-case\";\nimport { EXEC_COMMAND } from \"../helpers/complete-command\";\nimport { CompletionDirective } from \"../helpers/completion-directive-constants\";\nimport type { CompletionsPluginContext } from \"../types/plugin\";\n\n/**\n * The PowerShell Completions commands' handler wrapper for the Shell Shock project.\n */\nexport function PowerShellCompletionsCommand() {\n const context = usePowerlines<CompletionsPluginContext>();\n\n const bin = computed(() => getAppBin(context));\n const name = computed(() => camelCase(bin.value));\n\n return (\n <TypescriptFile\n path={joinPaths(\n context.entryPath,\n \"completions\",\n \"powershell\",\n \"command.ts\"\n )}\n imports={{\n \"node:os\": [\"os\"],\n \"node:fs/promises\": [\"readFile\", \"writeFile\"]\n }}\n builtinImports={{\n \"shell-shock:console\": [\n \"colors\",\n \"writeLine\",\n \"success\",\n \"warn\",\n \"stripAnsi\"\n ]\n }}>\n <TSDoc heading=\"Options for the PowerShell completions command.\" />\n <InterfaceDeclaration export name=\"PowerShellCompletionsOptions\">\n <TSDoc heading=\"The path to write the completion script to.\">\n <TSDocRemarks>{`If no extension is provided, the \\`.ps1\\` extension will be used.`}</TSDocRemarks>\n <TSDocDefaultValue\n type={ReflectionKind.string}\n defaultValue={`${bin.value}-completions.ps1`}\n />\n </TSDoc>\n <InterfaceMember name=\"script\" optional type=\"string | true\" />\n <Spacing />\n <TSDoc heading=\"The PowerShell configuration file to append the completion script to.\">\n <TSDocRemarks>{`The generated completion script will be appended to the specified configuration file. Possible values for the PowerShell configuration file include: \\\\n- \\`~/.config/powershell/Microsoft.PowerShell_profile.ps1\\``}</TSDocRemarks>\n <TSDocDefaultValue\n type={ReflectionKind.string}\n defaultValue=\"~/.config/powershell/Microsoft.PowerShell_profile.ps1\"\n />\n </TSDoc>\n <InterfaceMember name=\"config\" optional type=\"string | true\" />\n </InterfaceDeclaration>\n <Spacing />\n <TSDoc heading=\"Handler logic for the \\`completions powershell\\` command.\"></TSDoc>\n <FunctionDeclaration\n export\n default\n async\n name=\"handler\"\n parameters={[\n { name: \"options\", type: \"PowerShellCompletionsOptions\" }\n ]}>\n <VarDeclaration\n const\n name=\"completions\"\n type=\"string\"\n initializer={code` \\`# powershell completion for ${getAppTitle(\n context\n )} -*- shell-script -*-\n\n [Console]::OutputEncoding = [System.Text.Encoding]::UTF8\n function __${name.value}_debug {\n if ($env:BASH_COMP_DEBUG_FILE) {\n \"$args\" | Out-File -Append -FilePath \"$env:BASH_COMP_DEBUG_FILE\"\n }\n }\n\n filter __${name.value}_escapeStringWithSpecialChars {\n $_ -replace '\\\\s|#|@|\\\\$|;|,|''|\\\\{|\\\\}|\\\\(|\\\\)|\"|\\\\||<|>|&','\\\\\\`$&'\n }\n\n[scriptblock]$__${name.value}CompleterBlock = {\n param(\n $WordToComplete,\n $CommandAst,\n $CursorPosition\n )\n\n # Get the current command-line and convert into a string\n $Command = $CommandAst.CommandElements\n $Command = \"$Command\"\n\n __${name.value}_debug \"\"\n __${name.value}_debug \"========= starting completion logic ==========\"\n __${name.value}_debug \"WordToComplete: $WordToComplete Command: $Command CursorPosition: $CursorPosition\"\n\n )}_debug \"WordToComplete: $WordToComplete Command: $Command CursorPosition: $CursorPosition\"\n\n # The user could have moved the cursor backwards on the command-line.\n # We need to trigger completion from the $CursorPosition location, so we need\n # to truncate the command-line ($Command) up to the $CursorPosition location.\n # Make sure the $Command is longer then the $CursorPosition before we truncate.\n # This happens because the $Command does not include the last space.\n if ($Command.Length -gt $CursorPosition) {\n $Command = $Command.Substring(0, $CursorPosition)\n }\n __${name.value}_debug \"Truncated command: $Command\"\n\n $ShellCompDirectiveError=${CompletionDirective.CompletionDirectiveError}\n $ShellCompDirectiveNoSpace=${CompletionDirective.CompletionDirectiveNoSpace}\n $ShellCompDirectiveNoFileComp=${\n CompletionDirective.CompletionDirectiveNoFileComp\n }\n $ShellCompDirectiveFilterFileExt=${\n CompletionDirective.CompletionDirectiveFilterFileExt\n }\n $ShellCompDirectiveFilterDirs=${\n CompletionDirective.CompletionDirectiveFilterDirs\n }\n $ShellCompDirectiveKeepOrder=${\n CompletionDirective.CompletionDirectiveKeepOrder\n }\n\n # Prepare the command to request completions for the program.\n # Split the command at the first space to separate the program and arguments.\n $Program, $Arguments = $Command.Split(\" \", 2)\n\n $QuotedArgs = ($Arguments -split ' ' | ForEach-Object { \"'\" + ($_ -replace \"'\", \"''\") + \"'\" }) -join ' '\n __${name.value}_debug \"QuotedArgs: $QuotedArgs\"\n\n $RequestComp = \"& ${EXEC_COMMAND} complete '--' $QuotedArgs\"\n __${name.value}_debug \"RequestComp: $RequestComp\"\n\n # we cannot use $WordToComplete because it\n # has the wrong values if the cursor was moved\n # so use the last argument\n if ($WordToComplete -ne \"\" ) {\n $WordToComplete = $Arguments.Split(\" \")[-1]\n }\n __${name.value}_debug \"New WordToComplete: $WordToComplete\"\n\n\n # Check for flag with equal sign\n $IsEqualFlag = ($WordToComplete -Like \"--*=*\" )\n if ( $IsEqualFlag ) {\n __${name.value}_debug \"Completing equal sign flag\"\n # Remove the flag part\n $Flag, $WordToComplete = $WordToComplete.Split(\"=\", 2)\n }\n\n if ( $WordToComplete -eq \"\" -And ( -Not $IsEqualFlag )) {\n # If the last parameter is complete (there is a space following it)\n # We add an extra empty parameter so we can indicate this to the go method.\n __${name.value}_debug \"Adding extra empty parameter\"\n # PowerShell 7.2+ changed the way how the arguments are passed to executables,\n # so for pre-7.2 or when Legacy argument passing is enabled we need to use\n if ($PSVersionTable.PsVersion -lt [version]'7.2.0' -or\n ($PSVersionTable.PsVersion -lt [version]'7.3.0' -and -not [ExperimentalFeature]::IsEnabled(\"PSNativeCommandArgumentPassing\")) -or\n (($PSVersionTable.PsVersion -ge [version]'7.3.0' -or [ExperimentalFeature]::IsEnabled(\"PSNativeCommandArgumentPassing\")) -and\n $PSNativeCommandArgumentPassing -eq 'Legacy')) {\n $RequestComp=\"$RequestComp\" + ' \\\\\\`\"\\\\\\`\"'\n } else {\n $RequestComp = \"$RequestComp\" + ' \"\"'\n }\n }\n\n __${name.value}_debug \"Calling $RequestComp\"\n # First disable ActiveHelp which is not supported for Powershell\n $env:ActiveHelp = 0\n\n # call the command store the output in $out and redirect stderr and stdout to null\n # $Out is an array contains each line per element\n Invoke-Expression -OutVariable out \"$RequestComp\" 2>&1 | Out-Null\n\n # get directive from last line\n [int]$Directive = $Out[-1].TrimStart(':')\n if ($Directive -eq \"\") {\n # There is no directive specified\n $Directive = 0\n }\n __${name.value}_debug \"The completion directive is: $Directive\"\n\n # remove directive (last element) from out\n $Out = $Out | Where-Object { $_ -ne $Out[-1] }\n __${name.value}_debug \"The completions are: $Out\"\n if (($Directive -band $ShellCompDirectiveError) -ne 0 ) {\n # Error code. No completion.\n __${name.value}_debug \"Received error from custom completion go code\"\n return\n }\n\n ${bin.value}_debug \"Received error from custom completion go code\"\n return\n }\n\n $Longest = 0\n [Array]$Values = $Out | ForEach-Object {\n # Split the output in name and description\n $Name, $Description = $_.Split(\"\\\\\\`t\", 2)\n __${name.value}_debug \"Name: $Name Description: $Description\"\n\n # Look for the longest completion so that we can format things nicely\n if ($Longest -lt $Name.Length) {\n $Longest = $Name.Length\n }\n\n # Set the description to a one space string if there is none set.\n # This is needed because the CompletionResult does not accept an empty string as argument\n if (-Not $Description) {\n $Description = \" \"\n }\n @{ Name = \"$Name\"; Description = \"$Description\" }\n }\n\n\n $Space = \" \"\n if (($Directive -band $ShellCompDirectiveNoSpace) -ne 0 ) {\n # remove the space here\n __${name.value}_debug \"ShellCompDirectiveNoSpace is called\"\n $Space = \"\"\n }\n\n if ((($Directive -band $ShellCompDirectiveFilterFileExt) -ne 0 ) -or\n (($Directive -band $ShellCompDirectiveFilterDirs) -ne 0 )) {\n __${\n name.value\n }_debug \"ShellCompDirectiveFilterFileExt ShellCompDirectiveFilterDirs are not supported\"\n\n # return here to prevent the completion of the extensions\n return\n }\n\n $Values = $Values | Where-Object {\n # filter the result\n $_.Name -like \"$WordToComplete*\"\n\n # Join the flag back if we have an equal sign flag\n if ( $IsEqualFlag ) {\n __${\n name.value\n }_debug \"Join the equal sign flag back to the completion value\"\n $_.Name = $Flag + \"=\" + $_.Name\n }\n }\n\n # we sort the values in ascending order by name if keep order isn't passed\n if (($Directive -band $ShellCompDirectiveKeepOrder) -eq 0 ) {\n $Values = $Values | Sort-Object -Property Name\n }\n\n if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) {\n __${name.value}_debug \"ShellCompDirectiveNoFileComp is called\"\n\n if ($Values.Length -eq 0) {\n # Just print an empty string here so the\n # shell does not start to complete paths.\n # We cannot use CompletionResult here because\n # it does not accept an empty string as argument.\n \"\"\n return\n }\n }\n\n # Get the current mode\n $Mode = (Get-PSReadLineKeyHandler | Where-Object { $_.Key -eq \"Tab\" }).Function\n __${name.value}_debug \"Mode: $Mode\"\n\n $Values | ForEach-Object {\n\n # store temporary because switch will overwrite $_\n $comp = $_\n\n # PowerShell supports three different completion modes\n # - TabCompleteNext (default windows style - on each key press the next option is displayed)\n # - Complete (works like bash)\n # - MenuComplete (works like zsh)\n # You set the mode with Set-PSReadLineKeyHandler -Key Tab -Function <mode>\n\n # CompletionResult Arguments:\n # 1) CompletionText text to be used as the auto completion result\n # 2) ListItemText text to be displayed in the suggestion list\n # 3) ResultType type of completion result\n # 4) ToolTip text for the tooltip with details about the object\n\n switch ($Mode) {\n\n # bash like\n \"Complete\" {\n\n if ($Values.Length -eq 1) {\n __${name.value}_debug \"Only one completion left\"\n\n # insert space after value\n [System.Management.Automation.CompletionResult]::new($($comp.Name | __${\n name.value\n }_escapeStringWithSpecialChars) + $Space, \"$($comp.Name)\", 'ParameterValue', \"$($comp.Description)\")\n\n } else {\n # Add the proper number of spaces to align the descriptions\n while($comp.Name.Length -lt $Longest) {\n $comp.Name = $comp.Name + \" \"\n }\n\n # Check for empty description and only add parentheses if needed\n if ($($comp.Description) -eq \" \" ) {\n $Description = \"\"\n } else {\n $Description = \" ($($comp.Description))\"\n }\n\n [System.Management.Automation.CompletionResult]::new(\"$($comp.Name)$Description\", \"$($comp.Name)$Description\", 'ParameterValue', \"$($comp.Description)\")\n }\n }\n\n # zsh like\n \"MenuComplete\" {\n # insert space after value\n # MenuComplete will automatically show the ToolTip of\n # the highlighted value at the bottom of the suggestions.\n [System.Management.Automation.CompletionResult]::new($($comp.Name | __${\n name.value\n }_escapeStringWithSpecialChars) + $Space, \"$($comp.Name)\", 'ParameterValue', \"$($comp.Description)\")\n }\n\n # TabCompleteNext and in case we get something unknown\n Default {\n # Like MenuComplete but we don't want to add a space here because\n # the user need to press space anyway to get the completion.\n # Description will not be shown because that's not possible with TabCompleteNext\n [System.Management.Automation.CompletionResult]::new($($comp.Name | __${\n name.value\n }_escapeStringWithSpecialChars), \"$($comp.Name)\", 'ParameterValue', \"$($comp.Description)\")\n }\n }\n }\n}\n\nRegister-ArgumentCompleter -CommandName '${bin.value}' -ScriptBlock $__${\n name.value\n }CompleterBlock\n\\`; `}\n />\n <Spacing />\n <IfStatement condition={code`options.config`}>\n <VarDeclaration\n let\n name=\"configFilePath\"\n type=\"string\"\n initializer={code`options.config === true ? \"~/.config/powershell/Microsoft.PowerShell_profile.ps1\" : options.config`}\n />\n <Spacing />\n <IfStatement condition={code`configFilePath.startsWith(\"~\")`}>\n {code`configFilePath = join(os.homedir(), configFilePath.replace(\"~\", \"\")); `}\n </IfStatement>\n <Spacing />\n <VarDeclaration\n let\n name=\"configFileContent\"\n type=\"string\"\n initializer={code`\"\";`}\n />\n <Spacing />\n {code`try {\n configFileContent = await readFile(configFilePath, \"utf8\");\n } catch (error) {\n if (Error.isError(error) && error.code === \"ENOENT\") {\n // If the file doesn't exist, we can create it later when writing the completion script.\n warn(\\`Configuration file \\${colors.bold(configFilePath)} does not exist. It will be created when the completion script is written.\\`);\n } else {\n return { error };\n }\n }\n\n await writeFile(configFilePath, \\`\\${configFileContent}\\\\n\\\\n\\${stripAnsi(completions)}\\`);\n\n success(\\`${getAppTitle(\n context\n )} PowerShell completion script has been generated and appended to \\${colors.bold(configFilePath)}. Please restart your terminal or run \\`source \\${configFilePath}\\` to apply the changes.\\`); `}\n </IfStatement>\n <Spacing />\n <IfStatement condition={code`options.script`}>\n {code`const outputPath = options.script === true ? \"${\n bin.value\n }-completions.powershell\" : options.script;\n await writeFile(outputPath, stripAnsi(completions));\n\n success(\\`${getAppTitle(\n context\n )} PowerShell completion script has been generated at \\${colors.bold(outputPath)}.\\`);`}\n </IfStatement>\n <Spacing />\n <IfStatement condition={code`!options.config && !options.script`}>\n {code`writeLine(\" ------------------------------------------------- \");\n writeLine(completions);\n writeLine(\" ------------------------------------------------- \");`}\n </IfStatement>\n </FunctionDeclaration>\n </TypescriptFile>\n );\n}\n"],"mappings":"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"}
@@ -3,7 +3,6 @@ const require_helpers_complete_command = require('../helpers/complete-command.cj
3
3
  const require_helpers_completion_directive_constants = require('../helpers/completion-directive-constants.cjs');
4
4
  let _alloy_js_core_jsx_runtime = require("@alloy-js/core/jsx-runtime");
5
5
  let _shell_shock_core_plugin_utils = require("@shell-shock/core/plugin-utils");
6
- let _stryke_path = require("@stryke/path");
7
6
  let _alloy_js_core = require("@alloy-js/core");
8
7
  let _alloy_js_typescript = require("@alloy-js/typescript");
9
8
  let _powerlines_deepkit_vendor_type = require("@powerlines/deepkit/vendor/type");
@@ -11,6 +10,7 @@ let _powerlines_plugin_alloy_core = require("@powerlines/plugin-alloy/core");
11
10
  let _powerlines_plugin_alloy_core_contexts_context = require("@powerlines/plugin-alloy/core/contexts/context");
12
11
  let _powerlines_plugin_alloy_typescript = require("@powerlines/plugin-alloy/typescript");
13
12
  let _powerlines_plugin_alloy_typescript_components_tsdoc = require("@powerlines/plugin-alloy/typescript/components/tsdoc");
13
+ let _stryke_path = require("@stryke/path");
14
14
  let _stryke_string_format = require("@stryke/string-format");
15
15
 
16
16
  //#region src/components/zsh-command.tsx
@@ -19,12 +19,15 @@ let _stryke_string_format = require("@stryke/string-format");
19
19
  */
20
20
  function ZshCompletionsCommand() {
21
21
  const context = (0, _powerlines_plugin_alloy_core_contexts_context.usePowerlines)();
22
+ const bin = (0, _alloy_js_core.computed)(() => (0, _shell_shock_core_plugin_utils.getAppBin)(context));
23
+ const name = (0, _alloy_js_core.computed)(() => (0, _stryke_string_format.snakeCase)(bin.value));
22
24
  return (0, _alloy_js_core_jsx_runtime.createComponent)(_powerlines_plugin_alloy_typescript.TypescriptFile, {
23
25
  get path() {
24
26
  return (0, _stryke_path.joinPaths)(context.entryPath, "completions", "zsh", "command.ts");
25
27
  },
26
28
  imports: {
27
- "node:os": ["os"],
29
+ "node:os": "os",
30
+ "node:path": ["join"],
28
31
  "node:fs/promises": ["readFile", "writeFile"]
29
32
  },
30
33
  builtinImports: { "shell-shock:console": [
@@ -50,7 +53,7 @@ function ZshCompletionsCommand() {
50
53
  return _powerlines_deepkit_vendor_type.ReflectionKind.string;
51
54
  },
52
55
  get defaultValue() {
53
- return `${(0, _shell_shock_core_plugin_utils.getAppBin)(context)}-completions.zsh`;
56
+ return `${bin.value}-completions.zsh`;
54
57
  }
55
58
  })];
56
59
  }
@@ -98,19 +101,19 @@ function ZshCompletionsCommand() {
98
101
  name: "completions",
99
102
  type: "string",
100
103
  get initializer() {
101
- return _alloy_js_core.code`#compdef ${(0, _shell_shock_core_plugin_utils.getAppBin)(context)}
102
- compdef _${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))} ${(0, _shell_shock_core_plugin_utils.getAppBin)(context)}
104
+ return _alloy_js_core.code` \`#compdef ${bin.value}
105
+ compdef _${name.value} ${bin.value}
103
106
 
104
107
  # zsh completion for ${(0, _shell_shock_core_plugin_utils.getAppTitle)(context)} -*- shell-script -*-
105
108
 
106
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug() {
109
+ __${name.value}_debug() {
107
110
  local file="$BASH_COMP_DEBUG_FILE"
108
- if [[ -n \${file} ]]; then
109
- echo "$*" >> "\${file}"
111
+ if [[ -n \\\${file} ]]; then
112
+ echo "$*" >> "\\\${file}"
110
113
  fi
111
114
  }
112
115
 
113
- _${(0, _shell_shock_core_plugin_utils.getAppBin)(context)}() {
116
+ _${name.value}() {
114
117
  local shellCompDirectiveError=${require_helpers_completion_directive_constants.CompletionDirective.CompletionDirectiveError}
115
118
  local shellCompDirectiveNoSpace=${require_helpers_completion_directive_constants.CompletionDirective.CompletionDirectiveNoSpace}
116
119
  local shellCompDirectiveNoFileComp=${require_helpers_completion_directive_constants.CompletionDirective.CompletionDirectiveNoFileComp}
@@ -121,88 +124,88 @@ _${(0, _shell_shock_core_plugin_utils.getAppBin)(context)}() {
121
124
  local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace keepOrder
122
125
  local -a completions
123
126
 
124
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "\\n========= starting completion logic =========="
125
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "CURRENT: \${CURRENT}, words[*]: \${words[*]}"
127
+ __${name.value}_debug "\\n========= starting completion logic =========="
128
+ __${name.value}_debug "CURRENT: \\\${CURRENT}, words[*]: \\\${words[*]}"
126
129
 
127
130
  # The user could have moved the cursor backwards on the command-line.
128
131
  # We need to trigger completion from the $CURRENT location, so we need
129
132
  # to truncate the command-line ($words) up to the $CURRENT location.
130
133
  # (We cannot use $CURSOR as its value does not work when a command is an alias.)
131
- words=( "\${=words[1,CURRENT]}" )
132
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Truncated words[*]: \${words[*]},"
134
+ words=( "\\\${=words[1,CURRENT]}" )
135
+ __${name.value}_debug "Truncated words[*]: \\\${words[*]},"
133
136
 
134
- lastParam=\${words[-1]}
135
- lastChar=\${lastParam[-1]}
136
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "lastParam: \${lastParam}, lastChar: \${lastChar}"
137
- # For zsh, when completing a flag with an = (e.g., ${(0, _shell_shock_core_plugin_utils.getAppBin)(context)} -n=<TAB>)
137
+ lastParam=\\\${words[-1]}
138
+ lastChar=\\\${lastParam[-1]}
139
+ __${name.value}_debug "lastParam: \\\${lastParam}, lastChar: \\\${lastChar}"
140
+ # For zsh, when completing a flag with an = (e.g., ${bin.value} -n=<TAB>)
138
141
  # completions must be prefixed with the flag
139
142
  setopt local_options BASH_REMATCH
140
- if [[ "\${lastParam}" =~ '-.*=' ]]; then
143
+ if [[ "\\\${lastParam}" =~ '-.*=' ]]; then
141
144
  # We are dealing with a flag with an =
142
- flagPrefix="-P \${BASH_REMATCH}"
145
+ flagPrefix="-P \\\${BASH_REMATCH}"
143
146
  fi
144
147
 
145
148
  # Prepare the command to obtain completions, ensuring arguments are quoted for eval
146
- local -a args_to_quote=("\${(@)words[2,-1]}")
147
- if [ "\${lastChar}" = "" ]; then
149
+ local -a args_to_quote=("\\\${(@)words[2,-1]}")
150
+ if [ "\\\${lastChar}" = "" ]; then
148
151
  # If the last parameter is complete (there is a space following it)
149
152
  # We add an extra empty parameter so we can indicate this to the go completion code.
150
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Adding extra empty parameter"
153
+ __${name.value}_debug "Adding extra empty parameter"
151
154
  args_to_quote+=("")
152
155
  fi
153
156
 
154
157
  # Use Zsh's (q) flag to quote each argument safely for eval
155
- local quoted_args=("\${(@q)args_to_quote}")
158
+ local quoted_args=("\\\${(@q)args_to_quote}")
156
159
 
157
160
  # Join the main command and the quoted arguments into a single string for eval
158
- requestComp="${require_helpers_complete_command.exec} complete -- \${quoted_args[*]}"
161
+ requestComp="${require_helpers_complete_command.EXEC_COMMAND} complete -- \\\${quoted_args[*]}"
159
162
 
160
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "About to call: eval \${requestComp}"
163
+ __${name.value}_debug "About to call: eval \\\${requestComp}"
161
164
 
162
165
  # Use eval to handle any environment variables and such
163
- out=$(eval \${requestComp} 2>/dev/null)
164
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "completion output: \${out}"
166
+ out=$(eval \\\${requestComp} 2>/dev/null)
167
+ __${name.value}_debug "completion output: \\\${out}"
165
168
 
166
169
  # Extract the directive integer following a : from the last line
167
170
  local lastLine
168
171
  while IFS='\n' read -r line; do
169
- lastLine=\${line}
170
- done < <(printf "%s\n" "\${out[@]}")
171
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "last line: \${lastLine}"
172
+ lastLine=\\\${line}
173
+ done < <(printf "%s\n" "\\\${out[@]}")
174
+ __${name.value}_debug "last line: \\\${lastLine}"
172
175
 
173
- if [ "\${lastLine[1]}" = : ]; then
174
- directive=\${lastLine[2,-1]}
176
+ if [ "\\\${lastLine[1]}" = : ]; then
177
+ directive=\\\${lastLine[2,-1]}
175
178
  # Remove the directive including the : and the newline
176
179
  local suffix
177
- (( suffix=\${#lastLine}+2))
178
- out=\${out[1,-$suffix]}
180
+ (( suffix=\\\${#lastLine}+2))
181
+ out=\\\${out[1,-$suffix]}
179
182
  else
180
183
  # There is no directive specified. Leave $out as is.
181
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "No directive found. Setting to default"
184
+ __${name.value}_debug "No directive found. Setting to default"
182
185
  directive=0
183
186
  fi
184
187
 
185
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "directive: \${directive}"
186
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "completions: \${out}"
187
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "flagPrefix: \${flagPrefix}"
188
+ __${name.value}_debug "directive: \\\${directive}"
189
+ __${name.value}_debug "completions: \\\${out}"
190
+ __${name.value}_debug "flagPrefix: \\\${flagPrefix}"
188
191
 
189
192
  if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
190
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Completion received error. Ignoring completions."
193
+ __${name.value}_debug "Completion received error. Ignoring completions."
191
194
  return
192
195
  fi
193
196
 
194
197
  local activeHelpMarker="%"
195
- local endIndex=\${#activeHelpMarker}
196
- local startIndex=$((\${#activeHelpMarker}+1))
198
+ local endIndex=\\\${#activeHelpMarker}
199
+ local startIndex=$((\\\${#activeHelpMarker}+1))
197
200
  local hasActiveHelp=0
198
201
  while IFS='\n' read -r comp; do
199
202
  # Check if this is an activeHelp statement (i.e., prefixed with $activeHelpMarker)
200
- if [ "\${comp[1,$endIndex]}" = "$activeHelpMarker" ];then
201
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "ActiveHelp found: $comp"
202
- comp="\${comp[$startIndex,-1]}"
203
+ if [ "\\\${comp[1,$endIndex]}" = "$activeHelpMarker" ];then
204
+ __${name.value}_debug "ActiveHelp found: $comp"
205
+ comp="\\\${comp[$startIndex,-1]}"
203
206
  if [ -n "$comp" ]; then
204
- compadd -x "\${comp}"
205
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "ActiveHelp will need delimiter"
207
+ compadd -x "\\\${comp}"
208
+ __${name.value}_debug "ActiveHelp will need delimiter"
206
209
  hasActiveHelp=1
207
210
  fi
208
211
  continue
@@ -213,35 +216,35 @@ _${(0, _shell_shock_core_plugin_utils.getAppBin)(context)}() {
213
216
  # The description is preceded by a TAB character.
214
217
  # For zsh's _describe, we need to use a : instead of a TAB.
215
218
  # We first need to escape any : as part of the completion itself.
216
- comp=\${comp//:/\\:}
219
+ comp=\\\${comp//:/\\:}
217
220
 
218
221
  local tab="$(printf '\\t')"
219
- comp=\${comp//$tab/:}
222
+ comp=\\\${comp//$tab/:}
220
223
 
221
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Adding completion: \${comp}"
222
- completions+=\${comp}
224
+ __${name.value}_debug "Adding completion: \\\${comp}"
225
+ completions+=\\\${comp}
223
226
  lastComp=$comp
224
227
  fi
225
- done < <(printf "%s\n" "\${out[@]}")
228
+ done < <(printf "%s\n" "\\\${out[@]}")
226
229
 
227
230
  # Add a delimiter after the activeHelp statements, but only if:
228
231
  # - there are completions following the activeHelp statements, or
229
232
  # - file completion will be performed (so there will be choices after the activeHelp)
230
233
  if [ $hasActiveHelp -eq 1 ]; then
231
- if [ \${#completions} -ne 0 ] || [ $((directive & shellCompDirectiveNoFileComp)) -eq 0 ]; then
232
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Adding activeHelp delimiter"
234
+ if [ \\\${#completions} -ne 0 ] || [ $((directive & shellCompDirectiveNoFileComp)) -eq 0 ]; then
235
+ __${name.value}_debug "Adding activeHelp delimiter"
233
236
  compadd -x "--"
234
237
  hasActiveHelp=0
235
238
  fi
236
239
  fi
237
240
 
238
241
  if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
239
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Activating nospace."
242
+ __${name.value}_debug "Activating nospace."
240
243
  noSpace="-S ''"
241
244
  fi
242
245
 
243
246
  if [ $((directive & shellCompDirectiveKeepOrder)) -ne 0 ]; then
244
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Activating keep order."
247
+ __${name.value}_debug "Activating keep order."
245
248
  keepOrder="-V"
246
249
  fi
247
250
 
@@ -249,47 +252,47 @@ _${(0, _shell_shock_core_plugin_utils.getAppBin)(context)}() {
249
252
  # File extension filtering
250
253
  local filteringCmd
251
254
  filteringCmd='_files'
252
- for filter in \${completions[@]}; do
253
- if [ \${filter[1]} != '*' ]; then
255
+ for filter in \\\${completions[@]}; do
256
+ if [ \\\${filter[1]} != '*' ]; then
254
257
  # zsh requires a glob pattern to do file filtering
255
258
  filter="\\*.$filter"
256
259
  fi
257
260
  filteringCmd+=" -g $filter"
258
261
  done
259
- filteringCmd+=" \${flagPrefix}"
262
+ filteringCmd+=" \\\${flagPrefix}"
260
263
 
261
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "File filtering command: $filteringCmd"
264
+ __${name.value}_debug "File filtering command: $filteringCmd"
262
265
  _arguments '*:filename:'"$filteringCmd"
263
266
  elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
264
267
  # File completion for directories only
265
268
  local subdir
266
- subdir="\${completions[1]}"
269
+ subdir="\\\${completions[1]}"
267
270
  if [ -n "$subdir" ]; then
268
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Listing directories in $subdir"
269
- pushd "\${subdir}" >/dev/null 2>&1
271
+ __${name.value}_debug "Listing directories in $subdir"
272
+ pushd "\\\${subdir}" >/dev/null 2>&1
270
273
  else
271
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Listing directories in ."
274
+ __${name.value}_debug "Listing directories in ."
272
275
  fi
273
276
 
274
277
  local result
275
- _arguments '*:dirname:_files -/'" \${flagPrefix}"
278
+ _arguments '*:dirname:_files -/'" \\\${flagPrefix}"
276
279
  result=$?
277
280
  if [ -n "$subdir" ]; then
278
281
  popd >/dev/null 2>&1
279
282
  fi
280
283
  return $result
281
284
  else
282
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Calling _describe"
283
- if eval _describe $keepOrder "completions" completions -Q \${flagPrefix} \${noSpace}; then
284
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "_describe found some completions"
285
+ __${name.value}_debug "Calling _describe"
286
+ if eval _describe $keepOrder "completions" completions -Q \\\${flagPrefix} \\\${noSpace}; then
287
+ __${name.value}_debug "_describe found some completions"
285
288
 
286
289
  # Return the success of having called _describe
287
290
  return 0
288
291
  else
289
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "_describe did not find completions."
290
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Checking if we should do file completion."
292
+ __${name.value}_debug "_describe did not find completions."
293
+ __${name.value}_debug "Checking if we should do file completion."
291
294
  if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
292
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "deactivating file completion"
295
+ __${name.value}_debug "deactivating file completion"
293
296
 
294
297
  # Return 0 to indicate completion is finished and prevent zsh from
295
298
  # trying other completion algorithms (which could cause hanging).
@@ -297,21 +300,21 @@ _${(0, _shell_shock_core_plugin_utils.getAppBin)(context)}() {
297
300
  return 0
298
301
  else
299
302
  # Perform file completion
300
- __${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}_debug "Activating file completion"
303
+ __${name.value}_debug "Activating file completion"
301
304
 
302
305
  # We must return the result of this command, so it must be the
303
306
  # last command, or else we must store its result to return it.
304
- _arguments '*:filename:_files'" \${flagPrefix}"
307
+ _arguments '*:filename:_files'" \\\${flagPrefix}"
305
308
  fi
306
309
  fi
307
310
  fi
308
311
  }
309
312
 
310
313
  # don't run the completion function when being sourced or eval-ed
311
- if [ "\${funcstack[1]}" = "_${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}" ]; then
312
- _${(0, _stryke_string_format.snakeCase)((0, _shell_shock_core_plugin_utils.getAppBin)(context))}
314
+ if [ "\\\${funcstack[1]}" = "_${name.value}" ]; then
315
+ _${name.value}
313
316
  fi
314
- \`);`;
317
+ \`; `;
315
318
  }
316
319
  }),
317
320
  (0, _alloy_js_core_jsx_runtime.createComponent)(_powerlines_plugin_alloy_core.Spacing, {}),
@@ -341,7 +344,7 @@ fi
341
344
  (0, _alloy_js_core_jsx_runtime.memo)(() => _alloy_js_core.code`try {
342
345
  configFileContent = await readFile(configFilePath, "utf8");
343
346
  } catch (error) {
344
- if (error.code === "ENOENT") {
347
+ if (Error.isError(error) && error.code === "ENOENT") {
345
348
  // If the file doesn't exist, we can create it later when writing the completion script.
346
349
  warn(\`Configuration file \${colors.bold(configFilePath)} does not exist. It will be created when the completion script is written.\`);
347
350
  } else {
@@ -359,7 +362,7 @@ fi
359
362
  (0, _alloy_js_core_jsx_runtime.createComponent)(_alloy_js_typescript.IfStatement, {
360
363
  condition: _alloy_js_core.code`options.script`,
361
364
  get children() {
362
- return _alloy_js_core.code`const outputPath = options.script === true ? "${(0, _shell_shock_core_plugin_utils.getAppBin)(context)}-completions.zsh" : options.script;
365
+ return _alloy_js_core.code`const outputPath = options.script === true ? "${name.value}-completions.zsh" : options.script;
363
366
  await writeFile(outputPath, stripAnsi(completions));
364
367
 
365
368
  success(\`${(0, _shell_shock_core_plugin_utils.getAppTitle)(context)} Zsh completion script has been generated at \${colors.bold(outputPath)}.\`);`;