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