Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Completion not working for default shells other than bash #26

Closed
scrouthtv opened this issue Apr 14, 2020 · 26 comments
Closed

Completion not working for default shells other than bash #26

scrouthtv opened this issue Apr 14, 2020 · 26 comments
Assignees
Labels
bug Something isn't working

Comments

@scrouthtv
Copy link

scrouthtv commented Apr 14, 2020

If I'm not mistaken, the readme claims that by importing a wsl command both command and argument completion is enabled automatically for pwsh as well:

  • Command completion is enabled by PowerShell's command completion
  • Argument completion is enabled by registering an ArgumentCompleter that shims bash's programmable completion

To Reproduce
Steps to reproduce the behavior:

  1. Run pwsh:
PowerShell 7.0.0
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/powershell
Type 'help' to get help.

PS C:\Users\x> pwsh --version
PowerShell 7.0.0
  1. Select a wsl that has completion enabled in wsl bash:
[x@DESKTOP-04NUF17 ~]$ echo $0
bash
[x@DESKTOP-04NUF17 ~]$ git <tab><tab>
add               blame             cherry-pick       config            format-patch      gui               log.cmd           pull              remote            restore           show              status            worktree
am                branch            citool            describe          fsck              help              merge             push              repack            revert            show-branch       submodule
apply             bundle            clean             diff              gc                init              mergetool         range-diff        replace           rm                sparse-checkout   switch
archive           checkout          clone             difftool          gitk              instaweb          mv                rebase            request-pull      send-email        stage             tag
bisect            cherry            commit            fetch             grep              log               notes             reflog            reset             shortlog          stash             whatchanged
[x@DESKTOP-04NUF17 ~]$ grep --<tab><tab>
--after-context=         --byte-offset            --dereference-recursive  --exclude-from=          --fixed-strings          --invert-match           --max-count=             --null-data              --regexp=
--basic-regexp           --color                  --devices=               --extended-regexp        --help                   --label=                 --no-filename            --only-matching          --text
--before-context=        --colour                 --directories=           --file=                  --ignore-case            --line-buffered          --no-ignore-case         --perl-regexp            --version
--binary                 --context=               --exclude=               --files-with-matches     --include=               --line-number            --no-messages            --quiet                  --with-filename
--binary-files=          --count                  --exclude-dir=           --files-without-match    --initial-tab            --line-regexp            --null                   --recursive              --word-regexp
[lenni@DESKTOP-04NUF17 ~]$ ls --<tab><tab>
--all                                      --dereference-command-line-symlink-to-dir  --hide-control-chars                       --numeric-uid-gid                          --tabsize=
--almost-all                               --directory                                --human-readable                           --quote-name                               --time
--author                                   --dired                                    --hyperlink                                --quoting-style=                           --time=
--block-size=                              --escape                                   --ignore=                                  --recursive                                --time-style=
--classify                                 --file-type                                --ignore-backups                           --reverse                                  --version
--color                                    --format=                                  --indicator-style=                         --show-control-chars                       --width=
--color=                                   --full-time                                --inode                                    --si
--context                                  --group-directories-first                  --kibibytes                                --size
--dereference                              --help                                     --literal                                  --sort
--dereference-command-line                 --hide=                                    --no-group                                 --sort=
  1. Import the wsl command(s) into pwsh:
PS C:\Users\x> Import-WslCommand "git", "grep", "ls"
PS C:\Users\x>
  1. Completion does not work:
PS C:\Users\x> git .\.bash_profile<tab>^C
PS C:\Users\x> grep --<tab><tab>^C
PS C:\Users\x> ls --<tab><tab>^C
PS C:\Users\x>

Expected behavior
Tabbing on those commands in pwsh would provide me with the same completion commands as in bash.

