How to copy colorized script from PowerShell ISE

UPDATED Feb-03-2009:

Lee Holmes has posted an updated version of the script which does a much better job of HTML copy-pasting. It can also produce line numbers and has a number of other improvements.

 

In the previous article we demonstrated how to use Console-Copy script to make a colorized copy of console screen and place it in the system clipboard. Now what about doing the same thing with these nice looking colorized scripts that you can see in PowerShell ISE? Direct copy with Ctrl-C will copy just text without colorization. But the cool thing about PowerShell ISE is its great extensibility, which means that when you need a feature – you just script it! Let’s follow this path and see what we can learn on the way.

Let’s start from end and figure out how we attach a script to PowerShell ISE user interface. In the example below we create a new menu item which will be displayed as Copy Script menu command under Custom menu group. Clicking on this menu will automatically execute the Copy-Script function. The third parameter sets the hot key as you probably have already guessed. If you don’t want any hot key then just set its value to $null.

$psise.CustomMenu.Submenus.Add("Copy Script", {Copy-Script}, "Shift+Ctrl+S")

Now to the script itself. First, you should check whether there is any script window opened at all.

function Copy-Script
{
    if (-not $psise.CurrentOpenedFile)
    {
        Write-Error ‘No script is available for copying.’
        return
    }

If there is a script window opened then let’s get the text from the editor and do the parsing.

    $text = $psise.CurrentOpenedFile.Editor.Text

    trap { break }

    # Do syntax parsing.
    $errors = $null
    $tokens = [system.management.automation.psparser]::Tokenize($Text, [ref] $errors)

Parser can throw, that’s why we need to set error trapping before we call it.

We can ignore $errors for this particular task as the only thing we care is the set of tokens to use for colorization. Here is a list of tokens that PowerShell code can have:

PS D:\> [Enum]::GetNames([System.Management.Automation.PSTokenType])
Unknown
Command
CommandParameter
CommandArgument
Number
String
Variable
Member
LoopLabel
Attribute
Type
Operator
GroupStart
GroupEnd
Keyword
Comment
StatementSeparator
NewLine
LineContinuation
Position

The parser will return a set of tokens which we can iterate through and generate colored RTF blocks and HTML spans using the same technique as described in Colorized capture of console screen in HTML and RTF.

Once we are done, we should grab System.Windows.Clipboard and store our data, which will come in three flavors: UnicodeText, HTML and RTF:

    $dataObject = New-Object Windows.DataObject
    $dataObject.SetText([string]$text, [Windows.TextDataFormat]"UnicodeText")
    $dataObject.SetText([string]$rtf, [Windows.TextDataFormat]"Rtf")
    $dataObject.SetText([string]$html, [Windows.TextDataFormat]"Html")
    [Windows.Clipboard]::SetDataObject($dataObject, $true)

Full script attached.

Enjoy!
Vladimir Averkin
Windows PowerShell Team

Copy-Script.zip