Compartilhar via


Powershell Tab expansion

One of the things which annoys me about Powershell is that having (in effect) extended the available commands with functions and filters, Tab expansion doesn't find them. I was aware that people have done some clever things extending Tab-expansion (Power Tab being the obvious example), but they seemed like overkill for the one little thing I wanted.  Looking at the Powershell Community Extensions I noticed that they also change tab expansion, and a little bit of digging found there was already a function called TabExpansion. (The is also one called prompt.)

To paraphrase a line Arnie got in Predator "if it's a function I can re-program it " So I had a look at the code for TabExpansion, Type function:\TabExpandsion | clip  and it basically goes

 param($line, $lastWord)

& {
    switch -regex ($lastWord)

    {

        # Handle property and method expansion...

        'RegularExpression' {Script block}         # Handle variable name expansion...

        'Regular Expression' {Script block}          # Do completion on parameters...

        'Regular Expression' {Script block}     }
 } 

So all I needed to do was to put in some code for functions. The only complication I had was that cmdlet and file expansion is handled back the shell itself if TabExpansion() doesn't return any results. So if I ONLY check for functions I won't get all the things I want - e.g. typing st [tab] will return the "Start-Demo" function but not the cmdlets Start-Process Start-Service, Start-Sleep, Start-Transcript; nor will it find stuff.csv. So I had to put some lines in to do that. What I ended up with a regular Expression {scrip block}   to go into the switch as follows.

     '^(\w+)$'{             $Commands = (get-command -type function,externalscript,alias,cmdlet "$lastWord*") +  
    (get-command "$lastWord*" | where {$_.name -match ".exe"})                if ($commands -ne $null) {$Commands 
                                        get-childItem "$lastWord*" | % {$_.name} } 
              break;             }     

 

This returns 3 kinds of data firstly st [tab] returns start-demo [Function] and  Start-Process Start-Service, Start-Sleep, Start-Transcript [Cmdlets], the second Get-Command allows no [tab] to find notepad.exe (without returning lots of DLLs). And the Get-ChildItem ensures Stuff.csv is offered as well as the various starts. Originally I returned all 3 regardless but I found this replacing the expansion of filenames with something that worked less well - it didn't put quotes round names with spaces in for a start. So I only return filenames from the function if there are also commands to return, otherwise I let the shell find files for me.

So far this is working quite well, but I'd be interested to know what other people use.

Technorati Tags: Microsoft,Powershell

Comments

  • Anonymous
    March 24, 2008
    Now that is neat.  I like this