Добавить настраиваемое средство завершения аргументов для командлета?

Как добавить динамическое завершение вкладок аргументов в командлет PowerShell?

Когда я набираю это и нажимаю 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

Я нашел этот ответ, который дал пару полезных ссылок и сказал, что я должен запустить Get-Content function:TabExpansion2:

введите здесь описание изображения

Это выглядит как Необходимо реализовать CommandCompletion.CompleteInput. Я думал, что где-то читал, что существует Hashtable команд для функций. Если да, то где это и как установить кастомные? Я использую Chocolatey для распространения Paket.PowerShell. Вот код командлета.

ОБНОВЛЕНИЕ 20.06.2015:

Я закончил тем, что заставил его работать с кодом здесь: 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}'

Важны более полные имена параметров. Если их переименовать, это не сработает.


person Cameron Taggart    schedule 18.06.2015    source источник
comment
Другой важной частью было выполнение этого скрипта при загрузке модуля. Это было сделано путем добавления этого в .psd1: ScriptsToProcess = 'ArgumentTabCompletion.ps1'   -  person Cameron Taggart    schedule 21.06.2015


Ответы (2)


Вы можете взглянуть на модуль TabExpansion++, который был разработан, чтобы упростить расширение завершения табуляции.

Я просто играл с ним несколько минут, и я думаю, что вы хотите что-то вроде этого, основываясь на примере:

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 $_ 
        }   
}
person Mike Zboray    schedule 18.06.2015
comment
Я разместил свое решение выше. Я отмечаю это как ответ, так как это привело меня к этому решению. - person Cameron Taggart; 21.06.2015

Они называются динамическими параметрами и описаны в about_Functions_Advanced_Parameters.

В следующем примере показан образец функции со стандартными параметрами с именами Name и Path и необязательным динамическим параметром с именем DP1. Параметр DP1 находится в наборе параметров PSet1 и имеет тип Int32. Параметр DP1 доступен в функции Sample только в том случае, если значение параметра 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
        }
    }
}

Вот еще один пример. который выполняет динамические наборы проверки.


Я перечитал ваш вопрос, и, похоже, вам просто нужен статический, заранее определенный список значений, заполненных табуляцией, для определенного параметра. В этом случае вы можете просто использовать [ValidateSet()] атрибут:

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

Но если значения необходимо определить во время выполнения, вместо этого см. выше раздел о динамических параметрах.

person briantist    schedule 18.06.2015