Windows Vista Forums

Automatically expanding standard aliases
  1. #1


    Alex K. Angelopoulos [MVP] Guest

    Automatically expanding standard aliases

    One of the features I'd like in PowerShell is the ability to tab-expand
    standard aliases - e.g., when I have this
    PS> gci<TAB>
    get this:
    PS> Get-ChildItem

    There are several ways to do this; my personal quick-and-dirty approach is
    outlined below. This is a static approach; I could make it more dynamic and
    even faster by generating a lookup function on-the-fly (or periodically),
    but this works well enough in general for my needs.

    Step 1: Dump the standard TabExpansion function by redirecting to an
    external script.
    I did this by just redirecting to a separate script I use, named
    Expand-Tab.ps1. To do this, I have the following line in my profile script:

    function TabExpansion{param($line, $lastWord);Expand-Tab $line $lastWord}

    Step 2: Custom script
    The only other bit is using the following custom script.


    #Expand-Tab.ps1
    param($line, $lastWord)

    & {
    switch -regex ($lastWord)
    {
    '^[^\-\.]+$'
    {
    switch ($lastWord)
    {
    'ac' { 'Add-Content'; break;}
    'clc' { 'Clear-Content'; break;}
    'cli' { 'Clear-Item'; break;}
    'clp' { 'Clear-ItemProperty'; break;}
    'clv' { 'Clear-Variable'; break;}
    'cpi' { 'Copy-Item'; break;}
    'cpp' { 'Copy-ItemProperty'; break;}
    'cvpa' { 'Convert-Path'; break;}
    'epal' { 'Export-Alias'; break;}
    'epcsv' { 'Export-Csv'; break;}
    'fc' { 'Format-Custom'; break;}
    'fl' { 'Format-List'; break;}
    'foreach' { 'ForEach-Object'; break;}
    '%' { 'ForEach-Object'; break;}
    'ft' { 'Format-Table'; break;}
    'fw' { 'Format-Wide'; break;}
    'gal' { 'Get-Alias'; break;}
    'gc' { 'Get-Content'; break;}
    'gci' { 'Get-ChildItem'; break;}
    'gcm' { 'Get-Command'; break;}
    'gdr' { 'Get-PSDrive'; break;}
    'ghy' { 'Get-History'; break;}
    'gi' { 'Get-Item'; break;}
    'gl' { 'Get-Location'; break;}
    'gm' { 'Get-Member'; break;}
    'gp' { 'Get-ItemProperty'; break;}
    'gps' { 'Get-Process'; break;}
    'group' { 'Group-Object'; break;}
    'gsv' { 'Get-Service'; break;}
    'gsnp' { 'Get-PSSnapin'; break;}
    'gu' { 'Get-Unique'; break;}
    'gv' { 'Get-Variable'; break;}
    'gwmi' { 'Get-WmiObject'; break;}
    'iex' { 'Invoke-Expression'; break;}
    'ihy' { 'Invoke-History'; break;}
    'ii' { 'Invoke-Item'; break;}
    'ipal' { 'Import-Alias'; break;}
    'ipcsv' { 'Import-Csv'; break;}
    'mi' { 'Move-Item'; break;}
    'mp' { 'Move-ItemProperty'; break;}
    'nal' { 'New-Alias'; break;}
    'ndr' { 'New-PSDrive'; break;}
    'ni' { 'New-Item'; break;}
    'nv' { 'New-Variable'; break;}
    'oh' { 'Out-Host'; break;}
    'rdr' { 'Remove-PSDrive'; break;}
    'ri' { 'Remove-Item'; break;}
    'rni' { 'Rename-Item'; break;}
    'rnp' { 'Rename-ItemProperty'; break;}
    'rp' { 'Remove-ItemProperty'; break;}
    'rsnp' { 'Remove-PSSnapin'; break;}
    'rv' { 'Remove-Variable'; break;}
    'rvpa' { 'Resolve-Path'; break;}
    'sal' { 'Set-Alias'; break;}
    'sasv' { 'Start-Service'; break;}
    'sc' { 'Set-Content'; break;}
    'select' { 'Select-Object'; break;}
    'si' { 'Set-Item'; break;}
    'sl' { 'Set-Location'; break;}
    'sleep' { 'Start-Sleep'; break;}
    'sort' { 'Sort-Object'; break;}
    'sp' { 'Set-ItemProperty'; break;}
    'spps' { 'Stop-Process'; break;}
    'spsv' { 'Stop-Service'; break;}
    'sv' { 'Set-Variable'; break;}
    'tee' { 'Tee-Object'; break;}
    'where' { 'Where-Object'; break;}
    '?' { 'Where-Object'; break;}
    };
    break;
    }



    ###############
    # Handle property and method expansion...
    '(^.*)(\$(\w|\.)+)\.(\w*)$' {
    $method = [Management.Automation.PSMemberTypes] `
    'Method,CodeMethod,ScriptMethod,ParameterizedProperty'
    $base = $matches[1]
    $expression = $matches[2]
    Invoke-Expression ('$val=' + $expression)
    $pat = $matches[4] + '*'
    Get-Member -inputobject $val $pat | sort membertype,name |
    where { $_.name -notmatch '^[gs]et_'} |
    foreach {
    if ($_.MemberType -band $method)
    {
    # Return a method...
    $base + $expression + '.' + $_.name + '('
    }
    else {
    # Return a property...
    $base + $expression + '.' + $_.name
    }
    }
    break;
    }
    ###############





    ###############
    # Handle variable name expansion...
    '(^.*\$)(\w+)$' {
    $prefix = $matches[1]
    $varName = $matches[2]
    foreach ($v in Get-Childitem ('variable:' + $varName + '*'))
    {
    $prefix + $v.name
    }
    break;
    }
    ###############



    ###############
    # Do completion on parameters...
    '^-([\w0-9]*)' {
    $pat = $matches[1] + '*'

    # extract the command name from the string
    # first split the string into statements and pipeline elements
    # This doesn't handle strings however.
    $cmdlet = [regex]::Split($line, '[|;]')[-1]

    # Extract the trailing unclosed block e.g. ls | foreach { cp
    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 don't 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;
    }
    ###############
    }
    }



      My System SpecsSystem Spec

  2. #2


    klumsy@xtra.co.nz Guest

    Re: Automatically expanding standard aliases

    cool, trying to make powershell a bit more like powershell analyzer ?
    b.t.w i see you have the aliases hardcoded.. but you could you
    get-alias to generate that array easier, and allow for aliases added by
    the user.

    good work

    Karl


      My System SpecsSystem Spec

  3. #3


    Alex K. Angelopoulos [MVP] Guest

    Re: Automatically expanding standard aliases

    <klumsy@xtra.co.nz> wrote in message
    news:1160432977.197963.237670@i3g2000cwc.googlegroups.com...
    > cool, trying to make powershell a bit more like powershell analyzer ?


    Yes, for those people who are for some reason "analyzer-deprived".

    > b.t.w i see you have the aliases hardcoded.. but you could you
    > get-alias to generate that array easier, and allow for aliases added by
    > the user.


    Yes - but at (for me) a pretty steep performance penalty. And an added time
    investment.

    However, I think you're pointing out something that does need to be doable
    in some manner. How are you doing this in PowerShell Analyzer? What I'd been
    thinking about was a tool for creating a command database which could then
    be regenerated at will - and incidentally exported for use by other tools
    such as script editors. Doing that could make the performance of tab
    completion scream along - and possibly make it perform even more complex tab
    completion activities, such as not suggesting parameter names that have
    already been specified or are incompatible with already-specified
    parameters.



      My System SpecsSystem Spec

  4. #4


    Roman Kuzmin Guest

    Re: Automatically expanding standard aliases

    This works pretty fast (and for all available aliases):

    # Alias expansion (a case of switch($lastWord))
    '<my pattern for aliases>' {
    $alias = $matches[0] # according to <my pattern for aliases>
    if (Test-Path -Path Alias:$alias) {
    return (Get-Item Alias:$alias).Definition
    }
    break
    }

    --
    Thanks,
    Roman



      My System SpecsSystem Spec

  5. #5


    Fred J. Guest

    Re: Automatically expanding standard aliases

    Alex,
    I have a few questions about your function.
    You wrote
    > I did this by just redirecting to a separate script I use, named
    > Expand-Tab.ps1.Step 2: Custom script
    > The only other bit is using the following custom script.
    >
    >
    > #Expand-Tab.ps1
    > param($line, $lastWord)
    >
    > & {
    > switch -regex ($lastWord)
    > {

    .....
    }
    > }

    Am I correct that the first line is a comment? I know that if I type a
    function directly in a console window I write
    function Hello
    {
    param ([string] $name)

    write-output "Hello"
    write-output $name
    }

    Is the function declaration different when you place it in a 'ps1'
    file?

    Interesting enough, if I place the file in my $pshome directory it does
    not work, or rather it is not recognized by PS. What am I doing wrong?
    Thank you,
    Fred Jacobowitz


      My System SpecsSystem Spec

  6. #6


    Alex K. Angelopoulos [MVP] Guest

    Re: Automatically expanding standard aliases


    "Fred J." <swim.instructor@gmail.com> wrote in message
    news:1160450897.946452.15940@b28g2000cwb.googlegroups.com...
    > Alex,
    > I have a few questions about your function.


    >> #Expand-Tab.ps1


    > Am I correct that the first line is a comment?

    Yes. I usually make the first line of a script file the actual name I use
    for the file.

    I know that if I type a
    > function directly in a console window I write
    > function Hello
    > {
    > param ([string] $name)
    >
    > write-output "Hello"
    > write-output $name
    > }
    >
    > Is the function declaration different when you place it in a 'ps1'
    > file?


    There is no function declaration if you make it a script. Taking the case of
    your Hello function as a comparison, the equivalent script would be a file
    in your search path named Hello.ps1, and with exactly the content shown
    between the two comment lines (##########):

    ##########
    param ([string] $name)
    write-output "Hello"
    write-output $name
    ##########

    > Interesting enough, if I place the file in my $pshome directory it does
    > not work, or rather it is not recognized by PS. What am I doing wrong?


    It sounds like $pshome isn't in your search path, or possibly there's
    another issue. Could you confirm the following?
    (1) What's the value of $pshome?
    (On my system it's C:\WINDOWS\system32\WindowsPowerShell\v1.0).

    (2) What is the precise full file path to the script?
    From your description it should be something like - using the Hello.ps1
    example, since it's simpler to test -
    C:\WINDOWS\system32\WindowsPowerShell\v1.0\Hello.ps1

    (3) Is $pshome one of the elements in $envath?
    On my system, I have the search path
    C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\system32\WindowsPowerShell\v1.0;C:\bin;C:\bin\PowerShell

    (4) Usiing the hello.ps1 example, what is the complete, actual content of
    the file?
    It should be something like this:

    param ([string] $name)
    write-output "Hello"
    write-output $name

    It SHOULD NOT be something like this:

    function Hello
    {
    param ([string] $name)
    write-output "Hello"
    write-output $name
    }



      My System SpecsSystem Spec

  7. #7


    Fred J. Guest

    Re: Automatically expanding standard aliases

    Alex,
    Thank you for the explanation and examples. I finally figured out my
    problem. I created a script in '$PsHome\fred.ps1' as you described.
    But I had a file 'fred.cmd' located in c:\windows\system32.
    I finally figure it out when I renamed my script to something other
    than fred and got it to work.
    Thank you,
    Fred Jacobowitz
    ########################################################################

    Alex K. Angelopoulos [MVP] wrote:
    > "Fred J." <swim.instructor@gmail.com> wrote in message
    > news:1160450897.946452.15940@b28g2000cwb.googlegroups.com...
    > > Alex,
    > > I have a few questions about your function.

    >
    > >> #Expand-Tab.ps1

    >
    > > Am I correct that the first line is a comment?

    > Yes. I usually make the first line of a script file the actual name I use
    > for the file.
    >
    > I know that if I type a
    > > function directly in a console window I write
    > > function Hello
    > > {
    > > param ([string] $name)
    > >
    > > write-output "Hello"
    > > write-output $name
    > > }
    > >
    > > Is the function declaration different when you place it in a 'ps1'
    > > file?

    >
    > There is no function declaration if you make it a script. Taking the case of
    > your Hello function as a comparison, the equivalent script would be a file
    > in your search path named Hello.ps1, and with exactly the content shown
    > between the two comment lines (##########):
    >
    > ##########
    > param ([string] $name)
    > write-output "Hello"
    > write-output $name
    > ##########
    >
    > > Interesting enough, if I place the file in my $pshome directory it does
    > > not work, or rather it is not recognized by PS. What am I doing wrong?

    >
    > It sounds like $pshome isn't in your search path, or possibly there's
    > another issue. Could you confirm the following?
    > (1) What's the value of $pshome?
    > (On my system it's C:\WINDOWS\system32\WindowsPowerShell\v1.0).
    >
    > (2) What is the precise full file path to the script?
    > From your description it should be something like - using the Hello.ps1
    > example, since it's simpler to test -
    > C:\WINDOWS\system32\WindowsPowerShell\v1.0\Hello.ps1
    >
    > (3) Is $pshome one of the elements in $envath?
    > On my system, I have the search path
    > C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\system32\WindowsPowerShell\v1.0;C:\bin;C:\bin\PowerShell
    >
    > (4) Usiing the hello.ps1 example, what is the complete, actual content of
    > the file?
    > It should be something like this:
    >
    > param ([string] $name)
    > write-output "Hello"
    > write-output $name
    >
    > It SHOULD NOT be something like this:
    >
    > function Hello
    > {
    > param ([string] $name)
    > write-output "Hello"
    > write-output $name
    > }



      My System SpecsSystem Spec

  8. #8


    klumsy@xtra.co.nz Guest

    Re: Automatically expanding standard aliases

    i do it once.. however a user could then add new aliases, so i have a
    menu item that they can refresh the list of aliases and cmdlets.


      My System SpecsSystem Spec

  9. #9


    Alex K. Angelopoulos [MVP] Guest

    Re: Automatically expanding standard aliases

    I'm integrating this into my setup, by the way - although I'll be using
    Alias:: since I don't trust any mapped drives, even the unique ones.

    "Roman Kuzmin" <z@z.z> wrote in message
    news:e8RVL%23$6GHA.4408@TK2MSFTNGP02.phx.gbl...
    > This works pretty fast (and for all available aliases):
    >
    > # Alias expansion (a case of switch($lastWord))
    > '<my pattern for aliases>' {
    > $alias = $matches[0] # according to <my pattern for aliases>
    > if (Test-Path -Path Alias:$alias) {
    > return (Get-Item Alias:$alias).Definition
    > }
    > break
    > }
    >
    > --
    > Thanks,
    > Roman
    >




      My System SpecsSystem Spec

  10. #10


    Alex K. Angelopoulos [MVP] Guest

    Re: Automatically expanding standard aliases

    Doh!
    I've done that a few times. Since I had begun adopting the PowerShell naming
    conventions for WSH scripts a few years ago, I've even had hyphenated
    'legacy' scripts that caused mysterious failures. :|

    "Fred J." <swim.instructor@gmail.com> wrote in message
    news:1160465945.305105.145460@i3g2000cwc.googlegroups.com...
    > Alex,
    > Thank you for the explanation and examples. I finally figured out my
    > problem. I created a script in '$PsHome\fred.ps1' as you described.
    > But I had a file 'fred.cmd' located in c:\windows\system32.
    > I finally figure it out when I renamed my script to something other
    > than fred and got it to work.
    > Thank you,
    > Fred Jacobowitz
    > ########################################################################
    >
    > Alex K. Angelopoulos [MVP] wrote:
    >> "Fred J." <swim.instructor@gmail.com> wrote in message
    >> news:1160450897.946452.15940@b28g2000cwb.googlegroups.com...
    >> > Alex,
    >> > I have a few questions about your function.

    >>
    >> >> #Expand-Tab.ps1

    >>
    >> > Am I correct that the first line is a comment?

    >> Yes. I usually make the first line of a script file the actual name I use
    >> for the file.
    >>
    >> I know that if I type a
    >> > function directly in a console window I write
    >> > function Hello
    >> > {
    >> > param ([string] $name)
    >> >
    >> > write-output "Hello"
    >> > write-output $name
    >> > }
    >> >
    >> > Is the function declaration different when you place it in a 'ps1'
    >> > file?

    >>
    >> There is no function declaration if you make it a script. Taking the case
    >> of
    >> your Hello function as a comparison, the equivalent script would be a
    >> file
    >> in your search path named Hello.ps1, and with exactly the content shown
    >> between the two comment lines (##########):
    >>
    >> ##########
    >> param ([string] $name)
    >> write-output "Hello"
    >> write-output $name
    >> ##########
    >>
    >> > Interesting enough, if I place the file in my $pshome directory it does
    >> > not work, or rather it is not recognized by PS. What am I doing wrong?

    >>
    >> It sounds like $pshome isn't in your search path, or possibly there's
    >> another issue. Could you confirm the following?
    >> (1) What's the value of $pshome?
    >> (On my system it's C:\WINDOWS\system32\WindowsPowerShell\v1.0).
    >>
    >> (2) What is the precise full file path to the script?
    >> From your description it should be something like - using the Hello.ps1
    >> example, since it's simpler to test -
    >> C:\WINDOWS\system32\WindowsPowerShell\v1.0\Hello.ps1
    >>
    >> (3) Is $pshome one of the elements in $envath?
    >> On my system, I have the search path
    >>
    >> C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\system32\WindowsPowerShell\v1.0;C:\bin;C:\bin\PowerShell
    >>
    >> (4) Usiing the hello.ps1 example, what is the complete, actual content of
    >> the file?
    >> It should be something like this:
    >>
    >> param ([string] $name)
    >> write-output "Hello"
    >> write-output $name
    >>
    >> It SHOULD NOT be something like this:
    >>
    >> function Hello
    >> {
    >> param ([string] $name)
    >> write-output "Hello"
    >> write-output $name
    >> }

    >




      My System SpecsSystem Spec

Page 1 of 2 12 LastLast
Automatically expanding standard aliases problems?

Similar Threads
Thread Thread Starter Forum Replies Last Post
Vistal standard accounts automatically be promoted to Administrator norris1 System Security 1 11 Jan 2010
Email aliases in WLM 2009? Lankod Live Mail 0 20 Mar 2009
Can’t Delete a User with no Aliases KingJ50 General Discussion 8 08 May 2008
Howto: Automatically scanning and generating aliases Alex K. Angelopoulos [MVP] PowerShell 1 23 Jun 2006
Suggestion: Add the 6 missing standard aliases to PowerShell Alex K. Angelopoulos [MVP] PowerShell 1 22 Jun 2006