为Cmdlet添加自定义参数完成程序?

时间:2015-06-18 19:04:09

标签: powershell cmdlet chocolatey

如何将动态参数选项卡完成添加到PowerShell Cmdlet?

当我输入此内容并点击tab时,我希望它可以完成标签。

PM> Paket-Add -NuGet FSharp.Co

这些是我想在此示例中使用的值:

PM> Paket-FindPackages -SearchText FSharp.Co
FSharp.Core
FSharp.Core.3
FSharp.Configuration
FSharp.Core.Fluent-3.1
FSharp.Core.Fluent-4.0
FSharp.Compiler.Tools
FSharp.Compatibility.Scala
FSharp.Compatibility.OCaml
FSharp.Compiler.CodeDom
FSharp.Compiler.Service
FSharp.Control.Reactive
FSharp.Compatibility.Haskell
FSharp.Compatibility.OCaml.Numerics
FSharp.Compatibility.OCaml.Format
FSharp.Compatibility.OCaml.System
FSharp.Collections.ParallelSeq
FSharp.Compatibility.StandardML
FSharp.Compatibility.OCaml.LexYacc
FSharp.Control.AsyncSeq

我发现this answer提供了一些有用的链接,并说我应该运行Get-Content function:TabExpansion2

enter image description here

看起来CommandCompletion.CompleteInput需要实施。我以为我在某处读到函数有Hashtable个命令。如果是这样,它在哪里以及如何安装自定义的?我正在使用Chocolatey来分发Paket.PowerShell。这是Cmdlet code

更新2015-06-20:

我最终让它在这里使用代码: https://github.com/fsprojects/Paket/blob/76de1c44853ce09029ba157855525f435d951b85/src/Paket.PowerShell/ArgumentTabCompletion.ps1

# https://github.com/mariuszwojcik/RabbitMQTools/blob/master/TabExpansions.ps1
function createCompletionResult([string]$text, [string]$value, [string]$tooltip) {
    if ([string]::IsNullOrEmpty($value)) { return }
    if ([string]::IsNullOrEmpty($text)) { $text = $value }
    if ([string]::IsNullOrEmpty($tooltip)) { $tooltip = $value }
    $completionText = @{$true="'$value'"; $false=$value  }[$value -match "\W"]
    $completionText = $completionText -replace '\[', '``[' -replace '\]', '``]'
    New-Object System.Management.Automation.CompletionResult $completionText, $text, 'ParameterValue', $tooltip | write
}

$findPackages = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
    Paket-FindPackages -SearchText $wordToComplete -Max 100 | % {
        createCompletionResult $_ $_ $_ | write
    }
}

$findPackageVersions = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
    if (-not $fakeBoundParameter.NuGet){ return }
    Paket-FindPackageVersions -Name $fakeBoundParameter.NuGet -Max 100 | % {
        createCompletionResult $_ $_ $_ | write
    }
}

# create and add $global:options to the list of completers
# http://www.powertheshell.com/dynamicargumentcompletion/
if (-not $global:options) { $global:options = @{CustomArgumentCompleters = @{};NativeArgumentCompleters = @{}}}

$global:options['CustomArgumentCompleters']['Paket-Add:NuGet'] = $findPackages
$global:options['CustomArgumentCompleters']['Paket-Add:Version'] = $findPackageVersions

$function:tabexpansion2 = $function:tabexpansion2 -replace 'End\r\n{','End { if ($null -ne $options) { $options += $global:options} else {$options = $global:options}'

完成者参数名称很重要。重命名它们将使其无效。

2 个答案:

答案 0 :(得分:1)

这些被称为Dynamic parameters and are described in about_Functions_Advanced_Parameters

  

以下示例显示了带标准的示例函数   名为Name和Path的参数,以及可选的动态参数   DP1参数在PSet1参数集中并且有一个   Int32的类型。 Sample函数中提供了DP1参数   仅当Path参数的值包含" HKLM:",表示   它正在HKEY_LOCAL_MACHINE注册表驱动器中使用。

function Get-Sample {
    [CmdletBinding()]
    Param ([String]$Name, [String]$Path)

    DynamicParam
    {
        if ($path -match ".*HKLM.*:")
        {
            $attributes = new-object System.Management.Automation.ParameterAttribute
            $attributes.ParameterSetName = "__AllParameterSets"
            $attributes.Mandatory = $false
            $attributeCollection = new-object -Type System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection.Add($attributes)

            $dynParam1 = new-object -Type System.Management.Automation.RuntimeDefinedParameter("dp1", [Int32], $attributeCollection)

            $paramDictionary = new-object -Type System.Management.Automation.RuntimeDefinedParameterDictionary
            $paramDictionary.Add("dp1", $dynParam1)
            return $paramDictionary
        }
    }
}

Here's another example that does validation sets dynamically

我已经重新阅读了您的问题,看起来您可能只想要一个特定参数的标签已完成值的静态预定义列表。如果是这种情况,那么您只需use the [ValidateSet()] attribute

function Get-Something {
[CmdletBinding()]
param(
    [ValidateSet('One','Two','Three')]
    [String]
    $MyParam
)
}

但是如果需要在运行时确定值,那么请参阅上面关于动态参数的部分。

答案 1 :(得分:1)

您可能需要查看TabExpansion++ module,它旨在简化扩展标签的完成。

我刚刚玩了几分钟,我觉得你想要这样的事情基于这个例子:

Import-Module TabExpansion++

function PaketAddNugetCompletion
{
    [ArgumentCompleter(Parameter = 'Nuget', Command = 'Paket-Add')]
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Paket-FindPackages -SearchText $wordToComplete |
        ForEach-Object {
            # not quite sure what property to use off the result, but this might work.
            New-CompletionResult -CompletionText $_ 
        }   
}