Let PSReadline Handle PowerShell — Part 5

PowerShell Text Purple hero
ln the last article, I introduced you to PSReadline’s key handlers. These are blocks of code that PSReadline will execute when a particular key or key combination is detected. You can get rather sophisticated, although it might require some advanced PowerShell scripting skills. Many of the things you might want to accomplish require some specific features of the .NET classes that support PSReadline.  Sometimes, the best way to learn is to copy, paste, and try it out for yourself.
 

 
There is some documentation in the about_psreadline help file, although some of it is outdated or not as specific as it needs to be. The help file also mentions SamplePSReadlineProfile.ps1 with additional examples, but as far as I can tell it is not installed as part of the module. But, you can view it in the GitHub repository. I have used some of the examples as starting points for my own handlers. You can always see your current handlers with Get-PSReadlineKeyHandler. Let’s start with something simple.

Add to History

This handler will add the current command, entered at the prompt, to the PSReadlineHistory but not execute it.

Set-PSReadlineKeyHandler -Key Alt+w -BriefDescription SaveInHistory -LongDescription "Save current line in history but do not execute" -ScriptBlock {
    $line = $null
    $cursor = $null
    #get the current line
    [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
    #add to the history file
    [Microsoft.PowerShell.PSConsoleReadLine]::AddToHistory($line)
    #undo the current line
    [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
}

I am using the ALT+W key combination, which is not case-sensitive in Windows. The premise is that you type a command at a prompt, only to realize you needed to do something first. With this key handler, you can press Alt+W, which will copy the command to your PSReadlineHistory and then clear the line. You can enter the command you meant to run, then use the Up arrow or find the previously stored command from the history file, and load it back to your prompt. You really need to test this out for yourself.
 

Run Non-PowerShell Commands

The script block for your handler can run any PowerShell code. This means you can run just about anything you can think of. Here is a handler that will launch Notepad.

Set-PSReadlineKeyHandler -Chord Alt+F11 -BriefDescription "Open Notepad" -Description "Launch notepad.exe" -ScriptBlock {
notepad.exe
}

Of course, you can choose whatever key combination you want. In my example, I am using Alt+F11. Or how about this to open your PSReadline history file with the associated application for .txt files?

Set-PSReadlineKeyHandler -chord Ctrl+h -BriefDescription "Open PSReadlineHistory" -ScriptBlock {
#open the history file with the associated application for .txt files, probably Notepad.
Invoke-Item -Path $(Get-PSReadlineOption).HistorySavePath
}

Note that PSReadline should run in PowerShell on Linux, so you would need to ensure that your script block will work on that platform or that the key combination will be detected.

Copy Command to a File

Here is one that I put together that will take the current command, copy it to a ps1 file, and then open it in your editor.

Set-PSReadlineKeyHandler -chord Ctrl+Alt+E -BriefDescription "Copy to file" -Description "Copy the command to a ps1 file and open in the Powershell ISE" -ScriptBlock {
    $line = $null
    $cursor = $null
    [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
    $tmp = Join-Path -Path $env:TEMP -ChildPath untitled.ps1
    Set-Content -Path $tmp -value $line
    #or substitute the editor of your choice
    ise $tmp
}

For this sample, I am opening the PowerShell ISE. You can use anything you want. Now, I can have something like this in my console.

A sample PowerShell expression (Image Credit: Jeff Hicks)
A Sample PowerShell Expression (Image Credit: Jeff Hicks)

 
I can press Ctrl+Alt+E and then the command is copied to a file in my TEMP folder and opened in the PowerShell ISE.
The auto generated script file (Image Credit: Jeff Hicks)
The Auto-Generated Script File (Image Credit: Jeff Hicks)

Open OnlineHelp

I will leave you today with one of the more complicated key handlers. This will get online help for the command entered at your prompt.

Set-PSReadlineKeyHandler -Key Shift+F1 -BriefDescription "OnlineCommandHelp" -LongDescription "Open oneline help for the current command" -ScriptBlock {
    param($key, $arg)
    $ast = $null
    $tokens = $null
    $errors = $null
    $cursor = $null
    [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$ast, [ref]$tokens, [ref]$errors, [ref]$cursor)
        $commandAst = $ast.FindAll( {
        $node = $args[0]
        $node -is [System.Management.Automation.Language.CommandAst] -and
            $node.Extent.StartOffset -le $cursor -and
            $node.Extent.EndOffset -ge $cursor
        }, $true) | Select-Object -Last 1
    if ($commandAst -ne $null)
    {
        $commandName = $commandAst.GetCommandName()
        if ($commandName -ne $null)
        {
            $command = $ExecutionContext.InvokeCommand.GetCommand($commandName, 'All')
            if ($command -is [System.Management.Automation.AliasInfo])
            {
                $commandName = $command.ResolvedCommandName
            }
            if ($commandName -ne $null)
            {
                Get-Help $commandName -online
            }
        }
    }
}

At your PowerShell prompt, when you type a command and then press Shift+F1 (the key combo I’m using), PowerShell will get online help for the current cmdlet, which should open your browser to the documentation page.

PSReadline Key Handler results (Image Credit: Jeff Hicks)
PSReadline Key Handler Results (Image Credit: Jeff Hicks)

 
The command will not be executed, so you have time to read the help and modify the command before pressing Enter or Escape.

I am finding many ways to use these key handlers to make my PowerShell work more efficient and even a bit more fun. I will share some of my shortcuts in a future article.