2013-02-13 13 views
12

W jaki sposób zaimplementować uzupełnianie karty parametrów dla funkcji PowerShell lub poleceń cmdlet takich jak Get-Service i Get-Process w PowerShell 3.0?Zakończono zakończenie wartości parametru cmdlet PowerShell:

Zdaję sobie sprawę, że ValidateSet działa dla znanej listy, ale chcę wygenerować listę na żądanie.

Adam Driscoll hints that it is possible dla cmdletów, ale niestety nie został opracowany.

Trevor Sullivan shows a technique dla funkcji, ale jak rozumiem, jego kod generuje listę tylko wtedy, gdy funkcja jest zdefiniowana.

+0

Czy znasz tutaj: http://www.powertheshell.com/dynamicargumentcompletion/ –

+0

Nie, nie znalazłem tego. Bardzo informacyjny –

+0

Możesz również zajrzeć do http: //powertab.codeplex.com/jest to "dynamiczna intellisencja" z wersji powershell v.2, ale ja też to w 3.0 bardzo dobrze –

Odpowiedz

2

Klasycznie, użyłem wyrażenia regularnego.

np

function TabExpansion { 

    param($line, $lastWord) 

    if ($line -match '(-(\w+))\s+([^-]*$)') 
    { 
    ### Resolve Command name & parameter name 
     $_param = $matches[2] + '*' 
     $_opt = $Matches[3].Split(" ,")[-1] + '*' 
     $_base = $Matches[3].Substring(0,$Matches[3].Length-$Matches[3].Split(" ,")[-1].length) 

     $_cmdlet = [regex]::Split($line, '[|;=]')[-1] 

     if ($_cmdlet -match '\{([^\{\}]*)$') 
     { 
      $_cmdlet = $matches[1] 
     } 

     if ($_cmdlet -match '\(([^()]*)$') 
     { 
      $_cmdlet = $matches[1] 
     } 

     $_cmdlet = $_cmdlet.Trim().Split()[0] 

     $_cmdlet = @(Get-Command -type 'Cmdlet,Alias,Function,Filter,ExternalScript' $_cmdlet)[0] 

     while ($_cmdlet.CommandType -eq 'alias') 
     { 
      $_cmdlet = @(Get-Command -type 'Cmdlet,Alias,Function,Filter,ExternalScript' $_cmdlet.Definition)[0] 
     } 

    ### Currently target is Get-Alias & "-Name" parameter 

     if ("Get-Alias" -eq $_cmdlet.Name -and "Name" -like $_param) 
     { 
      Get-Alias -Name $_opt | % { $_.Name } | sort | % { $_base + ($_ -replace '\s','` ') } 
      break; 
     } 
    } 
} 

odniesienia http://gallery.technet.microsoft.com/scriptcenter/005d8bc7-5163-4a25-ad0d-25cffa90faf5


Posh-git jego nazwy TabExpansion do TabExpansionBackup w GitTabExpansion.ps1.
Zmodyfikowana TabExpansion posh-gita wywołuje oryginalną TabExpansion (TabExpansionBackup), gdy uzupełnienia nie są zgodne z poleceniami git.
Wszystko, co musisz zrobić, to zmienić definicję TabExpansionBackup.

(cat \ GitTabExpansion.ps1 |. Wybrać -last 18)
============================== GitTabExpansion .ps1 ==============================

if (Test-Path Function:\TabExpansion) { 
    Rename-Item Function:\TabExpansion TabExpansionBackup 
} 

function TabExpansion($line, $lastWord) { 
    $lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart() 

    switch -regex ($lastBlock) { 
     # Execute git tab completion for all git-related commands 
     "^$(Get-AliasPattern git) (.*)" { GitTabExpansion $lastBlock } 
     "^$(Get-AliasPattern tgit) (.*)" { GitTabExpansion $lastBlock } 

     # Fall back on existing tab expansion 
     default { if (Test-Path Function:\TabExpansionBackup) { TabExpansionBackup $line $lastWord } } 
    } 
} 

=========== ================================================== ==================

definiuj TabExpansionBackup (oryginalna TabExpansion)

function TabExpansionBackup { 
    ... 

    ### Resolve Command name & parameter name 

    ... 

    ### Currently target is Get-Alias & "-Name" parameter 

    ... 
} 
+0

Widzę, że ekskluzywny git już zdefiniował tę funkcję w moim środowisku. Czy istnieje sposób rozszerzenia/podklasy jakiejkolwiek istniejącej definicji? –

7

Przez chwilę zastanawiałem się nad tym, ponieważ chciałem zrobić to samo. Stworzyłem coś, z czego jestem naprawdę zadowolony.

Możesz dodać atrybuty ValidateSet z DynamicParam. Oto przykład, gdzie wygenerowałem mój ValidateSet w locie z pliku xml. Patrz "ValidateSetAttribute" w poniższym kodzie:

function Foo() { 
    [CmdletBinding()] 
    Param() 
    DynamicParam { 
     # 
     # The "modules" param 
     # 
     $modulesAttributeCollection = new-object -Type System.Collections.ObjectModel.Collection[System.Attribute] 

     # [parameter(mandatory=..., 
     #  ... 
     #)] 
     $modulesParameterAttribute = new-object System.Management.Automation.ParameterAttribute 
     $modulesParameterAttribute.Mandatory = $true 
     $modulesParameterAttribute.HelpMessage = "Enter one or more module names, separated by commas" 
     $modulesAttributeCollection.Add($modulesParameterAttribute)  

     # [ValidateSet[(...)] 
     $moduleNames = @() 
     foreach($moduleXmlInfo in Select-Xml -Path "C:\Path\to\my\xmlFile.xml" -XPath "//enlistment[@name=""wp""]/module") { 
      $moduleNames += $moduleXmlInfo.Node.Attributes["name"].Value 
     } 
     $modulesValidateSetAttribute = New-Object -type System.Management.Automation.ValidateSetAttribute($moduleNames) 
     $modulesAttributeCollection.Add($modulesValidateSetAttribute) 

     # Remaining boilerplate 
     $modulesRuntimeDefinedParam = new-object -Type System.Management.Automation.RuntimeDefinedParameter("modules", [String[]], $modulesAttributeCollection) 

     $paramDictionary = new-object -Type System.Management.Automation.RuntimeDefinedParameterDictionary 
     $paramDictionary.Add("modules", $modulesRuntimeDefinedParam) 
     return $paramDictionary 
    } 
    process { 
     # Do stuff 
    } 
} 

Z tym, mogę wpisać

Foo -modules M<press tab> 

i będzie tab-complete "MarcusModule" jeśli moduł był w pliku XML. Ponadto mogę edytować plik XML, a zachowanie zakończenia karty natychmiast zmieni się; nie musisz ponownie importować funkcji.

+0

Działa to świetnie. Dzięki. – majkinetor

+0

http://stackoverflow.com/a/23001637/288393 –

Powiązane problemy