Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell cmdlet parameter value tab completion

How do you implement the parameter tab completion for PowerShell functions or cmdlets like Get-Service and Get-Process in PowerShell 3.0?

I realise ValidateSet works for a known list, but I want to generate the list on demand.

Adam Driscoll hints that it is possible for cmdlets but unfortunately hasn't elaborated.

Trevor Sullivan shows a technique for functions, but as I understand it, his code only generates the list at the time the function is defined.

like image 716
David Gardiner Avatar asked Feb 13 '13 00:02

David Gardiner


People also ask

Does PowerShell have tab completion?

Built-in tab completion featuresPowerShell has enabled tab completion for many aspects of the command line experience.

What does %% mean in PowerShell?

% is an alias for the ForEach-Object cmdlet. An alias is just another name by which you can reference a cmdlet or function.

What does CLC do in PowerShell?

Description. The Clear-Content cmdlet deletes the contents of an item, such as deleting the text from a file, but it does not delete the item. As a result, the item exists, but it is empty. Clear-Content is similar to Clear-Item , but it works on items with contents, instead of items with values.

Which key is used for auto completing the entry in PowerShell ISE?

To automatically complete a cmdlet parameter entry In the Command Pane or Script pane, type a cmdlet followed by a dash and then press TAB . For example, type Get-Process - and then press TAB multiple times to display each of the parameters for the cmdlet in turn.


2 Answers

I puzzled over this for a while, because I wanted to do the same thing. I put together something that I'm really happy with.

You can add ValidateSet attributes from a DynamicParam. Here's an example of where I've generated my ValidateSet on-the-fly from an xml file. See the "ValidateSetAttribute" in the following code:

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

With that, I can type

Foo -modules M<press tab>

and it will tab-complete "MarcusModule" if that module was in the XML file. Furthermore, I can edit the XML file and the tab-completion behavior will immediately change; you don't have to re-import the function.

like image 143
Marcus Avatar answered Sep 20 '22 06:09

Marcus


Check the TabExpansionPlusPlus module on github, written by a former PowerShell team magician.

https://github.com/lzybkr/TabExpansionPlusPlus#readme

like image 45
Shay Levy Avatar answered Sep 24 '22 06:09

Shay Levy