FineFormat.completers.ps1
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 } } |