Main | Contact | Blog | Documentation

PowerShell Framework

The project dedicated to empowering your PowerShell scripting.



Covers the basics of implementing custom tab expansion.



Any of the following two must be true, in order for custom tabcompletion to apply:

If neither is true, it will silently not have any effect. Since this is a feature of user convenience, not a functional prerequisite, this should not have any effect on automation.

The Order of Things

Custom tab completion in PSFramework consists of two steps:

For both there are commands provided by the module.

Declaring a Scriptblock

All you really need for this to work is a name and a scriptblock:

# Create scriptblock that collects information and name it
Register-PSFTeppScriptblock -Name "mymodule.alcohol" -ScriptBlock {
    'Beer', 'Mead', 'Whiskey', 'Wine', 'Vodka', 'Rum (3y)', 'Rum (5y)', 'Rum (7y)'

The scriptblock could execute any arbitrary piece of code, such as looking up active directory, perform SQL queries. The scriptblock will not be executed within the scope of the module declaring it!

To execute code within the scope of your module, you need to invoke it in that module:

Register-PSFTeppScriptblock -Name "mymodule.beerlabel" -ScriptBlock {
    $module = Get-Module MyModule
    & $module { $script:Fridge.Label | Select-Object -Unique }

You do not need to handle what the user already typed before completing - the system is handling this for you.

Assigning a Scriptblock

To assign the scriptblock, three things are needed:

# Assign scriptblock to function
Register-PSFTeppArgumentCompleter -Command Get-Alcohol -Parameter Type -Name "mymodule.alcohol"

Nothing in this claims you can only provide custom tab completion only for your own commands! You can update tab completion for commands in other modules. This allows using this system in your profile to customize tab completion to your environment (for example to auto-populate the list of Hyper-V hosts to connect to).

Module Design Advice

When implementing this in your module, there are three main ways to distribute your code. No matter which you choose in the end, you should pick one mode and stick with it for your entire project.

Function Driven

Maintain the scriptblock definitions in their own, individual files, in their own folder. When compiling your module into a single file - if you do so - be sure to place them above the function definitions. If you do not compile your module into a single file, still make sure to have them executed before loading your commands.

Maintain and execute your assignments right below the commands you are assigning them to.

This makes it easy to see all aspects of a function within the file containing the function, while still being able to assign the same scriptblock multiple times.

Function Defined

Maintain both scriptblock definition & assignment in the same file the function completed for is stored.

This is the easiest way to maintain the added complexity within your module. However it makes it a lot harder to reuse scriptblocks and thus is not recommended if you make extensive use of this feature. Use with care and on lower scale implementations only.

Structure Driven

Maintain both scriptblock definition and assignment separate from each other and from the command.

This is the recommended path if you make extensive use of custom tab completion and structure your module by the type of resource implemented.

Scriptblock Implementation Notes

There are more advanced topics to help building your scriptblock:


Back to Tab Expansion

Version 1.0
Written on: 2018-06-18
Updated on: 2018-06-18