src/cmdlets/common/ArgumentCompletionHelper.ps1
# Copyright 2018, Adam Edwards # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ScriptClass ArgumentCompletionHelper { static { $__ArgumentCompleters = @{} function __RegisterArgumentCompleterScriptBlock([ScriptBlock] $argumentCompleter, $completionType) { $this.__ArgumentCompleters.Add($completionType, $argumentCompleter) } function __GetCompleter($completionType) { $completerBlock = $this.__ArgumentCompleters[$completionType] if ( ! $completerBlock ) { throw [ArgumentException]::new("Unknown ArgumentCompletionType '{0}'" -f $completionType) } $completerBlock } function RegisterArgumentCompleter([string] $command, [string[]] $parameterNames, $completionType) { $completerBlock = __GetCompleter $completionType $parameterNames | foreach { Register-ArgumentCompleter -commandname $command -ParameterName $_ -ScriptBlock $completerBlock } } function FindMatchesStartingWith($target, $sortedItems) { $sortedItemsCollection = try { if ( $sortedItems.Count -eq 0 ) { return $null } $sortedItems } catch [System.Management.Automation.PropertyNotFoundException] { # Don't assign an array / collection of size 1 here as PowerShell # converts this to a non-array / collection! Do it outside the catch } # This happens if $sortedItems is not an array, i.e. it is # just one string. if ( ! $sortedItemsCollection ) { $sortedItemsCollection = @($sortedItems) } $matchingItems = @() $lastMatch = $null $interval = $sortedItemsCollection.Count / 2 $current = $interval / 2 $previous = -1 if ( $target.length -ne 0 ) { while ( [int] $previous -ne [int] $current ) { $interval /= 2 $previous = $current $item = $sortedItemsCollection[[int]$current] $comparison = $target.CompareTo($item) if ( $comparison -gt 0 ) { $current += $interval } else { if ( $item.StartsWith($target) ) { $lastMatch = [int] $current } $current -= $interval } } } else { $lastMatch = 0 } if ( $lastMatch -ne $null ) { for ( $startsWithCandidate = $lastMatch; $startsWithCandidate -lt $sortedItemsCollection.Count; $startsWithCandidate++ ) { $candidate = $sortedItemsCollection[$startsWithCandidate] if ( ! $candidate.StartsWith($target) ) { break } $matchingItems += $candidate } } $matchingItems } } } |