about_Functions_Argument_Completion

简短说明

参数补全是 PowerShell 的一项功能,提供提示、启用发现和加快参数值的输入。

长说明

本文介绍为 PowerShell 函数实现参数补全程序的不同方法。 参数补全程序提供参数的可能值。 当用户在参数名称后按 Tab 键时,系统会在运行时计算可用值。 可通过多种方式为参数定义参数补全程序。

注意

Tab 是 Windows 上的默认键绑定。 可以使用 PSReadLine 模块或托管 PowerShell 的应用程序更改此键绑定。 在非 Windows 平台上,键绑定可能有所不同。 有关详细信息,请参阅 about_PSReadLine

ValidateSet 属性

ValidateSet 属性指定参数或变量的一组有效值,并启用 Tab 自动补全。 如果参数或变量值与集中的值不匹配,PowerShell 将生成错误。 在以下示例中,Fruit 参数的值只能为 Apple、Banana 或 Pear。

Param(
    [Parameter(Mandatory=$true)]
    [ValidateSet('Apple', 'Banana', 'Pear')]
    [string[]]
    $Fruit
)

在以下示例中,$flavor 变量的值必须是 Chocolate、Strawberry 或 Vanilla。 ValidateSet 属性可用于任何变量,而不仅仅用于参数。

[ValidateSet('Chocolate', 'Strawberry', 'Vanilla')]
[string]$flavor = 'Strawberry'

每次分配该变量时,都会进行验证,即使是在脚本中进行分配。

Param(
    [ValidateSet('hello', 'world')]
    [string]$Message
)

$Message = 'bye'

此示例会在运行时返回以下错误:

MetadataError: The attribute cannot be added because variable Message with
value bye would no longer be valid.

有关 Tab 扩展的详细信息,请参阅 about_Tab_Expansion

使用类的动态 ValidateSet 值

可以使用 Class 在运行时动态生成 ValidateSet 的值。 在以下示例中,变量 $Sound 的有效值是通过名为 SoundNames 的 Class 生成的,该 Class 检查三个文件系统路径中是否有可用的声音文件:

Class SoundNames : System.Management.Automation.IValidateSetValuesGenerator {
    [string[]] GetValidValues() {
        $SoundPaths = '/System/Library/Sounds/',
                      '/Library/Sounds',
                      '~/Library/Sounds'
        $SoundNames = ForEach ($SoundPath in $SoundPaths) {
            If (Test-Path $SoundPath) {
                (Get-ChildItem $SoundPath).BaseName
            }
        }
        return [string[]] $SoundNames
    }
}

然后,[SoundNames] 类作为动态 ValidateSet 值实施,如下所示:

Param(
    [ValidateSet([SoundNames])]
    [string]$Sound
)

注意

IValidateSetValuesGenerator 类是在 PowerShell 6.0 中引入的。

ArgumentCompletions 属性

通过 ArgumentCompletions 属性,你可以向特定参数添加 Tab 自动补全值。 必须为每个需要 Tab 自动补全的参数定义 ArgumentCompletions 属性。 ArgumentCompletions 属性与 ValidateSet 类似。 当用户在参数名称后按 Tab 时,这两个属性都会接收要显示的值的列表。 不过,与 ValidateSet 不同,这些值未经验证,更像是建议。 因此,用户可以提供任何值(不仅仅是列表中的值)。

ArgumentCompletions 属性不得与 ArgumentCompleter 属性混淆,后者需要脚本块来定义选项。 指定的值可用

语法如下:

function Test-ArgumentCompletions {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [ArgumentCompletions('Fruits', 'Vegetables')]
        $Type,

        [Parameter()]
        [ArgumentCompletions('Apple', 'Banana', 'Orange')]
        $Fruit,

        [Parameter()]
        [ArgumentCompletions('Onion', 'Carrot', 'Lettuce')]
        $Vegetable
    )
}

为每个参数提供了 ArgumentCompletions 属性的选项列表,以启用 Tab 自动补全。

此属性是在 PowerShell 6.0 中引入的。

ArgumentCompleter 属性

通过 ArgumentCompleter 属性,你可以向特定参数添加 Tab 自动补全值。 必须为每个需要 Tab 自动补全的参数定义 ArgumentCompleter 属性。

若要添加 ArgumentCompleter 属性,需要定义用于确定值的脚本块。 脚本块必须按照下面指定的顺序采用以下参数。 参数的名称并不重要,因为值按位置提供。

语法如下:

function MyArgumentCompleter {
    Param(
        [Parameter(Mandatory)]
        [ArgumentCompleter( {
            param ( $commandName,
                    $parameterName,
                    $wordToComplete,
                    $commandAst,
                    $fakeBoundParameters )
            # Perform calculation of tab completed values here.
        } )]
        $ParamName
    )
}

ArgumentCompleter 脚本块

