如何在 PowerShell 3.0 中为 PowerShell 函数或 cmdlet(如 Get-Service 和 Get-Process)实现参数选项卡完成?
我意识到ValidateSet适用于已知列表,但我想按需生成列表。
Adam Driscoll暗示cmdlet 是可能的,但遗憾的是没有详细说明。
Trevor Sullivan展示了一种函数技术,但据我了解,他的代码仅在定义函数时生成列表。
如何在 PowerShell 3.0 中为 PowerShell 函数或 cmdlet(如 Get-Service 和 Get-Process)实现参数选项卡完成?
我意识到ValidateSet适用于已知列表,但我想按需生成列表。
Adam Driscoll暗示cmdlet 是可能的,但遗憾的是没有详细说明。
Trevor Sullivan展示了一种函数技术,但据我了解,他的代码仅在定义函数时生成列表。
我对此感到困惑了一段时间,因为我想做同样的事情。我整理了一些我非常满意的东西。
您可以从 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>
如果该模块在 XML 文件中,它将使用制表符完成“MarcusModule”。此外,我可以编辑 XML 文件,制表符完成行为将立即改变;您不必重新导入该功能。
查看 github 上的 TabExpansionPlusPlus 模块,该模块由前 PowerShell 团队魔术师编写。
经典地,我使用正则表达式。
例如,
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
Posh-git 在 GitTabExpansion.ps1 中将 TabExpansion 重命名为 TabExpansionBackup。
当完成与 git 命令不匹配时,posh-git 重新定义的 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
...
}