2013-02-13 26 views
12

Làm cách nào để bạn triển khai hoàn thành tab tham số cho các chức năng PowerShell hoặc lệnh ghép ngắn như Get-Service và Get-Process trong PowerShell 3.0?Hoàn thành tab giá trị tham số cmdlet PowerShell

Tôi nhận thấy ValidateSet hoạt động cho danh sách đã biết nhưng tôi muốn tạo danh sách theo yêu cầu.

Adam Driscoll hints that it is possible cho lệnh ghép ngắn nhưng tiếc là không được xây dựng.

Trevor Sullivan shows a technique cho các chức năng, nhưng như tôi đã hiểu, mã của anh ấy chỉ tạo danh sách tại thời điểm hàm được xác định.

+0

Bạn đã đọc ở đây: http://www.powertheshell.com/dynamicargumentcompletion/ –

+0

Không, tôi đã không tìm thấy điều đó. Rất thông tin –

+0

Bạn cũng có thể xem http: //powertab.codeplex.com/đó là một 'intellissense năng động' từ powershell v.2 nhưng I'use nó cũng trong 3,0 rất tốt –

Trả lời

2

Cổ điển, tôi đã sử dụng regex.

ví dụ,

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

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


Posh-git đổi tên TabExpansion để TabExpansionBackup trong GitTabExpansion.ps1.
Và TabExpansion được cải thiện của posh-git gọi TabExpansion gốc (TabExpansionBackup) khi các lần hoàn thành không khớp với lệnh git.
Vì vậy, tất cả những gì bạn phải làm là xác định lại TabExpansionBackup.

(mèo. \ GitTabExpansion.ps1 | chọn -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 } } 
    } 
} 

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

Định nghĩa lại TabExpansionBackup (gốc TabExpansion)

function TabExpansionBackup { 
    ... 

    ### Resolve Command name & parameter name 

    ... 

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

    ... 
} 
+0

Tôi thấy rằng posh-git đã được xác định chức năng này trong môi trường của tôi. Có cách nào để mở rộng/phụ lớp bất kỳ định nghĩa hiện có? –

7

Tôi bối rối về điều này một lúc, bởi vì tôi muốn làm điều tương tự. Tôi đặt cùng thứ gì đó mà tôi thực sự hài lòng.

Bạn có thể thêm thuộc tính ValidateSet từ DynamicParam. Đây là một ví dụ về nơi tôi đã tạo ValidateSet của tôi on-the-fly từ một tập tin xml. Hãy xem phần "ValidateSetAttribute" trong đoạn mã sau:

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

Với điều đó, tôi có thể gõ

Foo -modules M<press tab> 

và nó sẽ bằng tab hoàn thành "MarcusModule" nếu module đó là trong file XML. Hơn nữa, tôi có thể chỉnh sửa tệp XML và hành vi hoàn thành tab sẽ ngay lập tức thay đổi; bạn không phải nhập lại hàm.

+0

Công trình này tuyệt vời. Cảm ơn. – majkinetor

+0

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

Các vấn đề liên quan