Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

246 lines (202 sloc) 8.885 kb
# Initial implementation by Jeremy Skinner
# http://www.jeremyskinner.co.uk/2010/03/07/using-git-with-windows-powershell/
$Global:GitTabSettings = New-Object PSObject -Property @{
AllCommands = $false
}
$subcommands = @{
bisect = 'start bad good skip reset visualize replay log run'
notes = 'edit show'
reflog = 'expire delete show'
remote = 'add rename rm set-head show prune update'
stash = 'list show drop pop apply branch save clear create'
submodule = 'add status init update summary foreach sync'
svn = 'init fetch clone rebase dcommit branch tag log blame find-rev set-tree create-ignore show-ignore mkdirs commit-diff info proplist propget show-externals gc reset'
tfs = 'bootstrap checkin checkintool ct cleanup cleanup-workspaces clone diagnostics fetch help init pull quick-clone rcheckin shelve shelve-list unshelve verify'
}
function script:gitCmdOperations($command, $filter) {
$subcommands.$command -split ' ' |
where { $_ -like "$filter*" }
}
$script:someCommands = @('add','am','annotate','archive','bisect','blame','branch','bundle','checkout','cherry','cherry-pick','citool','clean','clone','commit','config','describe','diff','difftool','fetch','format-patch','gc','grep','gui','help','init','instaweb','log','merge','mergetool','mv','notes','prune','pull','push','rebase','reflog','remote','rerere','reset','revert','rm','shortlog','show','stash','status','submodule','svn','tag','whatchanged')
function script:gitCommands($filter, $includeAliases) {
$cmdList = @()
if (-not $global:GitTabSettings.AllCommands) {
$cmdList += $someCommands -like "$filter*"
} else {
$cmdList += git help --all |
where { $_ -match '^ \S.*' } |
foreach { $_.Split(' ', [StringSplitOptions]::RemoveEmptyEntries) } |
where { $_ -like "$filter*" }
}
if ($includeAliases) {
$cmdList += gitAliases $filter
}
$cmdList | sort
}
function script:gitRemotes($filter) {
git remote |
where { $_ -like "$filter*" }
}
function script:gitBranches($filter, $includeHEAD = $false) {
$prefix = $null
if ($filter -match "^(?<from>\S*\.{2,3})(?<to>.*)") {
$prefix = $matches['from']
$filter = $matches['to']
}
$branches = @(git branch --no-color | foreach { if($_ -match "^\*?\s*(?<ref>.*)") { $matches['ref'] } }) +
@(git branch --no-color -r | foreach { if($_ -match "^ (?<ref>\S+)(?: -> .+)?") { $matches['ref'] } }) +
@(if ($includeHEAD) { 'HEAD','FETCH_HEAD','ORIG_HEAD','MERGE_HEAD' })
$branches |
where { $_ -ne '(no branch)' -and $_ -like "$filter*" } |
foreach { $prefix + $_ }
}
function script:gitRemoteBranches($remote, $ref, $filter) {
git branch --no-color -r |
where { $_ -like " $remote/$filter*" } |
foreach { $ref + ($_ -replace " $remote/","") }
}
function script:gitStashes($filter) {
(git stash list) -replace ':.*','' |
where { $_ -like "$filter*" } |
foreach { "'$_'" }
}
function script:gitFiles($filter, $files) {
$files | sort |
where { $_ -like "$filter*" } |
foreach { if($_ -like '* *') { "'$_'" } else { $_ } }
}
function script:gitIndex($filter) {
gitFiles $filter $GitStatus.Index
}
function script:gitAddFiles($filter) {
gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Working.Added))
}
function script:gitCheckoutFiles($filter) {
gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Working.Deleted))
}
function script:gitDeleted($filter) {
gitFiles $filter $GitStatus.Working.Deleted
}
function script:gitAliases($filter) {
git config --get-regexp ^alias\. | foreach {
if($_ -match "^alias\.(?<alias>\S+) .*") {
$alias = $Matches['alias']
if($alias -like "$filter*") {
$alias
}
}
} | Sort
}
function script:expandGitAlias($cmd, $rest) {
if((git config --get-regexp "^alias\.$cmd`$") -match "^alias\.$cmd (?<cmd>[^!].*)`$") {
return "git $($Matches['cmd'])$rest"
} else {
return "git $cmd$rest"
}
}
function GitTabExpansion($lastBlock) {
if($lastBlock -match "^$(Get-AliasPattern git) (?<cmd>\S+)(?<args> .*)$") {
$lastBlock = expandGitAlias $Matches['cmd'] $Matches['args']
}
# Handles tgit <command> (tortoisegit)
if($lastBlock -match "^$(Get-AliasPattern tgit) (?<cmd>\S*)$") {
# Need return statement to prevent fall-through.
return $tortoiseGitCommands | where { $_ -like "$($matches['cmd'])*" }
}
switch -regex ($lastBlock -replace "^$(Get-AliasPattern git) ","") {
# Handles git <cmd> <op>
"^(?<cmd>$($subcommands.Keys -join '|'))\s+(?<op>\S*)$" {
gitCmdOperations $matches['cmd'] $matches['op']
}
# Handles git remote (rename|rm|set-head|set-branches|set-url|show|prune) <stash>
"^remote.* (?:rename|rm|set-head|set-branches|set-url|show|prune).* (?<remote>\S*)$" {
gitRemotes $matches['remote']
}
# Handles git stash (show|apply|drop|pop|branch) <stash>
"^stash (?:show|apply|drop|pop|branch).* (?<stash>\S*)$" {
gitStashes $matches['stash']
}
# Handles git bisect (bad|good|reset|skip) <ref>
"^bisect (?:bad|good|reset|skip).* (?<ref>\S*)$" {
gitBranches $matches['ref'] $true
}
# Handles git branch -d|-D|-m|-M <branch name>
# Handles git branch <branch name> <start-point>
"^branch.* (?<branch>\S*)$" {
gitBranches $matches['branch']
}
# Handles git <cmd> (commands & aliases)
"^(?<cmd>\S*)$" {
gitCommands $matches['cmd'] $TRUE
}
# Handles git help <cmd> (commands only)
"^help (?<cmd>\S*)$" {
gitCommands $matches['cmd'] $FALSE
}
# Handles git push remote <ref>:<branch>
"^push.* (?<remote>\S+) (?<ref>[^\s\:]*\:)(?<branch>\S*)$" {
gitRemoteBranches $matches['remote'] $matches['ref'] $matches['branch']
}
# Handles git push remote <branch>
# Handles git pull remote <branch>
"^(?:push|pull).* (?:\S+) (?<branch>[^\s\:]*)$" {
gitBranches $matches['branch']
}
# Handles git pull <remote>
# Handles git push <remote>
# Handles git fetch <remote>
"^(?:push|pull|fetch).* (?<remote>\S*)$" {
gitRemotes $matches['remote']
}
# Handles git reset HEAD <path>
# Handles git reset HEAD -- <path>
"^reset.* HEAD(?:\s+--)? (?<path>\S*)$" {
gitIndex $matches['path']
}
# Handles git <cmd> <ref>
"^commit.*-C\s+(?<ref>\S*)$" {
gitBranches $matches['ref'] $true
}
# Handles git add <path>
"^add.* (?<files>\S*)$" {
gitAddFiles $matches['files']
}
# Handles git checkout -- <path>
"^checkout.* -- (?<files>\S*)$" {
gitCheckoutFiles $matches['files']
}
# Handles git rm <path>
"^rm.* (?<index>\S*)$" {
gitDeleted $matches['index']
}
# Handles git <cmd> <ref>
"^(?:checkout|cherry-pick|diff|difftool|log|merge|rebase|reflog\s+show|reset|revert|show).* (?<ref>\S*)$" {
gitBranches $matches['ref'] $true
}
}
}
$PowerTab_RegisterTabExpansion = Get-Command Register-TabExpansion -Module powertab -ErrorAction SilentlyContinue
if ($PowerTab_RegisterTabExpansion)
{
& $PowerTab_RegisterTabExpansion "git.exe" -Type Command {
param($Context, [ref]$TabExpansionHasOutput, [ref]$QuoteSpaces) # 1:
$line = $Context.Line
$lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
$TabExpansionHasOutput.Value = $true
GitTabExpansion $lastBlock
}
return
}
if (Test-Path Function:\TabExpansion) {
Rename-Item Function:\TabExpansion TabExpansionBackup
}
function TabExpansion($line, $lastWord) {
$lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
switch -regex ($lastBlock) {
# Execute git tab completion for all git-related commands
"^$(Get-AliasPattern git) (.*)" { GitTabExpansion $lastBlock }
"^$(Get-AliasPattern tgit) (.*)" { GitTabExpansion $lastBlock }
# Fall back on existing tab expansion
default { if (Test-Path Function:\TabExpansionBackup) { TabExpansionBackup $line $lastWord } }
}
}
Jump to Line
Something went wrong with that request. Please try again.