-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFineFormat.completers.ps1
More file actions
111 lines (97 loc) · 4.11 KB
/
FineFormat.completers.ps1
File metadata and controls
111 lines (97 loc) · 4.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
using namespace System.Management.Automation
using namespace System.Management.Automation.Language
using namespace System.Collections
using namespace System.Collections.Generic
class PossibleValues
{
[string]$Original
[string]$Escaped
PossibleValues($in)
{
$this.Original = $in
if ($in -match '[`\[\]]')
{
$this.Escaped = $in -replace '[`\[\]]', '`$0'
$this.Escaped = $this.Escaped.Insert($this.Escaped.Length, "'").Insert(0, "'")
}
else
{
$this.Escaped = $this.Original
}
}
}
class TypeNameCompleter : IArgumentCompleter
{
[IEnumerable[CompletionResult]] CompleteArgument(
[string] $commandName,
[string] $parameterName,
[string] $wordToComplete,
[CommandAst] $commandAst,
[IDictionary] $fakeBoundParameters
)
{
$result = New-Object -TypeName 'List[CompletionResult]'
$valuesToExclude = New-Object -TypeName 'List[String]'
$possibleValues = New-Object -TypeName 'List[PossibleValues]'
$TypeNameOfValue = @()
$valuesAst = @()
[string]$command = ""
# Format-Fine -InputObject $ObjectArray -TypeName ...
if ($inputObjectParameterAst = $commandAst.Find({$args[0].GetType().Name -eq 'CommandParameterAst' -and $args[0].ParameterName -eq 'InputObject'}, $false))
{
$inputObjectParameterValueAst = $commandAst.CommandElements[$commandAst.CommandElements.IndexOf($inputObjectParameterAst) + 1]
if ($inputObjectParameterValueAst.GetType().Name -ne 'CommandParameterAst')
{
$command = $inputObjectParameterValueAst.Extent.Text
}
}
# Get-SomeObjects | Format-Fine -TypeName ...
elseif ($i = $commandAst.Parent.PipelineElements.IndexOf($commandAst))
{
$endOffset = $commandAst.Parent.PipelineElements[$i-1].Extent.EndOffset
$startOffset = $commandAst.Parent.PipelineElements[$i-1].Extent.StartOffset
$command = $commandAst.Parent.Extent.Text.Substring(0, $endOffset-$startOffset)
}
if ($command)
{
$TypeNameOfValue = [scriptblock]::Create($command).Invoke() | ForEach-Object {$_.psobject.Properties.TypeNameOfValue} | Sort-Object | Get-Unique
}
$possibleValues = $TypeNameOfValue | ForEach-Object { [PossibleValues]::new($_) }
$commandParameterAst = $commandAst.Find({$args[0].GetType().Name -eq 'CommandParameterAst' -and $args[0].ParameterName -eq $parameterName}, $false)
if ($commandParameterValueAst = $commandAst.CommandElements[$commandAst.CommandElements.IndexOf($commandParameterAst)+1])
{
# -TypeName one, two<Tab>
if ($commandParameterValueAst.GetType().Name -eq 'ArrayLiteralAst')
{
$valuesAst = $commandParameterValueAst.Elements[0..($commandParameterValueAst.Elements.Count - 2)]
}
# -TypeName one, <Tab>
elseif ($commandParameterValueAst.GetType().Name -eq 'ErrorExpressionAst')
{
$valuesAst = $commandParameterValueAst.NestedAst
}
# -TypeName one<Tab> case doesn't need to be processed, because there is nothing to exclude
foreach ($va in $valuesAst)
{
# -TypeName one,
if ($va.StringConstantType -eq 'BareWord')
{
$valuesToExclude.Add($va.SafeGetValue())
}
# -TypeName 'one',
elseif ($va.StringConstantType -eq 'SingleQuoted')
{
$valuesToExclude.Add("'$($va.SafeGetValue())'")
}
}
}
foreach ($pv in $possibleValues)
{
if ( ($pv.Escaped -like "$wordToComplete*" -or $pv.Escaped -like "'$wordToComplete*") -and $pv.Escaped -notin $valuesToExclude )
{
$result.Add([CompletionResult]::new($pv.Escaped, $pv.Original, [CompletionResultType]::ParameterValue, $pv.Original))
}
}
return $result
}
}