This blog has moved to http://ThePowerShellGuy.com
Greetings /\/\o\/\/
I made another addition to the Tab Completion handeling of PowerShell, multilevel Variable completion.
*Edit* There are newer versions of this script, you can find the
latest on my new blog : The PowerShell Guy ( http://ThePowerShellGuy.com
)
This versions are much more powerfull
Just download the latest PowerTab.ZIP file from the overview page
here : http://thepowershellguy.com/blogs/posh/pages/powertab.aspx
run PowetTabSetup.Ps1 and you are ready to go
***
I made this addition as the standard tabcompletion, does only expand methods and properties on the first level, and on hitting [tab] the what I did find very annoying.
e.g.
$host.U [tab]
$host.UI
$host.UI.R [Tab]
$host.UI
$host.UI.RawUI.f [Tab]
$host.UI
with the new tabexpansion function :
$Host.UI.Ra [tab]
$Host.UI.RawUI. [tab]
$Host.UI.RawUI.get_BackgroundColor()
$Host.UI.RawUI.get_BackgroundColor().Ge [tab] [tab]
$Host.UI.RawUI.get_BackgroundColor().GetType()
PoSH>$Host.UI.RawUI.Fo [tab]
PoSH>$Host.UI.RawUI.ForegroundColor
Gray
Now the following changes are made from the default tab handling :
# - Methods and properties of types
[regex]::M [tab]
[regex]::Match(
# - tab completion on types.
[system.ma [tab]
[System.Management.Ma [tab] [tab]
[System.Management.ManagementClass]
# DBMwS: Added Progressbar and Scoped variable name expansion
$env:A [tab]
$env:ALLUSERSPROFILE
$global:dt [tab]
$global:dtAssemblies
# - shows get_ methods
removed filter to also see get_ methods handy for WMI and AD
# - MultiLevel variable Tab Completion
PoSH>$Host.UI.RawUI.Fo [tab]
PoSH>$Host.UI.RawUI.ForegroundColor
# - Bracet Removal
this one I did add for new-object use, as a shortcut so that I can use tabcompletion on the -TypeName parameter, I type a '[' complete the typename, type '=' and [tab] and the braces are removed.
new-object [s [tab]
new-object [System.Ma [tab]
new-object [System.Management.Ma [tab]
new-object [System.Management.ManagementClass]
new-object [System.Management.ManagementClass]= [tab]
new-object System.Management.ManagementClass
# show assemblyname in progressbar
just a visual change.
and here is the new function TabExpansion function :.
# TabExpansion.ps1
# Version 0.4
# Replacement of default TabExpansion function
# /\/\o\/\/ 2006
function TabExpansion {
# This is the default function that gets called for tab expansion.
# Edited by /\/\o\/\/ from the original to handle :
# - Cached tab completion on types (janel / mow).
# - Methods and properties of types
# - shows get_ methods
# - MultiLevel variable Tab Completion
# - Bracet Removal
# Edited by DBMwS: Added Progressbar and Scoped variable name expansion
param($line, $lastWord)
begin {
$_Method = [Management.Automation.PSMemberTypes] 'Method,CodeMethod,ScriptMethod,ParameterizedProperty'
$_ScopeNames = @("global", "local", "script", "private")
}
process {
switch -regex ($lastWord)
{
# Handle methods of Types (/\/\o\/\/)..
'(\[.*\])::(\w*)' {
invoke-expression "$($matches[1]) gm -static" where {$_.name -like "$($matches[2])*"} % {
if ($_.MemberType -band $_Method) {
"$($matches[1])::$($_.name)" + '('
} Else {
"$($matches[1])::$($_.name)"
}
}
break;
}
# Remove Brackets from typename (/\/\o\/\/)
'(\[.*\])=(\w*)' {
"$($matches[1].replace('[','').replace(']',''))"
break;
}
# Cache and Handle namespace and TypeNames (/\/\o\/\/) ..
'\[(.*)' {
$matched = $matches[1]
# only the first time Fill a DataTable with Typenames,namespaces and dotCount (level)
if (!($global:dtAssemblies)) {
$global:dtAssemblies = New-Object System.Data.Datatable
[VOID]($global:dtAssemblies.Columns.add('name',[string]))
[VOID]($global:dtAssemblies.Columns.add('DC',[int]))
[VOID]($global:dtAssemblies.Columns.add('NS',[string]))
$assemblies = [appdomain]::CurrentDomain.getassemblies()
[void] ($assemblies % {$i = 0} {
$i++;
[int]$assemblyProgress = ($i * 100) / $assemblies.Length
write-progress "Adding Assembly $($_.getName().name):" "$assemblyProgress" -perc $assemblyProgress
$types = $_.GetTypes()
$types % {$j = 0} {
$j++;
if (($j % 200) -eq 0) {
[int]$typeProgress = ($j * 100) / $types.Length
write-progress "Adding types percent complete :"`
"$typeProgress" -perc $typeProgress -id 1
}
$dc = $_.fullName.split(".").count - 1
$ns = $_.namespace
$global:dtAssemblies.rows.add("$_",$dc,$ns)
}
write-progress "Adding types percent complete :" "100" -perc 100 -id 1
})
}
# actual tab completion
$dots = $matches[1].split(".").count - 1
switch ($dots) {
0 {"[System","[Microsoft"}
Default {
$res = @()
$res += $global:dtAssemblies.select("ns like '$($matched)%' and dc = $($dots + 1)")
select -uni ns % {"[$($_.ns)"};
$res += $global:dtAssemblies.select("name like '$($matched)%' and dc = $dots") % {"[$($_.name)]"}
$res
}
}
break;
}
# Handle property and method expansion (MultiLevel added /\/\o\/\/)...
'\$(\w+)\.(.*)' {
$variableName = $matches[1]
$val = '$' + $matches[1]
$level = $matches[2].split('.').count
if ($level -gt 1) {
$ofs = '.';$val = '$' + $variableName + ".$($matches[2].split('.')[0..($level -2)])"
}
$pat = $matches[2].split('.')[($level -1)] + '*'
# /\/\o\/\/ removed : -and $n -notmatch '^[ge]et_'
# to get get_ methods on WMI and AD objects
invoke-expression "Get-Member -inputobject $val" where {$n = $_.name; $n -like $pat } foreach {
if ($_.MemberType -band $_method)
{
# Return a method...
$val + '.' + $_.name + '('
}
else {
# Return a property...
$val + '.' + $_.name
}
}
break;
}
# Handle expansions for both "Scope Variable Name" and "Type Variable Names" (DbmwS)
'(.*^\$)(\w+):(\w*)$' {
$type = $matches[2]; # function, variable, etc.. that are not scopes
$prefix = $matches[1] + $type; # $ + function
$typeName = $matches[3]; # e.g. in '$function:C', value will be 'C'
if ($_ScopeNames -contains $type) {
# Scope Variable Name Expansion
foreach ($scopeVariable in
(Get-Variable "$($typeName)*" -Scope $type Sort-Object name)) {
$prefix + ":" + $scopeVariable.Name
}
} else {
# Type name expansion($function:, $variable, $env: ,etc)
foreach ($t in (Get-ChildItem ($type + ":" + $typeName + '*') Sort-Object name)) {
$prefix + ":" + $t.Name
}
}
break;
}
# Handle variable name expansion (original)...
'(.*^\$)(\w+)$' {
$prefix = $matches[1]
$varName = $matches[2]
foreach ($v in Get-Childitem ('variable:' + $varName + '*')) {
$prefix + $v.name
}
break;
}
# Do completion on parameters (original) ...
'^-([\w0-9]*)' {
$pat = $matches[1] + '*'
# extract the command name from the string
# first split the string into statements and pipeline elements
# This doesnt handle strings however.
$cmdlet = [regex]::Split($line, '[;]')[-1]
# Extract the trailing unclosed block
if ($cmdlet -match '\{([^\{\}]*)$') {
$cmdlet = $matches[1]
}
# Extract the longest unclosed parenthetical expression...
if ($cmdlet -match '\(([^()]*)$') {
$cmdlet = $matches[1]
}
# take the first space separated token of the remaining string
# as the command to look up. Trim any leading or trailing spaces
# so you dont get leading empty elements.
$cmdlet = $cmdlet.Trim().Split()[0]
# now get the info object for it...
$cmdlet = @(Get-Command -type 'cmdlet,alias' $cmdlet)[0]
# loop resolving aliases...
while ($cmdlet.CommandType -eq 'alias') {
$cmdlet = @(Get-Command -type 'cmdlet,alias' $cmdlet.Definition)[0]
}
# expand the parameter sets and emit the matching elements
foreach ($n in $cmdlet.ParameterSets Select-Object -expand parameters) {
$n = $n.name
if ($n -like $pat) { '-' + $n }
}
break;
}
} # EO switch
} # EO Process
}
you can past al code to a PowerShell console,
or save it to a file and start it dotsourced (from your profile):
. .\Tabcompletion.ps1
Enjoy,
Greetings /\/\o\/\/
Tags : Monad msh PowerShell