脚本块参数设置为以下值:

  • $commandName(位置 0)- 此参数设置为脚本块提供 Tab 完成的命令的名称。
  • $parameterName(位置 1)- 此参数设置为其值需要 Tab 完成的参数。
  • $wordToComplete(位置 2)- 此参数设置为用户在按下 Tab 之前提供的值。脚本块应使用此值来确定 Tab 完成值。
  • $commandAst(位置 3)- 此参数设置为当前输入行的抽象语法树 (AST)。 有关详细信息,请参阅 AST 类型文档。
  • $fakeBoundParameters(位置 4)- 此参数设置为在用户按下 Tab 之前包含 cmdlet 的 $PSBoundParameters 的哈希表。有关详细信息,请参阅 about_Automatic_Variables

ArgumentCompleter 脚本块必须使用管道(例如 ForEach-ObjectWhere-Object)或其他合适的方法展开值。 返回值数组会导致 PowerShell 将整个数组视为一个 Tab 完成值。

以下示例将 Tab 自动补全添加到 Value 参数。 如果仅指定了 Value 参数,则会显示 Value 的所有可能值或参数。 指定 Type 参数时,Value 参数仅显示该类型的可能值。

此外,-like 运算符可确保在用户键入以下命令并使用 Tab 自动补全的情况下仅返回 Apple。

Test-ArgumentCompleter -Type Fruits -Value A

function MyArgumentCompleter{
    param ( $commandName,
            $parameterName,
            $wordToComplete,
            $commandAst,
            $fakeBoundParameters )

    $possibleValues = @{
        Fruits = @('Apple', 'Orange', 'Banana')
        Vegetables = @('Onion', 'Carrot', 'Lettuce')
    }

    if ($fakeBoundParameters.ContainsKey('Type')) {
        $possibleValues[$fakeBoundParameters.Type] | Where-Object {
            $_ -like "$wordToComplete*"
        }
    } else {
        $possibleValues.Values | ForEach-Object {$_}
    }
}

function Test-ArgumentCompleter {
[CmdletBinding()]
 param (
        [Parameter(Mandatory=$true)]
        [ValidateSet('Fruits', 'Vegetables')]
        $Type,

        [Parameter(Mandatory=$true)]
        [ArgumentCompleter({ MyArgumentCompleter @args })]
        $Value
      )
}

基于类的参数补全程序

从 PowerShell 7.2 开始,添加了一项新功能,让你能够定义参数化参数补全程序的更多泛型实现。

通过从 ArgumentCompleterAttribute 进行派生,可以创建可重复使用的泛型补全程序,例如:

[DirectoryCompleter(ContainingFile="pswh.exe", Depth=2)]

[DateCompleter(WeekDay='Monday', From="LastYear")]

[GitCommits(Branch='release')]

派生的属性必须实现 IArgumentCompleterFactory 接口,并使用属性值创建专用补全程序。

using namespace System.Collections
using namespace System.Collections.Generic
using namespace System.Management.Automation
using namespace System.Management.Automation.Language

class NumberCompleter : IArgumentCompleter {

    [int] $From
    [int] $To
    [int] $Step

    NumberCompleter([int] $from, [int] $to, [int] $step) {
        if ($from -gt $to) {
            throw [ArgumentOutOfRangeException]::new("from")
        }
        $this.From = $from
        $this.To = $to
        $this.Step = $step -lt 1 ? 1 : $step
    }

    [IEnumerable[CompletionResult]] CompleteArgument(
        [string] $CommandName,
        [string] $parameterName,
        [string] $wordToComplete,
        [CommandAst] $commandAst,
        [IDictionary] $fakeBoundParameters) {

        $resultList = [List[CompletionResult]]::new()
        $local:to = $this.To
        $local:step = $this.Step
        for ($i = $this.From; $i -lt $to; $i += $step) {
            $resultList.Add([CompletionResult]::new($i.ToString()))
        }

        return $resultList
    }
}

class NumberCompletionsAttribute : ArgumentCompleterAttribute, IArgumentCompleterFactory {
    [int] $From
    [int] $To
    [int] $Step

    NumberCompletionsAttribute([int] $from, [int] $to, [int] $step) {
        $this.From = $from
        $this.To = $to
        $this.Step = $step
    }

    [IArgumentCompleter] Create() { return [NumberCompleter]::new($this.From, $this.To, $this.Step) }
}

因此,PowerShell 中的用法如下:

function Add{
    param(
       [NumberCompletions(0, 100, 5)]
       [int] $X,

       [NumberCompletions(0, 100, 5)]
       [int] $Y
    )
    $X + $Y
}

Register-ArgumentCompleter

Register-ArgumentCompleter cmdlet 会注册自定义参数完成程序。 通过参数完成程序,可以在运行时为指定的任何命令提供动态 Tab 完成。

有关详细信息,请参阅 Register-ArgumentCompleter

另请参阅