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

PowerShell Alias Tab Completion not working #852

Open
adrianwright109 opened this issue Apr 6, 2021 · 18 comments
Open

PowerShell Alias Tab Completion not working #852

adrianwright109 opened this issue Apr 6, 2021 · 18 comments

Comments

@adrianwright109
Copy link

System Details

  • posh-git version/path: 1.0.0 {userPath}\Documents\PowerShell\Modules\posh-git\1.0.0
  • PowerShell version: 7.1.3 hosted 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?

@rkeithhill
Copy link
Collaborator

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.

@adrianwright109
Copy link
Author

adrianwright109 commented Apr 6, 2021

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.

@rkeithhill
Copy link
Collaborator

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

@adrianwright109
Copy link
Author

adrianwright109 commented Apr 7, 2021

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"

@rkeithhill
Copy link
Collaborator

The gcko example you show at the top works for me. You are cd'd into a Git directory, right?

PoshGitProxyFuncCompletion

@adrianwright109
Copy link
Author

adrianwright109 commented Apr 7, 2021

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.

git.aliases.mp4

@rkeithhill
Copy link
Collaborator

Try gcko instead of gkco. :-)

@Aankhen
Copy link

Aankhen commented Apr 8, 2021

This doesn’t work for me either, with a simple ggit alias. I copied over the supporting code from GitTabExpansion.ps1 and confirmed manually that the alias isn’t recognized:

Copying Get-AliasPattern, $GitProxyFunctionRegex, and the Select-Object line that uses it shows that my g alias doesn’t match

@adrianwright109
Copy link
Author

Try gcko instead of gkco. :-)

Even correcting my typo and using gcko instead of gkco it still doesn't give me any tab completion on branch names.

@Aankhen
Copy link

Aankhen commented Apr 8, 2021

This doesn’t work for me either, with a simple ggit alias. I copied over the supporting code from GitTabExpansion.ps1 and 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.

@rkeithhill
Copy link
Collaborator

@Aankhen Configure the alias without an extension and configure the alias before importing posh-git and it works:

posh-git-alias-tab-completion

@rkeithhill
Copy link
Collaborator

rkeithhill commented Apr 8, 2021

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?

@Aankhen
Copy link

Aankhen commented Apr 8, 2021

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!

@adrianwright109
Copy link
Author

adrianwright109 commented Apr 8, 2021

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.

@rkeithhill
Copy link
Collaborator

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.

@0x0309
Copy link

0x0309 commented Apr 10, 2021

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?

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.

@hoang-himself
Copy link

Is there any update on this?

@MisinformedDNA
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants