posh-git
posh-git copied to clipboard
PowerShell Alias Tab Completion not working
System Details
- posh-git version/path:
1.0.0 {userPath}\Documents\PowerShell\Modules\posh-git\1.0.0 - PowerShell version:
7.1.3hosted in Windows Terminal version:1.6.10571.0 - git version:
2.29.2.windows.2 - OS:
Microsoft Windows NT 10.0.19042.0
Issue Description
I have just updated my existing posh-git installation to version 1.0.0, hoping to take advantage of pull request #779 which added the tab completion feature to PowerShell aliases.
Unfortunately it hasn't worked or not as I had expected it would have work.
For example I have created a PowerShell alias called gco for git checkout
function Execute-Git-Command {
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$True,
Position=1
)]
[String]
$GitCommand
)
Write-Host "Command:" -NoNewline -ForegroundColor Magenta
Write-Host "$GitCommand" -ForegroundColor Cyan
Invoke-Expression "$GitCommand"
}
function Git-Checkout
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$BranchName
)
if(-not($PSBoundParameters.ContainsKey('BranchName'))) {
Get-Help Git-Checkout
return
}
& Execute-Git-Command -GitCommand "$git checkout $BranchName"
}
Set-Alias -Name gco -Value Git-Checkout -Option AllScope -Force
I had expected that when I typed gco m and then pressed the tab key that the tab completion would have cycled through a suggested list of git branch names beginning with the letter m every time the tab key was pressed.
What actually happens in the above scenario is nothing after pressing the tab key the command gco m remains unchanged.
Do I need to do anything else to enable PowerShell aliases to have tab completion functionality?
Right now, the module peeks at the definition of the proxy function - Git-Checkout - in your case, and doesn't find what it expects. I was worried that this implementation was too "optimistic" on how folks might define their proxy functions. Here's the regex it is currently using:
# The regular expression here is roughly follows this pattern:
#
# <begin anchor><whitespace>*<git>(<whitespace><parameter>)*<whitespace>+<$args><whitespace>*<end anchor>
#
# The delimiters inside the parameter list and between some of the elements are non-newline whitespace characters ([^\S\r\n]).
# In those instances, newlines are only allowed if they preceded by a non-newline whitespace character.
#
# Begin anchor (^|[;`n])
# Whitespace (\s*)
# Git Command (?<cmd>$(GetAliasPattern git))
# Parameters (?<params>(([^\S\r\n]|[^\S\r\n]``\r?\n)+\S+)*)
# $args Anchor (([^\S\r\n]|[^\S\r\n]``\r?\n)+\`$args)
# Whitespace (\s|``\r?\n)*
# End Anchor ($|[|;`n])
$script:GitProxyFunctionRegex = "(^|[;`n])(\s*)(?<cmd>$(Get-AliasPattern git))(?<params>(([^\S\r\n]|[^\S\r\n]``\r?\n)+\S+)*)(([^\S\r\n]|[^\S\r\n]``\r?\n)+\`$args)(\s|``\r?\n)*($|[|;`n])"
Also, to enable this feature make sure you're importing with import-module posh-git -arg 0,0,1.
Looking at the RegEx it makes a call to
$(Get-AliasPattern git)
function Get-AliasPattern($cmd) {
$aliases = @($cmd) + @(Get-Alias | Where-Object { $_.Definition -eq $cmd } | Select-Object -Exp Name)
"($($aliases -join '|'))"
}
Then that in turn makes a call to Get-Alias where the definition has to be git as the where clause uses the -eq comparator. Don't see how it can ever return a list of Aliases as their function names (i.e. definitions) would all need to be called function git { }
I'm guessing it should return a list of Alias Definitions created for git commands.
I my case running
Get-Alias | Where-Object { $_.Definition -eq $cmd } | Select-Object -Exp Name
returns nothing.
If I run
Get-Alias | Where-Object { $_.Definition -Like "Git-*" } | Select-Object -Exp Name
Then I get a list of all my git Aliases as I've prefixed all the Alias function names with Git-. e.g. Git-Checkout.
This:
$aliases = @($cmd) + @(Get-Alias | Where-Object { $_.Definition -eq $cmd } | Select-Object -Exp Name)
Is looking for aliases of the specified $cmd. Note that the first part of the result is @($cmd). So the result will always include the passed in $cmd e.g (git). But if there's an alias (g being a common one), you'd get (git|g).
The problem is that the proxy regex is not matching your function definition. If you do something like this, it would work:
function Git-Checkout { git checkout $args }
Set-Alias -Name gco -Value Git-Checkout -Option AllScope -Force
Import-Module posh-git -arg 0,0,1
I've added a new alias to my list of aliases for regex testing purposes as suggested above:
function Git-Checkout2 { git checkout $args }
Set-Alias -Name gcko -Value Git-Checkout2 -Option AllScope -Force
I'm also setting the arguments when importing the module:
# Setup Git Posh with arguments
# [bool]$ForcePoshGitPrompt,
# [bool]$UseLegacyTabExpansion,
# [bool]$EnableProxyFunctionExpansion
Import-Module posh-git -arg 0,0,1
When I type gcko m and then hit tab nothing gets completed, I'm expecting that it will complete the branch name to master and pressing enter will run git checkout master.
My full list of aliases looks like this:
$git = "git"
$defaultRemote = "origin"
$defaultBranch = "master"
function Execute-Git-Command {
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$True,
Position=1
)]
[String]
$GitCommand
)
Write-Host "Command:" -NoNewline -ForegroundColor Magenta
Write-Host "$GitCommand" -ForegroundColor Cyan
Invoke-Expression "$GitCommand"
}
function Get-Current-Branch {
$currentBranch = Invoke-Expression "$git rev-parse --abbrev-ref HEAD"
return $currentBranch
}
function Git-Add-Remote-Upstream
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$UpstreamUrl
)
if(-not($PSBoundParameters.ContainsKey('UpstreamUrl'))) {
Get-Help Git-Add-Remote-Upstream
return
}
& Execute-Git-Command -GitCommand "$git remote add upstream $UpstreamUrl"
}
Set-Alias -Name garu -Value Git-Add-Remote-Upstream -Option AllScope -Force
function Git-Checkout
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$BranchName
)
if(-not($PSBoundParameters.ContainsKey('BranchName'))) {
Get-Help Git-Checkout
return
}
& Execute-Git-Command -GitCommand "$git checkout $BranchName"
}
Set-Alias -Name gco -Value Git-Checkout -Option AllScope -Force
function Git-Checkout2 { git checkout $args }
Set-Alias -Name gcko -Value Git-Checkout2 -Option AllScope -Force
function Git-Commit
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$CommitMessage
)
if(-not($PSBoundParameters.ContainsKey('CommitMessage'))) {
Get-Help Git-Commit
return
}
& Execute-Git-Command -GitCommand "$git commit -m ""$CommitMessage"""
}
Set-Alias -Name gcm -Value Git-Commit -Option AllScope -Force
function Git-Commit-Push
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$CommitMessage
)
if(-not($PSBoundParameters.ContainsKey('CommitMessage'))) {
Get-Help Git-Commit-Push
return
}
$currentBranch = Get-Current-Branch
& Git-Commit -CommitMessage $CommitMessage
& Git-Push-Verbose -Remote $defaultRemote -TargetBranch $currentBranch
& Git-Status
}
Set-Alias -Name gcmp -Value Git-Commit-Push -Option AllScope -Force
function Git-Delete-Branch
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$BranchName
)
if(-not($PSBoundParameters.ContainsKey('BranchName'))) {
Get-Help Git-Delete-Branch
return
}
& Git-Delete-Remote-Branch -BranchName $BranchName
& Git-Delete-Local-Branch -BranchName $BranchName
}
Set-Alias -Name gdb -Value Git-Delete-Branch -Option AllScope -Force
function Git-Delete-Local-Branch
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$BranchName
)
if(-not($PSBoundParameters.ContainsKey('BranchName'))) {
Get-Help Git-Delete-Local-Branch
return
}
& Git-Checkout -BranchName $defaultBranch
& Execute-Git-Command -GitCommand "$git branch -d $BranchName"
}
Set-Alias -Name gdlb -Value Git-Delete-Local-Branch -Option AllScope -Force
function Git-Delete-Remote-Branch
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$BranchName
)
if(-not($PSBoundParameters.ContainsKey('BranchName'))) {
Get-Help Git-Delete-Remote-Branch
return
}
& Git-Checkout -BranchName $defaultBranch
& Execute-Git-Command -GitCommand "$git push -d $defaultRemote $BranchName"
}
Set-Alias -Name gdrb -Value Git-Delete-Remote-Branch -Option AllScope -Force
function Git-Fetch
{
[CmdletBinding()]
PARAM (
)
& Execute-Git-Command -GitCommand "$git fetch"
}
Set-Alias -Name gf -Value Git-Fetch -Option AllScope -Force
function Git-Help
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$Alias
)
if(-not($PSBoundParameters.ContainsKey('Alias'))) {
Get-Help Git-Help
return
}
& Get-Help $Alias
}
Set-Alias -Name gh -Value Git-Help -Option AllScope -Force
function Git-List-Aliases
{
[CmdletBinding()]
PARAM (
)
& Get-Alias -Definition Git-* | Select-Object -Property Name, Definition, Description
}
Set-Alias -Name gla -Value Git-List-Aliases -Option AllScope -Force
function Git-List-Local-Branches
{
[CmdletBinding()]
PARAM (
)
& Execute-Git-Command -GitCommand "$git branch"
}
Set-Alias -Name gllb -Value Git-List-Local-Branches -Option AllScope -Force
function Git-List-Pending-Commits
{
[CmdletBinding()]
PARAM (
)
$currentBranch = Get-Current-Branch
& Execute-Git-Command -GitCommand "$git log --pretty=oneline $defaultRemote/$currentBranch..HEAD"
}
Set-Alias -Name glpc -Value Git-List-Pending-Commits -Option AllScope -Force
function Git-List-Remotes
{
[CmdletBinding()]
PARAM (
)
& Execute-Git-Command -GitCommand "$git remote -v"
}
Set-Alias -Name glr -Value Git-List-Remotes -Option AllScope -Force
function Git-List-Remote-Branches
{
[CmdletBinding()]
PARAM (
)
& Execute-Git-Command -GitCommand "$git branch -a"
}
Set-Alias -Name glrb -Value Git-List-Remote-Branches -Option AllScope -Force
function Git-List-Stashes
{
[CmdletBinding()]
PARAM (
)
& Execute-Git-Command -GitCommand "$git stash list"
}
Set-Alias -Name gls -Value Git-List-Stashes -Option AllScope -Force
function Git-Merge-Branch
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$SourceBranch,
[Parameter(
Mandatory=$False,
Position=2
)]
[String]
$TargetBranch
)
if(-not($PSBoundParameters.ContainsKey('SourceBranch')) -or -not($PSBoundParameters.ContainsKey('TargetBranch'))) {
Get-Help Git-Merge-Branch
return
}
& Git-Checkout -BranchName $SourceBranch
& Git-Pull-Verbose -Remote $defaultRemote -SourceBranch $SourceBranch
& Git-Checkout -BranchName $TargetBranch
& Git-Pull-Verbose -Remote $defaultRemote -SourceBranch $TargetBranch
& Execute-Git-Command -GitCommand "$git merge $SourceBranch"
}
Set-Alias -Name gmb -Value Git-Merge-Branch -Option AllScope -Force
function Git-Merge-Branch-Push
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$SourceBranch,
[Parameter(
Mandatory=$False,
Position=2
)]
[String]
$TargetBranch
)
if(-not($PSBoundParameters.ContainsKey('SourceBranch')) -or -not($PSBoundParameters.ContainsKey('TargetBranch'))) {
Get-Help Git-Merge-Branch-Push
return
}
& Git-Merge-Branch -SourceBranch $SourceBranch -TargetBranch $TargetBranch
& Git-Push-Verbose -Remote $defaultRemote -TargetBranch $TargetBranch
& Git-Status
}
Set-Alias -Name gmbp -Value Git-Merge-Branch-Push -Option AllScope -Force
function Git-Merge-Current-Branch
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$TargetBranch
)
if(-not($PSBoundParameters.ContainsKey('TargetBranch'))) {
Get-Help Git-Merge-Current-Branch
return
}
$currentBranch = Get-Current-Branch
& Git-Merge-Branch -SourceBranch $currentBranch -TargetBranch $TargetBranch
}
Set-Alias -Name gmcb -Value Git-Merge-Current-Branch -Option AllScope -Force
function Git-Merge-Current-Branch-Push
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$TargetBranch
)
if(-not($PSBoundParameters.ContainsKey('TargetBranch'))) {
Get-Help Git-Merge-Current-Branch-Push
return
}
$currentBranch = Get-Current-Branch
& Git-Merge-Branch -SourceBranch $currentBranch -TargetBranch $TargetBranch
& Git-Push-Verbose -Remote $defaultRemote -TargetBranch $TargetBranch
& Git-Status
}
Set-Alias -Name gmcbp -Value Git-Merge-Current-Branch-Push -Option AllScope -Force
function Git-New-Branch-From-Current-Branch
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$BranchName
)
if(-not($PSBoundParameters.ContainsKey('BranchName'))) {
Get-Help Git-New-Branch-From-Current-Branch
return
}
$currentBranch = Get-Current-Branch
& Git-Checkout -BranchName $currentBranch
& Git-Pull-Verbose -Remote $defaultRemote -SourceBranch $currentBranch
& Execute-Git-Command -GitCommand "$git branch $BranchName"
& Execute-Git-Command -GitCommand "$git push --set-upstream $defaultRemote $BranchName"
& Git-Checkout -BranchName $BranchName
}
Set-Alias -Name gnbfc -Value Git-New-Branch-From-Current-Branch -Option AllScope -Force
function Git-Pull
{
[CmdletBinding()]
PARAM (
)
$currentBranch = Get-Current-Branch
& Git-Pull-Verbose -Remote $defaultRemote -SourceBranch $currentBranch
}
Set-Alias -Name gp -Value Git-Pull -Option AllScope -Force
function Git-Pull-Verbose
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$Remote,
[Parameter(
Mandatory=$False,
Position=2
)]
[String]
$SourceBranch
)
if(-not($PSBoundParameters.ContainsKey('Remote')) -or -not($PSBoundParameters.ContainsKey('SourceBranch'))) {
Get-Help Git-Pull-Verbose
return
}
& Execute-Git-Command -GitCommand "$git pull $Remote $SourceBranch"
}
Set-Alias -Name gpv -Value Git-Pull-Verbose -Option AllScope -Force
function Git-Push
{
[CmdletBinding()]
PARAM (
)
$currentBranch = Get-Current-Branch
& Git-Push-Verbose -Remote $defaultRemote -TargetBranch $currentBranch
}
Set-Alias -Name gpush -Value Git-Push -Option AllScope -Force
function Git-Push-Verbose
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$Remote,
[Parameter(
Mandatory=$False,
Position=2
)]
[String]
$TargetBranch
)
if(-not($PSBoundParameters.ContainsKey('Remote')) -or -not($PSBoundParameters.ContainsKey('TargetBranch'))) {
Get-Help Git-Push-Verbose
return
}
& Execute-Git-Command -GitCommand "$git push $Remote $TargetBranch"
}
Set-Alias -Name gpushv -Value Git-Push-Verbose -Option AllScope -Force
function Git-Rebase-Branch
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$SourceBranch,
[Parameter(
Mandatory=$False,
Position=2
)]
[String]
$TargetBranch
)
if(-not($PSBoundParameters.ContainsKey('SourceBranch')) -or -not($PSBoundParameters.ContainsKey('TargetBranch'))) {
Get-Help Git-Rebase-Branch
return
}
& Git-Checkout -BranchName $SourceBranch
& Git-Pull-Verbose -Remote $defaultRemote -SourceBranch $SourceBranch
& Git-Checkout -BranchName $TargetBranch
& Git-Pull-Verbose -Remote $defaultRemote -SourceBranch $TargetBranch
& Execute-Git-Command -GitCommand "$git rebase $SourceBranch"
}
Set-Alias -Name grb -Value Git-Rebase-Branch -Option AllScope -Force
function Git-Rebase-Branch-Push
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$SourceBranch,
[Parameter(
Mandatory=$False,
Position=2
)]
[String]
$TargetBranch
)
if(-not($PSBoundParameters.ContainsKey('SourceBranch')) -or -not($PSBoundParameters.ContainsKey('TargetBranch'))) {
Get-Help Git-Rebase-Branch-Push
return
}
& Git-Rebase-Branch -SourceBranch $SourceBranch -TargetBranch $TargetBranch
& Git-Push-Verbose -Remote $defaultRemote -TargetBranch $TargetBranch
& Git-Status
}
Set-Alias -Name grbp -Value Git-Rebase-Branch-Push -Option AllScope -Force
function Git-Rebase-Current-Branch
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$SourceBranch
)
if(-not($PSBoundParameters.ContainsKey('SourceBranch'))) {
Get-Help Git-Rebase-Current-Branch
return
}
$currentBranch = Get-Current-Branch
& Git-Rebase-Branch -SourceBranch $SourceBranch -TargetBranch $currentBranch
}
Set-Alias -Name grcb -Value Git-Rebase-Current-Branch -Option AllScope -Force
function Git-Rebase-Current-Branch-Push
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$SourceBranch
)
if(-not($PSBoundParameters.ContainsKey('SourceBranch'))) {
Get-Help Git-Rebase-Current-Branch-Push
return
}
$currentBranch = Get-Current-Branch
& Git-Rebase-Branch -SourceBranch $SourceBranch -TargetBranch $currentBranch
& Git-Push-Verbose -Remote $defaultRemote -TargetBranch $currentBranch
& Git-Status
}
Set-Alias -Name grcbp -Value Git-Rebase-Current-Branch-Push -Option AllScope -Force
function Git-Status
{
[CmdletBinding()]
PARAM (
)
& Execute-Git-Command -GitCommand "$git status"
}
Set-Alias -Name gs -Value Git-Status -Option ReadOnly -Force -Description "git status"
function Git-Rename-Branch
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$OldBranch,
[Parameter(
Mandatory=$False,
Position=2
)]
[String]
$NewBranch
)
if(-not($PSBoundParameters.ContainsKey('OldBranch')) -or -not($PSBoundParameters.ContainsKey('NewBranch'))) {
Get-Help Git-Rename-Branch
return
}
& Execute-Git-Command -GitCommand "$git branch -m $OldBranch $NewBranch"
& Execute-Git-Command -GitCommand "$git push $defaultRemote :$OldBranch"
& Execute-Git-Command -GitCommand "$git push --set-upstream $defaultRemote $NewBranch"
}
Set-Alias -Name grnb -Value Git-Rename-Branch -Option AllScope -Force
function Git-Rename-Current-Branch
{
[CmdletBinding()]
PARAM (
[Parameter(
Mandatory=$False,
Position=1
)]
[String]
$NewBranch
)
if(-not($PSBoundParameters.ContainsKey('NewBranch'))) {
Get-Help Git-Rename-Current-Branch
return
}
$currentBranch = Get-Current-Branch
& Git-Rename-Branch -OldBranch $currentBranch -NewBranch $NewBranch
}
Set-Alias -Name grncb -Value Git-Rename-Current-Branch -Option AllScope -Force
function Git-Undo-All-Changes
{
[CmdletBinding()]
PARAM (
)
& Execute-Git-Command -GitCommand "$git stash push -u"
& Execute-Git-Command -GitCommand "$git stash drop"
}
Set-Alias -Name guc -Value Git-Undo-All-Changes -Option AllScope -Force -Description "Undo all local changes"
function Git-Update
{
[CmdletBinding()]
PARAM (
)
& Execute-Git-Command -GitCommand "$git update-git-for-windows"
}
Set-Alias -Name gupd -Value Git-Update -Option AllScope -Force -Description "Undo all local changes"
The gcko example you show at the top works for me. You are cd'd into a Git directory, right?

