Skip to content

Commit a1d45c7

Browse files
committed
Improved tab completion: New functions to add help hints to parameters (GitHintTabExpansion.ps1)
1 parent 5a87e8a commit a1d45c7

File tree

3 files changed

+209
-0
lines changed

3 files changed

+209
-0
lines changed

src/GitHintTabExpansion.ps1

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
<#
2+
The following code is used to add hints to git tab completion
3+
It's called in GitTabExpansion.ps1 / Expand-GitCommand
4+
#>
5+
6+
# This caches the hints to reduce command executions
7+
$script:paramHints = @{}
8+
9+
<#
10+
.DESCRIPTION
11+
Returns a short help for the questioned git mode or $null if no help is available
12+
.PARAMETER Mode
13+
the mode for which the help is needed
14+
#>
15+
function Get-GITModeHint {
16+
param (
17+
[String] $Mode
18+
)
19+
20+
$Command="git"
21+
22+
# Ensure the "command key" is present
23+
if (-not $script:paramHints.containsKey($Command)) { $script:paramHints.add($Command, @{}) }
24+
# Populate the "mode branch" if empty
25+
if (-not $script:paramHints.$Command.containsKey("*")) {
26+
$helpStrings = Invoke-Utf8ConsoleCommand { & $Command --no-pager help -a 2>&1 }
27+
$modeTable = @{}
28+
foreach ($line in $helpStrings) {
29+
if ($line -match "\s{3,3}([^\s]*)\s+(.*)") {
30+
$modeTable.add($matches[1], $matches[2])
31+
}
32+
}
33+
$script:paramHints.$Command.add("*", $modeTable)
34+
}
35+
36+
# Create the results
37+
if ($script:paramHints.$Command."*".containsKey($Mode))
38+
{
39+
return @($Mode, $script:paramHints.$Command."*".$Mode)
40+
} else {
41+
return $null
42+
}
43+
}
44+
45+
<#
46+
.DESCRIPTION
47+
Returns a short help for the provided option or $null if no help is available
48+
.PARAMETER Mode
49+
The mode of git (e.g. commit)
50+
.PARAMETER Parameter
51+
The actual parameter, for which the help is needed
52+
#>
53+
function Get-GITParameterHint {
54+
param (
55+
[String] $Mode,
56+
[String] $Parameter
57+
)
58+
59+
$Command="git"
60+
61+
# Ensure the "command key" is present
62+
if (-not $script:paramHints.containsKey($Command)) { $script:paramHints.add($Command, @{}) }
63+
# Populate the "mode branch" if empty
64+
if (-not $script:paramHints.$Command.containsKey($Mode)) {
65+
$helpStrings = Invoke-Utf8ConsoleCommand { & $Command $Mode -h 2>&1 }
66+
$exceptions = @("diff")
67+
$preProcessedStrings = @()
68+
# Preprocessing
69+
foreach ($line in $helpStrings)
70+
{
71+
switch -RegEx ($line) {
72+
"^\s{2,2}(-.*)$" {
73+
# this a line defining a parameter, if we are in git diff
74+
if ($Mode -like "diff") { $preProcessedStrings += "$($Matches[1])" }
75+
}
76+
"^\s{15,15}(\s.*)$" {
77+
# this line belongs to the parameter description of the line before in git diff
78+
if ($Mode -like "diff") { $preProcessedStrings[-1] = "$($preProcessedStrings[-1])$($Matches[1])" }
79+
}
80+
"^\s{4,4}(-.*)$" {
81+
# this is a line defining a parameter
82+
if ($Mode -notin $exceptions) { $preProcessedStrings += "$($Matches[1])" }
83+
}
84+
"^\s{25,25}(\s.*)$" {
85+
# this line belongs to the parameter description of the line before
86+
if ($Mode -notin $exceptions) { $preProcessedStrings[-1] = "$($preProcessedStrings[-1])$($Matches[1])" }
87+
}
88+
}
89+
}
90+
$helpTable = [HashTable]::New(0, [StringComparer]::Ordinal)
91+
foreach ($line in $preProcessedStrings)
92+
{
93+
switch -RegEx ($line) {
94+
# -p, --param This is the parameter p
95+
"^(-.), --([^\s\[]+)\s+([^<]*)$" {
96+
$helpTable.add($matches[1], @(($matches[1] +" ("+ $matches[2] +")"), $matches[3]))
97+
$helpTable.add("--"+$matches[2], @(("--"+ $matches[2]), $matches[3]))
98+
break
99+
}
100+
# --param This is the parameter p
101+
"^--([^\s\[]+)\s+([^<]*)$" {
102+
$helpTable.add("--"+$matches[1], @(("--"+ $matches[1]), $matches[2]))
103+
break
104+
}
105+
# -p This is the parameter p
106+
"^(-[^-])\s+([^<]*)$" {
107+
$helpTable.add($matches[1], @($matches[1], $matches[2]))
108+
break
109+
}
110+
# -p, --param <file> This is the parameter p
111+
"^(-.), --([^\s\[]+)\s(<[^>]*>)\s+(.*)$" {
112+
$helpTable.add($matches[1], @(($matches[1] +" ("+ $matches[2] +")"), ($matches[3]+" | "+$matches[4])))
113+
$helpTable.add("--"+$matches[2], @(("--"+ $matches[2]), ($matches[3]+" | "+$matches[4])))
114+
break
115+
}
116+
# --param <file> This is the parameter p
117+
"^--([^\s\[]+)\s(<[^>]*>)\s+(.*)$" {
118+
$helpTable.add("--"+$matches[1], @(("--"+ $matches[1]), ($matches[2]+" | "+$matches[3])))
119+
break
120+
}
121+
# -p <file> This is the parameter p
122+
"^(-[^-])\s(<[^>]*>)\s+(.*)$" {
123+
$helpTable.add($matches[1], @($matches[1], ($matches[2]+" | "+$matches[3])))
124+
break
125+
}
126+
# -p, --param[=foo] This is the parameter p
127+
"^(-.), --([^\s\[]+)(\[[^\]]*\])\s+(.*)$" {
128+
$helpTable.add($matches[1], @(($matches[1] +" ("+ $matches[2] +")"), ($matches[3]+" | "+$matches[4])))
129+
$helpTable.add("--"+$matches[2], @(("--"+ $matches[2]), ($matches[3]+" | "+$matches[4])))
130+
break
131+
}
132+
# --param[=foo] This is the parameter p
133+
"^--([^\s\[]+)(\[[^\]]*\])\s+(.*)$" {
134+
$helpTable.add("--"+$matches[1], @(("--"+ $matches[1]), ($matches[2]+" | "+$matches[3])))
135+
break
136+
}
137+
# -p[=foo] This is the parameter p
138+
"^(-[^-])(\[[^\]]*\])\s+(.*)$" {
139+
$helpTable.add($matches[1], @($matches[1], ($matches[2]+" | "+$matches[3])))
140+
break
141+
}
142+
}
143+
}
144+
$script:paramHints.$Command.add($Mode, $helpTable)
145+
}
146+
147+
# Create the results
148+
if ($script:paramHints.$Command.$Mode.containsKey($Parameter))
149+
{
150+
return @(($script:paramHints.$Command.$Mode.$Parameter)[0], ($script:paramHints.$Command.$Mode.$Parameter)[1])
151+
} else {
152+
return $null
153+
}
154+
}
155+
156+
<#
157+
.DESCRIPTION
158+
The function takes the original command line and already defined possible completions; it will add the hints depending on the context
159+
.PARAMETER Command
160+
The originating command line
161+
.PARAMETER PossibleParams
162+
The possible parameters as a string array
163+
#>
164+
function Add-HintsToParams {
165+
param (
166+
[String] $Command,
167+
[String[]] $PossibleParams
168+
)
169+
170+
$cmdParts = $Command.split()
171+
172+
# We are only handling git at the moment
173+
if ($Command -notmatch "^$(Get-AliasPattern git) (.*)") { return $PossibleParams }
174+
175+
# Determing git mode, which is the first parameter without dashes, but not the last one, which is "" or an incomplete parameter
176+
$cmdMode = $null
177+
for ($i=1; $i -lt $cmdParts.length-1; $i++) {
178+
if (-not $cmdParts[$i].StartsWith("-")) {
179+
$cmdMode = $cmdParts[$i]
180+
break
181+
}
182+
}
183+
184+
$newTabCompletions = @()
185+
if ($cmdMode) {
186+
# we're searching a parameter for mode $cmdMode
187+
foreach ($p in $PossibleParams) {
188+
$desc = Get-GITParameterHint -Mode $cmdMode -Parameter $p
189+
if ($desc) {
190+
$newTabCompletions += [System.Management.Automation.CompletionResult]::new($p, $desc[0], 'ParameterValue', $desc[1])
191+
} else {
192+
$newTabCompletions += $p
193+
}
194+
}
195+
} else {
196+
# at the moment, we have no command mode in the command line and are looking for a mode
197+
foreach ($m in $PossibleParams) {
198+
$desc = Get-GITModeHint -Mode $m
199+
if ($desc) {
200+
$newTabCompletions += [System.Management.Automation.CompletionResult]::new($m, $desc[0], 'ParameterValue', $desc[1])
201+
} else {
202+
$newTabCompletions += $m
203+
}
204+
}
205+
}
206+
return $newTabCompletions
207+
}

src/GitTabExpansion.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ function script:expandParamValues($cmd, $param, $filter) {
302302

303303
function Expand-GitCommand($Command) {
304304
$res = Invoke-Utf8ConsoleCommand { GitTabExpansionInternal $Command $Global:GitStatus }
305+
$res = Add-HintsToParams -Command $Command -PossibleParams $res
305306
$res
306307
}
307308

src/posh-git.psm1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ if (Test-Path Env:\POSHGIT_ENABLE_STRICTMODE) {
1515
. $PSScriptRoot\GitUtils.ps1
1616
. $PSScriptRoot\GitPrompt.ps1
1717
. $PSScriptRoot\GitParamTabExpansion.ps1
18+
. $PSScriptRoot\GitHintTabExpansion.ps1
1819
. $PSScriptRoot\GitTabExpansion.ps1
1920
. $PSScriptRoot\TortoiseGit.ps1
2021

0 commit comments

Comments
 (0)