Desktop (please complete the following information):

  • Windows 2004 (OS Build (19041.173)
  • Arch Linux on Windows 10 x86_64 on 4.19.84-microsoft-standard
  • GNU bash, version 5.0.16(1)-release (x86_64-pc-linux-gnu)
@mikebattista
Copy link
Owner

Your expectation is correct. That should work and works for me.

Has this ever worked for you (so a regression)? Or is this the first time you're trying?

Could you attempt to <TAB> complete again with an imported command and then send me a few things?

  • gcm git, grep, ls
  • $WslCompletionFunctions
  • wsl -l
  • wsl apt list bash-completion

@scrouthtv
Copy link
Author

I just installed the module and it didn't work out of the box.
Output:

PS C:\Users\x> gcm git, grep, ls                                                          
                                                                                              
CommandType     Name                                               Version    Source          
-----------     ----                                               -------    ------          
Function        git                                                0.2.2      WslInterop      
Function        grep                                               0.2.2      WslInterop      
Function        ls                                                 0.2.2      WslInterop      
                                                                                              
PS C:\Users\x> $WslCompletionFunctions                                                    
                                                                                              
Name                           Value                                                          
----                           -----                                                          
git                            _minimal                                                       
grep                           _minimal                                                       
                                                                                              
PS C:\Users\x> wsl -l                                                                     
Windows Subsystem for Linux Distributions:                                                    
Arch (Default)                                                                                
PS C:\Users\x> wsl apt list bash-completion                                               
zsh:1: command not found: apt                                                                 
PS C:\Users\x> wsl pacman -Qi bash-completion                                             
Name            : bash-completion                                                             
Version         : 2.10-1                                                                      
Description     : Programmable completion for the bash shell                                  
Architecture    : any                                                                         
URL             : https://github.com/scop/bash-completion                                     
Licenses        : GPL2                                                                        
Groups          : None                                                                        
Provides        : None                                                                        
Depends On      : bash                                                                        
Optional Deps   : None                                                                        
Required By     : None                                                                        
Optional For    : bash                                                                        
Conflicts With  : None                                                                        
Replaces        : None                                                                        
Installed Size  : 836.42 KiB                                                                  
Packager        : Bartłomiej Piotrowski <bpiotrowski@archlinux.org>                           
Build Date      : Thu 12 Dec 2019 09:54:58 PM CET                                             
Install Date    : Tue 14 Apr 2020 02:45:57 PM CEST                                            
Install Reason  : Explicitly installed                                                        
Install Script  : No                                                                          
Validated By    : Signature                                                                   

I'm using z shell if that's causing the trouble.

@mikebattista
Copy link
Owner

Thanks. Different distros are typically what complicates things. I recently updated the README to indicate the bash-completion package was a prerequisite, since not all distributions include it out of the box.

Based on the Install Date and Install Reason for the bash-completion package, it looks like you just installed it?

Have you tried argument completion again since installing that package?

With the bash-completion package installed, can you try $WslCompletionFunctions = @{ git = '__git_wrap__git_main'; grep = '_longopt'; ls = '_longopt' } and then <TAB> completing again?

@scrouthtv
Copy link
Author

Actually I think my system time is messed up. I install bash-completion before I ran Import-WslCommand. Since then, I tried completion although it did not work.

However, by running your command, everything works fine:

PS C:\Users\x> Import-WslCommand "git", "grep", "ls"
PS C:\Users\x> gcm git, grep, ls

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        git                                                0.2.2      WslInterop
Function        grep                                               0.2.2      WslInterop
Function        ls                                                 0.2.2      WslInterop

PS C:\Users\x> $WslCompletionFunctions = @{ git = '__git_wrap__git_main'; grep = '_longopt'; ls = '_longopt' }
PS C:\Users\x> $WslCompletionFunctions

Name                           Value
----                           -----
ls                             _longopt
git                            __git_wrap__git_main
grep                           _longopt

PS C:\Users\x> git add^C
PS C:\Users\x> grep --after-context=^C
PS C:\Users\x> ls --all^C

I am currently trying completion with bash as my default shell, but give me two more minutes for a result.

@scrouthtv
Copy link
Author

I somehow managed to get

less -<TAB>--------------------------------------------------c^C

@scrouthtv
Copy link
Author

Nope, even with bash as my default shell tab completion is not imported.

@scrouthtv
Copy link
Author

PS C:\Users\x> wsl sh -c "env | grep SHELL"
SHELL=/bin/bash
PS C:\Users\x> gcm git
Get-Command: The term 'git' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
PS C:\Users\x> Import-WslCommand "git"
PS C:\Users\x> git <TAB>.bash_profile

@mikebattista
Copy link
Owner

Ok. Based on your original output from $WslCompletionFunctions, I'd recommend also resetting the completion function cache, since it may have been populated from attempts to autocomplete before the bash-completion package was installed.

  • ri "$Env:APPDATA\PowerShell WSL Interop\WslCompletionFunctions"
  • Restart PowerShell
  • Attempt to autocomplete again with git, grep, and ls
  • Send the output of $WslCompletionFunctions

Let me know how it goes. The fact that you were able to autocomplete when $WslCompletionFunctions was populated correctly indicates there may be an issue with how this is populated.

If there is something I should capture in the README to better support z shell, I would like to figure out what that is and add it.

@scrouthtv
Copy link
Author

Doesn't look too good:

PS C:\Users\x> wsl sh -c "env | grep SHELL"
SHELL=/bin/bash
PS C:\Users\x> ri "$Env:APPDATA\PowerShell WSL Interop\WslCompletionFunctions"
PS C:\Users\x> Import-WslCommand "git", "grep", "ls"
PS C:\Users\x> echo $WslCompletionFunctions
PS C:\Users\x>

I always tried these with a new instance of pwsh. Profile is completely empyt too.

@scrouthtv
Copy link
Author

https://pastebin.com/W3f3xdum
These are the files bash-completion provides on Arch, if there is anything missing.

@scrouthtv
Copy link
Author

I guess you retrieve the completion function using

# Try to find the completion function.
$global:WslCompletionFunctions[$command] = wsl.exe (". /usr/share/bash-completion/bash_completion 2> /dev/null; __load_completion $command 2> /dev/null; complete -p $command 2> /dev/null | sed -E 's/^complete.*-F ([^ ]+).*`$/\1/'" -split ' ')
            
# If we can't find a completion function, default to _minimal which will resolve Linux file paths.
if ($null -eq $global:WslCompletionFunctions[$command] -or $global:WslCompletionFunctions[$command] -like "complete*") {
    $global:WslCompletionFunctions[$command] = "_minimal"
}

# Update the bash completion function cache.
New-Item $WslCompletionFunctionsCache -Force | Out-Null
$global:WslCompletionFunctions | Export-Clixml $WslCompletionFunctionsCache

(WslInterop.psm1, 3a5c1b7, line 123 - 135)

When I only run the very first wsl command, it works how (I guess) it is supposed to:

PS C:\Users\x> $command="grep"
PS C:\Users\x> echo $command
grep
PS C:\Users\x> wsl.exe (". /usr/share/bash-completion/bash_completion 2> /dev/null; __load_completion $command 2> /dev/null; complete -p $command 2> /dev/null | sed -E 's/^complete.*-F ([^ ]+).*`$/\1/'" -split ' ')
_longopt
PS C:\Users\x>

@scrouthtv
Copy link
Author

Both ls and git are also correctly reported.

@mikebattista
Copy link
Owner

Can you run through my steps exactly as I shared them?

You should restart PowerShell after clearing the APPDATA cache. Then you also need to attempt autocompletion before calling $WslCompletionFunctions, otherwise no output would be expected.

@scrouthtv
Copy link
Author

Doesn't look too good:

PS C:\Users\x> wsl sh -c "env | grep SHELL"
SHELL=/bin/bash
PS C:\Users\x> ri "$Env:APPDATA\PowerShell WSL Interop\WslCompletionFunctions"
PS C:\Users\x> Import-WslCommand "git", "grep", "ls"
PS C:\Users\x> echo $WslCompletionFunctions
PS C:\Users\x>

I always tried these with a new instance of pwsh. Profile is completely empyt too.

@mikebattista
Copy link
Owner

I don't see you attempting to <TAB> complete between importing the commands and outputting $WslCompletionFunctions.

@scrouthtv
Copy link
Author

Oh sorry, my bad. Now the fun begins: I tried this with bash as in above:

PS C:\Users\x> wsl sh -c "env | grep SHELL"
SHELL=/bin/bash
PS C:\Users\x> ri "$Env:APPDATA\PowerShell WSL Interop\WslCompletionFunctions"
Remove-Item: Cannot find path 'C:\Users\x\AppData\Roaming\PowerShell WSL Interop\WslCompletionFunctions' because it does not exist.
PS C:\Users\x> Import-WslCommand "git", "grep", "ls"
PS C:\Users\x> git <TAB>add^C
PS C:\Users\x> echo $WslCompletionFunctions

Name                           Value
----                           -----
git                            __git_wrap__git_main

PS C:\Users\x>

However, with zsh:

PS C:\Users\x> wsl sh -c "env | grep SHELL"
SHELL=/usr/bin/zsh
PS C:\Users\x> ri "$Env:APPDATA\PowerShell WSL Interop\WslCompletionFunctions"
Remove-Item: Cannot find path 'C:\Users\x\AppData\Roaming\PowerShell WSL Interop\WslCompletionFunctions' because it does not exist.
PS C:\Users\x> Import-WslCommand "git", "grep", "ls"
PS C:\Users\x> git <TAB>.\.bash_history^C
PS C:\Users\x> echo $WslCompletionFunctions

Name                           Value
----                           -----
git                            _minimal

PS C:\Users\x>

@scrouthtv
Copy link
Author

This is because bash has a command __load_completion which is used to retrieve the completion for a given $command. However, zsh does not have this command:

> __load_completion grep
zsh: command not found: __load_completion

@mikebattista
Copy link
Owner

Ok. Thanks. So sounds like at least bash is working as expected now.

So __load_completion is defined within /usr/share/bash-completion/bash_completion which I dot source to identify completion functions, as you saw in the code.

Is there a different way to source this file for z shell so __load_completion would be defined?

@scrouthtv
Copy link
Author

Suggestion:
Change WslInterop.psm1 line 125 to

 wsl.exe bash -c ". /usr/share/bash-completion/bash_completion 2> /dev/null; __load_completion $command 2> /dev/null; complete -p $command 2> /dev/null | sed -E 's/^complete.*-F ([^ ]+).*`$/\1/'" -split ' '

For example:

PS C:\Users\x> wsl sh -c "env | grep SHELL"
PS C:\Users\x> $command="grep"
PS C:\Users\x> wsl.exe (". /usr/share/bash-completion/bash_completion 2> /dev/null; __load_completion $command 2> /dev/null; complete -p $command 2> /dev/null | sed -E 's/^complete.*-F ([^ ]+).*`$/\1/'" -split ' ')
PS C:\Users\x> wsl.exe bash -c ". /usr/share/bash-completion/bash_completion 2> /dev/null; __load_completion $command 2> /dev/null; complete -p $command 2> /dev/null | sed -E 's/^complete.*-F ([^ ]+).*`$/\1/'" -split ' '
_longopt
PS C:\Users\x> 

@scrouthtv
Copy link
Author

I don't really know how sourcing a bash completion function would work in zsh so using bash instead seems to be the easiest (and fastest) way.

@mikebattista
Copy link
Owner

I can try that.

Actually I think my system time is messed up. I install bash-completion before I ran Import-WslCommand. Since then, I tried completion although it did not work.

However, by running your command, everything works fine:

PS C:\Users\x> Import-WslCommand "git", "grep", "ls"
PS C:\Users\x> gcm git, grep, ls

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        git                                                0.2.2      WslInterop
Function        grep                                               0.2.2      WslInterop
Function        ls                                                 0.2.2      WslInterop

PS C:\Users\x> $WslCompletionFunctions = @{ git = '__git_wrap__git_main'; grep = '_longopt'; ls = '_longopt' }
PS C:\Users\x> $WslCompletionFunctions

Name                           Value
----                           -----
ls                             _longopt
git                            __git_wrap__git_main
grep                           _longopt

PS C:\Users\x> git add^C
PS C:\Users\x> grep --after-context=^C
PS C:\Users\x> ls --all^C

I am currently trying completion with bash as my default shell, but give me two more minutes for a result.

Can you confirm here that you were using z shell when you set $WslCompletionFunctions = @{ git = '__git_wrap__git_main'; grep = '_longopt'; ls = '_longopt' } manually and autocompletion worked?

I want to make sure that, assuming $WslCompletionFunctions is populated correctly, autocompletion would in fact work with z shell.

@scrouthtv
Copy link
Author

Sorry for not answering your question. In the retried the test you mentioned with z shell and even with $WslCompletionFunctions set, completion does not work:

PS C:\Users\x> wsl sh -c "env | grep SHELL"
SHELL=/usr/bin/zsh
PS C:\Users\x> Import-WslCommand "git", "grep", "ls"
PS C:\Users\x> git .\.android\^C
PS C:\Users\x> $WslCompletionFunctions = @{ git = '__git_wrap__git_main'; grep = '_longopt'; ls = '_longopt' }
PS C:\Users\x> $WslCompletionFunctions

Name                           Value
----                           -----
git                            __git_wrap__git_main
ls                             _longopt
grep                           _longopt

PS C:\Users\x> git .\.bash_history^C
PS C:\Users\x> grep --<TAB>^C
PS C:\Users\x> ls --<TAB>^C

I guess there is a second command that converts the __git_wrap__git_main and _longopt at runtime to actual completions based on the context at runtime? This function involves wsl too but is not explicitly calling bash?

@mikebattista mikebattista self-assigned this Apr 15, 2020
@mikebattista mikebattista added the bug Something isn't working label Apr 15, 2020
@mikebattista
Copy link
Owner

Thanks. It not working is what I would have expected given the dot sourcing issue, which is why I was surprised that it might have worked for you looking back at the history of the repros.

Calling bash explicitly both when identifying completion functions and generating completions is the right approach. Now I'm just battling with WSL not accepting the completion generation command when I switch to bash -c.

@mikebattista mikebattista reopened this Apr 18, 2020
@mikebattista mikebattista changed the title Completion not working Completion not working for default shells other than bash Apr 21, 2020
@mikebattista
Copy link
Owner

@scrouthtv could you try your repro again with the latest code?

  • Reset your completion function cache with ri "$Env:APPDATA\PowerShell WSL Interop\WslCompletionFunctions"
  • Restart PowerShell
  • Clone the repo locally to <PATH>
  • Run Import-Module "<PATH>\WslInterop.psd1" -Force
  • Rerun your repro with zsh as your WSL shell

Everything works for me now with zsh set as my default shell.

@scrouthtv
Copy link
Author

Yep works for me now, too. Thanks for your quick help!

@mikebattista
Copy link
Owner

Awesome. 0.2.3 was published with the fix. Thanks for reporting this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants