chocolatey / choco

Chocolatey - the package manager for Windows
https://chocolatey.org
Other
10.05k stars 890 forks source link

Tab completion does not work since PowerShell 7.4 #3364

Open yan12125 opened 7 months ago

yan12125 commented 7 months ago

Checklist

What You Are Seeing?

Hitting tab after typing choco only shows filenames

What is Expected?

Choco commands like install, upgrade, etc. should be shown

How Did You Get This To Happen?

  1. Make sure PowerShell profile contains the following snippet
    $ChocolateyProfile = "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
    if (Test-Path($ChocolateyProfile)) {
    Import-Module "$ChocolateyProfile"
    }
  2. Upgrade PowerShell to 7.4.0
  3. Type choco and hit tab

System Details

Installed Packages

au 2022.10.24
chocolatey 2.2.2
chocolatey-compatibility.extension 1.0.0
chocolatey-core.extension 1.4.0
chocolatey-windowsupdate.extension 1.0.5
dellcommandupdate 5.1.0
delta 0.16.5
DotNet4.6.1 4.6.1055.20170308
Firefox 120.0.0
git.install 2.43.0
gnupg 2.4.3
KB2919355 1.0.20160915
KB2919442 1.0.20160915
KB2999226 1.0.20181019
KB3033929 1.0.5
KB3035131 1.0.3
KB3118401 1.0.5
kdeconnect-kde 23.4.0
keepassxc 2.7.6
libreoffice-still 7.5.8
microsoft-windows-terminal 1.18.3181
miktex.install 23.10.12
neovim 0.9.4
nodejs-lts 20.10.0
notepadplusplus.install 8.6.0
PIME 1.3.0
powershell-core 7.4.0
python39 3.9.13.20230703
ripgrep 13.0.0.20220913
syncthingtray 1.4.9
synergy 1.14.6.19
texstudio.install 4.6.3
vcredist140 14.38.33130
vcredist2015 14.0.24215.20170201

Output Log

(N/A - not sure how to get logs for tab completion)

Additional Context

The cause is that Chocolatey only defines TabExpansion function to enable completions, while that function is no longer used by PowerShell 7.4 [1]. A solution might be adding TabExpansion2 function (supported since PowerShell 3) besides the existing TabExpansion function, so that all users with PowerShell 2 ~ 7.4 can have Chocolatey tab completions.

As a side note, if TabExpansion2 is added, https://github.com/chocolatey/choco/issues/2255 will likely be solved as well.

[1] https://github.com/PowerShell/PowerShell/pull/18337

silverqx commented 7 months ago

I can confirm this, after upgrading to PS 7.4 tab completion stopped working and I can't get it working anymore.

silverqx commented 7 months ago

@yan12125 Do you know how to quickly workaround this? I tried to rename all occurrences to TabExpansion2 but it didn't help, is even possible to quickly workaround it?

yan12125 commented 7 months ago

Do you know how to quickly workaround this?

I downgraded PowerShell.

silverqx commented 7 months ago

I want to have the latest 7.4 version so that's not what I want to do, I can live for some time w/o these completions.

It looks like the fix should be easy, I don't see anything that can cause bigger problems, and the code doesn't hardly depend on anything what was remove by the TabExpansion PR.

It looks like the problem is how things are exported or something?, but I looked to this only 5mins so I can be wrong.

yan12125 commented 6 months ago

I'm not sure if there is an easy fix. PowerShell < 7.4 calls the TabExpansion function provided by Chocolatey for custom tab completions, and that function is no longer called by PowerShell > 7.4 as indicated in the aforementionef PR. A proper fix is probably using newer completion APIs like Register-ArgumentCompleter.

Scoop has a similar issue (https://github.com/Moeologist/scoop-completion/issues/35), and a relevant fix (https://github.com/Moeologist/scoop-completion/pull/25) is quite large.

silverqx commented 6 months ago

That aren't a good news, it looks like they will need to rewrite it to make it work again, what means we will be some time without tab completion 😞

mklement0 commented 5 months ago

For background information, see https://github.com/PowerShell/PowerShell/issues/20930#issuecomment-1897472499

Here's a solution that works in v7.4+:

function script:Get-AliasNames($exe) {
    @($exe, "$exe.exe") + @(Get-Alias | Where-Object { $_.Definition -eq $exe } | Select-Object -Exp Name)
}

Register-ArgumentCompleter -Native -CommandName (Get-AliasNames choco) -ScriptBlock {
    param($wordToComplete, $commandAst, $cursorColumn)

    # NOTE:
    # * The stringified form of $commandAst is the command's own command line (irrespective of
    #   whether other statements are on the same line or whether it is part of a pipeline).
    # * However, trailing whitespace is trimmed in the string representation of $commandAst. 
    #   Therefore, when the actual command line ends in space(s), they must be added back
    #   so that ChocolateyTabExpansion recognizes the start of a new argument.
    $ownCommandLine = [string] $commandAst
    $ownCommandLine = $ownCommandLine.Substring(0, [Math]::Min($ownCommandLine.Length, $cursorColumn))
    $ownCommandLine += ' ' * ($cursorColumn - $ownCommandLine.Length)

    ChocolateyTabExpansion $ownCommandLine
}
mklement0 commented 5 months ago

I've fixed a problem in the code in the previous comment, which now makes it support intra-line expansions properly too - from what I can tell, this makes it suitable for a fix.

However, if you want to avoid having to modify the module, I've posted a polyfill that overrides the TabExpansion2 function only, and, if added to $PROFILE, should work with all modules that still rely on the legacy TabExpansion function - see https://github.com/PowerShell/PowerShell/issues/20930#issuecomment-1899191414

yan12125 commented 5 months ago

Thank you very much for the update! I just need one more line in Register-ArgumentCompleter script block to make it work: (the line removed during a comment edit)

    param($wordToComplete, $commandAst, $cursorColumn)

Without this, the behavior is kind of different from chocolatey on older PowerShell. When I type choco out and hit the Tab key, an older PowerShell shows the complete subcommand choco outdated, while the Register-ArgumentCompleter approach shows choco --help.

mklement0 commented 5 months ago

Ouch! Thank you for catching that, @yan12125 - code in the earlier comment is now updated (I had simply made a copy-paste error when only partially replacing the original code).

pauby commented 5 months ago

@mklement0 Are you able to submit a PR for the changes that you're making? It sounds like you have it very close to working universally across PS versions.

mklement0 commented 5 months ago

@pauby, I've submitted #3387 - hope that's good enough.