I have tried doing exactly the same as you but when I hit tab nothing happens...
N.B. I have created a master and develop branch.
I get the same result when running PowerShell 7.1.3 standalone to exclude Windows Terminal.
https://user-images.githubusercontent.com/47532258/113896285-b40a7a80-97c1-11eb-8e1d-9b738d4cd27b.mp4
Try gcko instead of gkco. :-)
This doesn’t work for me either, with a simple g → git alias. I copied over the supporting code from GitTabExpansion.ps1 and confirmed manually that the alias isn’t recognized:

Try
gckoinstead ofgkco. :-)
Even correcting my typo and using gcko instead of gkco it still doesn't give me any tab completion on branch names.
This doesn’t work for me either, with a simple
g→gitalias. I copied over the supporting code fromGitTabExpansion.ps1and confirmed manually that the alias isn’t recognized:
Well, I’m not sure what the deal is there, but I did find that my config was importing Posh-Git earlier as well as later, which is why the g alias wasn’t being recognized. The autocompletion works with the alias now that I’ve fixed that.
@Aankhen Configure the alias without an extension and configure the alias before importing posh-git and it works:

There are two issues here being conflated a bit. Simple PowerShell alias tab expansion works but there is a bug where if you specify an alias with an extension e.g. New-Alias g git.exe we don't tab expand for that. I'll work on a fix for that.
The second issue is around the use of "proxy functions" e.g. Git-Checkout. This is a harder problem to solve because of the way posh-git looks at all existing functions using a regex as a heuristic to A) guess which function we should provide tab expansion for and B) sus out command vs parameter expansion. This seems very, very brittle to me. I wonder if instead we should just provide a canned set of ArgumentCompleters with this module that you could use to decorate your function's parameters?
For what it’s worth, I use Set-Alias -Name g -Value git and PowerShell (apparently) adds the .exe itself, but that doesn’t seem to affect the Tab completion. As I mentioned earlier, I fixed the double import (which meant the alias was defined too late) and it works A-OK. 👌 I apologize for muddying the waters!
I must check that I am setting the aliases before I call
Import-Module posh-git -arg 0,0,1
I agree it's brittle to rely on a RegEx expression to parse the custom aliases as everyone will create them slightly differently like I have with not using $args as a singular parameter in the "proxy functions" for example.
Would be safer if there was some way of decorating the "proxy functions" to inform the tab completion what each function/parameter does and then provide the correct completion info.
Would be safer if there was some way of decorating the "proxy functions" to inform the tab completion what each function/parameter does and then provide the correct completion info.
Yes, that is what I was suggesting above in the "second issue". But I don't know what the feasibility is for this approach.
The second issue is around the use of "proxy functions" e.g.
Git-Checkout. This is a harder problem to solve because of the way posh-git looks at all existing functions using a regex as a heuristic to A) guess which function we should provide tab expansion for and B) sus out command vs parameter expansion. This seems very, very brittle to me. I wonder if instead we should just provide a canned set ofArgumentCompleterswith this module that you could use to decorate your function's parameters?
Yes it does seem very brittle. By decorate function parameters, do you mean creating some attributes which Posh-Git scans for? What about something like this:
# autocomplete all git checkout arguments
Register-GitArgumentCompleter -Function Git-Checkout -Command checkout
# autocomplete the branch parameter of the Git-Checkout function as a git branch
Register-GitArgumentCompleter -Function Git-Checkout -Parameter branch -Type branch
Wouldn't this be fairly simple to implement as it could just call into the existing autocompleter? Also it has the benefit of not having to scan all defined functions and their parameters so the module could import faster.
Is there any update on this?
I was experiencing this issue and found that the cause was the order of the alias getting set and the module being imported.
# Does not work
Import-Module posh-git
Set-Alias -Name g -Value git
# Works!
Set-Alias -Name g -Value git
Import-Module posh-git