2013-02-13 85 views
12

如何在PowerShell 3.0中为PowerShell函数或cmdlet(如Get-Service和Get-Process)实施参数选项卡完成?PowerShell cmdlet参数值选项卡完成

我知道ValidateSet适用于已知列表,但我希望根据需要生成列表。

亚当Driscoll hints that it is possible为cmdlet,但不幸的是没有阐述。

Trevor Sullivan shows a technique函数,但据我所知,他的代码只在函数定义时生成列表。

+0

你读过这里:http://www.powertheshell.com/dynamicargumentcompletion/ – 2013-02-13 06:55:03

+0

不,我没有找到。非常丰富的 – 2013-02-13 10:57:22

+0

你也可以看一下http://powertab.codeplex。com /这是一个来自PowerShell v.2的'动态intellissense',但我也用它在3.0非常好 – 2013-02-13 10:59:28

回答

2

经典,我用正则表达式。

例如,

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; 
     } 
    } 
} 

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


辣妹-git的重命名TabExpansion到TabExpansionBackup在GitTabExpansion.ps1。
当完成与git命令不匹配时,posh-git的redifined TabExpansion调用原始TabExpansion(TabExpansionBackup)。
所以你所要做的就是重新定义TabExpansionBackup。

(cat。\ GitTabExpansion.ps1 | select -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 } } 
    } 
} 

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

重新定义TabExpansionBackup(原始TabExpansion)

function TabExpansionBackup { 
    ... 

    ### Resolve Command name & parameter name 

    ... 

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

    ... 
} 
+0

我看到posh-git已经在我的环境中定义了这个函数。有没有办法扩展/分类任何现有的定义? – 2013-02-13 23:13:22

7

我对此感到困惑,因为我想要做同样的事情。我整理了一些我很满意的东西。

您可以从DynamicParam添加ValidateSet属性。以下是我从xml文件即时生成ValidateSet的示例。请参阅“ValidateSetAttribute”在下面的代码:

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 
    } 
} 

就这样,我可以输入

Foo -modules M<press tab> 

,它会选项卡完成“MarcusModule”如果该模块是XML文件英寸此外,我可以编辑XML文件并且标签完成行为将立即改变;您不必重新导入该功能。

+0

这很好。谢谢。 – majkinetor 2015-02-28 09:21:09

+0

http://stackoverflow.com/a/23001637/288393 – 2016-03-04 13:19:46