PowerShell ISE Convert All Aliases

Yesterday I posted an article on how to convert a selected word to an alias or cmdlet. While I think there is still some value in this piecemeal approach. sometimes you want to make wholesale changes, such as when troubleshooting a script that someone else wrote that is full of cryptic aliases. I have a function you can integrate into the ISE that will convert all aliases in a block of selected text and convert them to their full cmdlet name equivalents.

My function, ConvertTo-Definition, is designed to only work within the PowerShell ISE and assumes you want to convert all aliases to their command definitions. Personally, I don’t see a reason for converting the other way in a script but you can add that functionality if you really need it.

[cc lang=”Powershell”]
Function ConvertTo-Definition {

[cmdletbinding()]

Param(
[Parameter(Position=0,Mandatory=$True,HelpMessage=”Enter a string to convert from an alias to a command”)]
[string]$Text
)

#Verify we are in the ISE
if ($host.name -match “ISE”)
{
Write-Verbose “Getting aliases”
$aliases=get-alias | where {$_.name -notmatch “\?|\%”}

foreach ($alias in $aliases) {
#match any alias on a word boundary that doesn’t start with a $ or
#has a – before or after it.
if ($Text -match “(m?)(?<=\b)(? {
Write-Verbose ("Replacing {0} with {1}" -f $alias.name,$alias.Definition)
#replace the alias with the definition
$Text=$Text -replace "(m?)(?<=\b)(? }
} #foreach

#handle special cases of ? and %
if ($Text -match "\?")
{
Write-Verbose "Replacing with Where-Object"
$Text=$Text -replace "\?","Where-Object"
}

if ($Text -match "\%")
{
Write-Verbose "Replacing with ForEach-Object"
$Text=$Text -replace "\%","ForEach-Object"
}

Write-Verbose $text
#write the replacement string to the current file
$psise.currentfile.editor.insertText($Text)

} #if ISE
else
{
Write-Warning "You must be using the PowerShell ISE"
}
} #end function
[/cc]

The core of the function uses regular expressions, which I'll get to momentarily. But because of that I ran into snags with aliases like ? and % so when I get the current list of aliases, I skip those.

[cc lang="PowerShell"]
$aliases=get-alias | where {$_.name -notmatch "\?|\%"}
[/cc]

At the end of the script I use a simple replace for those characters.

[cc lang="PowerShell"]
#handle special cases of ? and %
if ($Text -match "\?")
{
Write-Verbose "Replacing with Where-Object"
$Text=$Text -replace "\?","Where-Object"
}

if ($Text -match "\%")
{
Write-Verbose "Replacing with ForEach-Object"
$Text=$Text -replace "\%","ForEach-Object"
}
[/cc]

Of course, if you have a ? say at the end of a comment this might get converted. In fact let me state now that the conversion may not be 100% accurate. In my testing it has been pretty good but you might have something I didn't think of. Bottom line: double check your code after converting.

The main conversion is accomplished with a regular expression pattern. A huge shout out and thanks to my PowerShell MVP brethren for helping me work out the pattern details. As you see it is pretty gnarly.

[cc lang="PowerShell"]
foreach ($alias in $aliases) {
#match any alias on a word boundary that doesn't start with a $ or
#has a - before or after it.
if ($Text -match "(m?)(?<=\b)(? {
Write-Verbose ("Replacing {0} with {1}" -f $alias.name,$alias.Definition)
#replace the alias with the definition
$Text=$Text -replace "(m?)(?<=\b)(? }
} #foreach
[/cc]

The function goes through each alias in the list and finds where it matches in the text, as long as the alias doesn't begin with a $ (you might have a variable called $ps) and isn't surrounded by a dash. This prevents Write-Host from getting converted to Write-Write-Host because Write is an alias. I could have done this with a single replace command, but I decided to use the test so that if there was a match I would write information using Write-Verbose. Even though I don't need Write-Verbose when using the function in the ISE it was invaluable in helping me develop and troubleshoot.

The function replaces all aliases with their command equivalents and then inserts the text back into the current file.

[cc lang="PowerShell"]
Write-Verbose $text
#write the replacement string to the current file
$psise.currentfile.editor.insertText($Text)
[/cc]

To use, I select as little or as much of the script in the ISE as I want, run the function and my script is automatically updated. As with my other ISE functions, the best approach is to add it to your Add-Ons menu. Thus I dot source the function in my ISE profile and then add this line to update the menu:

[cc lang="PowerShell"]
$psISE.CurrentPowerShellTab.AddOnsMenu.submenus.Add("Convert All Aliases",{ConvertTo-Definition $psise.CurrentFile.Editor.SelectedText},$Null) | Out-Null
[/cc]

As I said, I expect this to be far from perfect so I hope you'll let me know what issues you run into. This also doesn't handle parameter aliases or omitted parameters which is another problem I'd like to tackle. Parameter names may be long but at least they are meaningful.

In the mean time, download Convert-AllDefinition and let me know what you think.

2 thoughts on “PowerShell ISE Convert All Aliases”

  1. Several people have commented about why I didn’t use the tokenizer. Well, my primary answer is because I’m not a developer and don’t think that way. Perhaps my result is a little more complicated but it doesn’t rely on any .NET programming knowledge. That said, someone sent me a code sample using the tokenizer and I’m working with it. I can see the advantages and ultimately you probably don’t really care how the conversion happens so I might post a revision when I find some time to thoroughly review and test.

    Of course, if you write your script with full cmdlet names to begin with, this is all moot.

  2. Pingback: Round up « Use PowerShell

Comments are closed.