PowerShell
Edit|Remove
 
Copy Script in Colour to the Clipboard for HTML or RTF Paste

Script-To-Clip 1.1

Introduction

Script-To-Clip is designed for use in PowerShell ISE.  It copies the entire contents or your selection from the currently selected script pane to the system clipboard, colourised for RTF and HTML, black and white for Unicode Text.  The clipboard can be pasted into any application that supports pasting in UnicodeText, RTF or HTML format.  When pasting in HTML format the line numbers will also be visible.  It supports passing a file into it if need be.

I'm all for documentation of code (although I'm probably not following accepted methodology).  Many of us need to grab code snippets or entire scripts and paste them into documents. The code always looks so much better if you can apply colour so it looks like it did in your editor.  If this script enables and encourages people to document their code then great.  I didn't create this tool, I fixed it and enhanced it.  I'm new to PowerShell and I wanted a tool to do this, so as you do, I went looking on the internet.   The best I could find was an eight year old script written by Vladimir Averkin and updated by Lee Holmes.  They had done some impressive work but it was broken due to changes in the PowerShell $psise module. There were a number of bugs and I wanted to be able to colour copy just a selection when I wanted.

You can paste into Microsoft WordPad and Word, or any decent word processor.  You can paste into your favourite HTML editor, I used KompoZer for this.  Or straight into a webpage which accepts HTML posts, like this Script Centre when you upload a contribution!

You can see an example of the output below, I have used my own script pane colours, I hope they're acceptable!  I assigned the function to the key combo "Ctrl+Shift+C", as ordinary copy is "Ctrl+C".  You could enter Script-To-Clip from the command line, but a shortcut is really the only way to use it as you need to run it when you're in another script. Here's an example, add a "Scripting Tools" submenu to the Add-Ons menu and add a menu item "Script to Clipboard" with a short-cut key combo of
"Ctrl+Shift+C".


$MyMenu = $psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Scripting Tools",$null,$null)
$MyMenu.Submenus.Add("Script to Clipboard",{Script-To-Clip},"Ctrl+Shift+C")
 
I post this updated version here so those of you that go looking like I did won't need to reproduce it!  Please enjoy using this tool and please speak up if you can see any ways to enhance it or further optimise it (like I said, I'm a beginner with PowerShell).  I don't consider the use of aliases or short variable names optimising ;-), and as I'm a beginner I want it to be as readable as possible!  I am aware that there's much I don't know about PowerShell and there're probably far better ways to do some of the things done here.  Like perhaps the use of system.text.stringbuilder objects to build the strings is outdated?....

Everything else is in the documentation below.

Function Script-To-Clip

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
   
#############################################################################################
$HStringFunctionScriptToClip = @' 
 
Script-To-Clip is designed for use in PowerShell ISE. It copies the entire contents
or your selection from the currently selected script pane to the system clipboard
colourised for RTF and HTML, black and white for Unicode Text.  The clipboard can be
pasted into any application that supports pasting in UnicodeText, RTF or HTML format.
When pasting in HTML format the line numbers will also be visible.  It supports
passing a file into it if need be.

By default it clipboards the entire script you have active in your scripting pane,
if you have selected some of the on-screen text it clipboards that.  There is a switch
allowing you to use the default script pane colours as output, not your own selected
colours.  I have assigned the command to it's own key combo, "Ctrl+Shift+C".

Usage: Recommendation, assign a keyboard combo to your favourite command

        Clipboard the script you have active in your script pane
        or your text selection
        Script-To-Clip

        Same as above, but use the default PowerShell ISE colours
        Script-To-Clip -DefaultColour y

'@

$HStringHistoryFunctionScriptToClip = @'
History:

The original version was written by Vladimir Averkin in early 2009.  It was
quickly superceded by an updated version written by Lee Holmes in February 2009.
See Lee's version here:
http://www.leeholmes.com/blog/2009/02/03/more-powershell-syntax-highlighting/
I am unaware of a newer version, this script did not work at first due to the
age of the code.

Garth Moodie
2017-08-18
Improvements:
Removed the parameter -SelectedText as you can now select a small selection of your
script and Script-ToClip it or Scipt-To-Clip the whole script.

Bug Fixes
Bug:   Non-literal strings do not display variables and group variables containing
       commands.
Fix:   Identified which tokens are non-literal strings and contain a variable/s.
       Added a new function HTML-StringVar-Token to parse the strings and extract the
       variables from the string.  The strings and the variables are appended to the
       HTML string builder, and the group variables are sent through the PowerShell
       tokeniser and appended to the HTML string builder.

2017-08-15
Improvements:
Added the parameter -SelectedText so you can paste a small selection of your script
elsewhere.

Added the parameter -DefaultColour so you don't need to use the colours on your
script pane, you can use PowerShell ISE default script pane colours.

Made the left of the page where the numbering is look as it does in PowerShell ISE.
Right-aligned the numbers, removed leading "0"s, set the font colour and set the
background colour the same as the script background.

Encapsulated the code into a function so this can be run instead of the script.

Moved the internal functions to the top, updated variables, joined the script code to
the Main function which then became this function.  Removed redundant test code,
moved the RTF initialisation into it's own function.  Added documentation as I read
through it, initially to help me understand.  In the end there is less code and lots
of documentation.

Bug Fixes:
Error: Does not work, error message; 'No script is available for copying.'
Fix:   Replaced "$psise.CurrentOpenedFile" with "$psise.CurrentFile"

Bug:   HTML puts a multi-line block comment all on one line <# e.g. your multi lines #>
Fix:   Told the HTML token processor to do the same for Comments as it does for Strings

Bug:   Here-Strings may have large sections on one line.
Fix:   Both RTF and HTML processors changed line break splitting from "`r`n" to "`n"
       
Bug:   HTML, line formatting is not WYSIWYG for comments and strings.
Fix:   Rewrote the section of the HTML token processing for comments and strings.
       Involved replacing all spaces with HTML and removing all the trimming code.

Bug:   RTF, line formatting is not WYSIWYG.
Fix:   Assigned the Lucida Console font (used by PowerShell ISE) in the RTF Header.

Bug:   RTF, pasted content has no colour when using -DefaultColour switch.
Fix:   Rewrote the RTF RGB colour string conversion.

Bug:   HTML, there is always one more number in the column than there are rows.
Fix:   Removed the number column processing from the HTML Token processor and created
       the number column just before the html clipboard content page is created.
'@

#############################################################################################
Function Script-To-Clip { 
[CmdletBinding()] 
param($Path, [string]$DefaultColour) 

#############################################################################################
# Function Initialise-RTF
#
# The header part of the RTF string builder contains the information about the document.
# The function creates the header, assigning the screen font to the text and creates
# the list of RGB colours in use. The text is appended to the RTF string builder.
#
# Creates: $RTFTokenTypeColourNos   The RGB colour values needed to colour the individual tokens
# Returns: $RTFBuilder              The initialised RTF string builder
#############################################################################################
Function RTF-Initialise ($RTFBuilder) {
    # Append RTF Header 
    $RTFHeader = "{\rtf1\fbidis\ansi\ansicpg1252\deff0\deflang1033{\fonttbl" + 
        "{\f0\fnil\fcharset0 Lucida Console;}}" 
    $RTFBuilder.Append($RTFHeader) | Out-Null
    $RTFBuilder.Append("`r`n") | Out-Null

    # Append RTF colour table which will contain all Powershell console colors. 
    $RTFBuilder.Append("{\colortbl ;") | Out-Null

    # Generate RTF colour number for each token type. 
    $RTFColourIndex = 1 
    $RTFColourNos = @{} 
    [Enum]::GetNames([System.Management.Automation.PSTokenType]) | Sort | ForEach-Object {
        # Extract the colours from the hex string to get RTF colour
        $TokenColour = $TokenColours[$_].ToString()
        $Red         = [Convert]::ToInt32($TokenColour.substring(3, 2), 16)
        $Green       = [Convert]::ToInt32($TokenColour.substring(5, 2), 16)
        $Blue        = [Convert]::ToInt32($TokenColour.substring(7, 2), 16)
        $RTFColour   = "\red$Red\green$Green\blue$Blue;" 
        If ($RTFColourNos.Keys -notcontains $RTFColour) {
            # This is a new colour, add to the list
            $RTFColourNos.$RTFColour = $RTFColourIndex
            $RTFBuilder.Append($RTFColour) | Out-Null
            $RTFTokenTypeColourNos.$_ = $RTFColourIndex 
            $RTFColourIndex ++ 
        } 
        Else { 
            $RTFTokenTypeColourNos.$_ = $RTFColourNos.$RTFColour 
        } 
    } 
    $RTFBuilder.Append('}') | Out-Null
    $RTFBuilder.Append("`r`n") | Out-Null

    # Append RTF document settings. 
    $RTFBuilder.Append('\viewkind4\uc1\pard\f0\fs20 ') | Out-Null
    Return $RTFBuilder
}    


#############################################################################################
# Function RTF-Append-Token
#
# Generates an RTF string from the token content and colour, and appends it to the RTF
# string builder
#
# Requires: $Content and $ColourNumber - the Token content and colour reference
# Returns:  $RTFStringBuilder          - The updated RTF string builder
#############################################################################################
Function RTF-Append-Token ($RTFStringBuilder, $Content, $ColourNumber) 
{ 
    $Content = $Content.Replace('\','\\').Replace("`n","\cf1\par`r`n") 
    $Content = $Content.Replace("`t",'\tab').Replace('{','\{').Replace('}','\}')
    $RTFStringBuilder.Append("\cf$ColourNumber $Content")
} 


#############################################################################################
$HStringFunctionHTMLStringVarToken = @'
 
HTML-StringVar-Token accepts only Tokens which are non-literal strings that contain
at least one variable.  There are two types of variable, the "$" followed by
alpha-numeric characters and the group variable which contains commands.
For the examples $MyTextVar = "My Text"

e.g. String:    "My var returns $MyTextVar"
     Result:    My var returns My Text

or the group variable,
e.g. String:    "My command writes to the host $(Write-Host "My text is $MyTextVar")"
     Result:    My command writes to the host My Text

The string parts are appended as is, the variables need to be identified and appended
with the correct colour and the group variables need to be re-tokenised and appended.

Requires: $StrVarLineNum - The line you are on in the script, may be incramented
          $StrVarContent - The content of the token containing the string that
                           has a variable/s

'@

#############################################################################################
Function HTML-StringVar-Token ($StrVarLineNum, $StrVarContent) {

    If (($StrVarContent.Contains('$(')) -or ($StrVarContent.Contains('$'))) {
        $StrVarLength = $StrVarContent.Length
        If ($StrVarContent.Contains('$(')) {
              $VarLocation = $StrVarContent.IndexOf('$(')}
        Else {$VarLocation = $StrVarContent.IndexOf('$')}
        # Append any chars before the variable to the HTML string builder
        If ($VarLocation -ne 0) {
            $StrContent = $StrVarContent.SubString(0,$VarLocation)
            $StrVarLineNum = HTML-Append-Token $StrVarLineNum $StrContent 'String'
        }
        # Process the entire group variable
        If ($StrVarContent.Contains('$(')) {
            $StrVariable = '$('
            $OpenParenth = 1
            $RemainStart = $VarLocation + 1
            Do { # Get the entire group variable string
                $RemainStart++
                $StrChar = $StrVarContent.SubString($RemainStart,1)
                $StrVariable += $StrChar
                If ($StrChar -eq '(') {$OpenParenth++}
                If ($StrChar -eq ')') {$OpenParenth--}
            } Until (($OpenParenth -eq 0) -or ($RemainStart -eq $StrVarLength - 2))
            $RemainStart++
            # Tokenise the group variable
            $errors = $null
            $VarTokens = [system.management.automation.psparser]::Tokenize($StrVariable,[ref]$errors)
            $VarPosition = 0
            # Append the group variable tokens to the HTML string builder
            ForEach ($VarToken in $VarTokens) { 
                If ($VarPosition -lt $VarToken.Start) {
                    $TokenLength = $VarToken.Start-$VarPosition
                    $TokenContent = $StrVariable.Substring($VarPosition,$TokenLength) 
                    $TokenType    = 'Unknown' 
                    $CurrentLine  = HTML-Append-Token $CurrentLine $TokenContent $TokenType
                } 
                $TokenContent = $StrVariable.Substring($VarToken.Start, $VarToken.Length) 
                $TokenType    = $VarToken.Type.ToString() 
                $CurrentLine  = HTML-Append-Token $CurrentLine $TokenContent $TokenType
                $VarPosition = $VarToken.Start + $VarToken.Length 
            }
       }
        # Process the full variable name
        ElseIf ($StrVarContent.Contains('$')) {
            $StrVariable = '$'
            $CharMatch   = $true
            $RemainStart = $VarLocation
            Do {
                $RemainStart++
                $StrChar = $StrVarContent.SubString($RemainStart,1)
                If (($StrChar -match "^[a-zA-Z0-9\s]+$") -and ($StrChar -ne ' ')) {
                    $StrVariable += $StrChar
                }
                Else {$CharMatch = $false}
            } Until ((-not $CharMatch) -or ($RemainStart -eq $StrVarLength - 1))
            # Append the variable to the HTML string builder
            $StrVarLineNum = HTML-Append-Token $StrVarLineNum $StrVariable 'Variable'
        }

        # This is the end of the string
        If ($RemainStart -eq $StrVarLength-1) {
            $EndString = $StrVarContent.SubString($StrVarLength-1,1)
            $StrVarLineNum = HTML-Append-Token $StrVarLineNum $EndString 'String'
        }
        # Process the remainder of the string
        Else {
            $StrRemaining = $StrVarContent.SubString($RemainStart,$StrVarLength-$RemainStart)
            # There's another variable, do it again
            If ($StrRemaining.Contains('$')) {
                $StrVarLineNum = HTML-StringVar-Token $StrVarLineNum $StrRemaining
            }
            # There are only string characters left, append to the HTML string builder
            Else{
                $StrVarLineNum = HTML-Append-Token $StrVarLineNum $StrRemaining 'String'
            }
        }
    }
    Return $StrVarLineNum
    Else {Write-Host "There is no variable in the string!!"}
}


#############################################################################################
# Function HTML-Append-Token
#
# Generates an HTML string from the token content and colour, and appends it to the HTML
# string builder. Incraments the line counter when a new line is encountered.
#
# Modifies:   $HTMLBuilder       - A parent function variable.  Appending
#                                  to the string being built.
# References: $TokenColours      - To get the HTML colour needed.
# Requires:   $Content and $Type - The content and type of the token
# Returns:    $LineNumber        - The current Line Number, updated if need be.
#############################################################################################
Function HTML-Append-Token ($LineNumber, $Content, $Type) 
{ 
    $FirstChar  = ""
    $FirstChars = ""
    If ($Content.Length -ge 2) { 
        $FirstChar  = $Content.SubString(0,1)
        $FirstChars = $Content.SubString(0,2)
    }
    If (($Type -eq 'NewLine') -or ($Type -eq 'LineContinuation')) { 
        # Need to append a new line
        If($Type -eq 'LineContinuation') { 
            $HTMLBuilder.Append('`') | Out-Null
        }
        $HTMLBuilder.Append("<br />`r`n") | Out-Null
        $LineNumber++ 
    } 
    ElseIf (($Type -eq 'String') -and ($FirstChar -ne "'") -and ($FirstChars -ne "@'")`
                                 -and ($Content.Contains("$"))) {
        $LineNumber = HTML-StringVar-Token $LineNumber $Content
    }
    Else {
        $Content = [System.Web.HttpUtility]::HtmlEncode($Content) 
        # Replace the spaces with HTML
        $Content = $Content.Replace(' ', '&nbsp;') 
        $HTMLColour = $TokenColours[$Type].ToString().Replace('#FF', '#') 
        If (($Type -eq 'String') -or ($Type -eq 'Comment')) {
            $Lines = $Content -split "`n" 
            $Content = "" 
            $MultipleLines = $false 
            ForEach($Line in $Lines) { 
                If($MultipleLines) { 
                    $Content += "<BR />`r`n" 
                    $LineNumber++ 
                } 
                $Content += $Line
                $MultipleLines = $true 
            }
        } 
        $HTMLBuilder.Append("<span style='color:$HTMLColour'>$Content</span>") | Out-Null
    } 
    Return $LineNumber
} 


#############################################################################################
# Function HTML-For-Clipboard
#
# Insert the finished HTML script and Line Number Column strings into an HTML page
# formatted for the Windows Clipboard.
#
# The 3 lines with a "background" colour value are in order; the table, the number column
# and the cell colour. I have them all set to a light grey so they match my script pane.
# The number column also has a value "color" for the colour of the numbers.
#
# Requires: $HTMLContent  - The converted script
#           $LineNoColumn - The line numbers at the left of the page
# Returns:  $HTMLPage     - The completed HTML fomatted for the Windows Clipboard
#############################################################################################
Function HTML-For-Clipboard($HTMLContent, $LineNoColumn) {
 
$HTMLPage = @" 
Version:1.0 
StartHTML:0000000000 
EndHTML:0000000000 
StartFragment:0000000000 
EndFragment:0000000000 
StartSelection:0000000000 
EndSelection:0000000000 
SourceURL:file:///about:blank 
<!DOCTYPE HTML PUBLIC `"-//W3C//DTD HTML 4.0 Transitional//EN`"> 
<HTML> 
<HEAD> 
<TITLE>HTML Clipboard</TITLE> 
</HEAD> 
<BODY> 
<!--StartFragment--> 
<DIV style='font-family:Consolas,Lucida Console; font-size:10pt; 
    width:750; border:1px solid black; overflow:auto; padding:5px; background:#fafafa'> 
<TABLE BORDER='0' cellpadding='5' cellspacing='0'> 
<TBODY> 
<TR> 
    <TD VALIGN='Top'> 
<DIV style='font-family:Consolas,Lucida Console; font-size:10pt; 
    padding:5px; text-align: right; color:#4886AD; background:#fafafa'> 
__LINES__ 
</DIV> 
    </TD> 
    <TD VALIGN='Top' NOWRAP='NOWRAP'> 
<DIV style='font-family:Consolas,Lucida Console; font-size:10pt; 
    padding:5px; background:#fafafa'> 
__HTML__ 
</DIV> 
    </TD> 
</TR> 
</TBODY> 
</TABLE> 
</DIV> 
<!--EndFragment--> 
</BODY> 
</HTML> 
"@
 
    # Insert the column of line numbers
    $HTMLPage = $HTMLPage.Replace("__LINES__", $LineNoColumn) 
    $StartFragment = $HTMLPage.IndexOf("<!--StartFragment-->") + 
        "<!--StartFragment-->".Length + 2 
    $EndFragment = $HTMLPage.IndexOf("<!--EndFragment-->") + 
        $HTMLContent.Length - "__HTML__".Length 
    $StartHtml = $HTMLPage.IndexOf("<!DOCTYPE") 
    $EndHtml = $HTMLPage.Length + $HTMLContent.Length - "__HTML__".Length 
    $HTMLPage = $HTMLPage -replace "StartHTML:0000000000", 
        ("StartHTML:{0:0000000000}" -f $StartHtml) 
    $HTMLPage = $HTMLPage -replace "EndHTML:0000000000", 
        ("EndHTML:{0:0000000000}" -f $EndHtml) 
    $HTMLPage = $HTMLPage -replace "StartFragment:0000000000", 
        ("StartFragment:{0:0000000000}" -f $StartFragment) 
    $HTMLPage = $HTMLPage -replace "EndFragment:0000000000", 
        ("EndFragment:{0:0000000000}" -f $EndFragment) 
    $HTMLPage = $HTMLPage -replace "StartSelection:0000000000", 
        ("StartSelection:{0:0000000000}" -f $StartFragment) 
    $HTMLPage = $HTMLPage -replace "EndSelection:0000000000", 
        ("EndSelection:{0:0000000000}" -f $EndFragment) 
    # Insert the content in HTML format
    $HTMLPage = $HTMLPage.Replace("__HTML__", $HTMLContent) 
    
    Return $HTMLPage 
} 


#############################################################################################
# Main Function Beginning

# Get the input from a file or the current script open in the PowerShell ISE
If ($Path) {
    # The user supplied a full filename (path included)
    If (Test-Path $Path) {$Text = (Get-Content $Path) -join "`r`n"}
    Else {
        Write-Error "The file ""$Path"" is not available for copying."
    } 
}
ElseIf (-not $psise.CurrentFile) {
    Write-Error 'No current script are you running PowerShell ISE?' 
}
# See if the user wants a selection of text from the script pane
Else {
    $Text = $psise.CurrentFile.Editor.SelectedText
    If ($Text) {
        $psise.CurrentFile.Editor.InsertText($Text)
        $CurrentLine = $psISE.CurrentFile.Editor.CaretLine
        $FirstLine   = $CurrentLine
    }
    Else { # The user wants the whole script pane (default)
        $Text = $psise.CurrentFile.Editor.Text
        $CurrentLine = 1 
        $FirstLine   = $CurrentLine
    }
}

If ($Text) {
    # Ok, have data, can start
    # Set the colours to the standard Script Pane colours 
    # I have changed the Operator colour, it was too hard to read
    $TokenColours = @{ 
    #    Type                   Colour(Hex)
        'Attribute'          = '#FFADD8E6' 
        'Command'            = '#FF0000FF' 
        'CommandArgument'    = '#FF8A2BE2' 
        'CommandParameter'   = '#FF000080' 
        'Comment'            = '#FF006400' 
        'GroupEnd'           = '#FF000000' 
        'GroupStart'         = '#FF000000' 
        'Keyword'            = '#FF00008B' 
        'LineContinuation'   = '#FF000000' 
        'LoopLabel'          = '#FF00008B' 
        'Member'             = '#FF000000' 
        'NewLine'            = '#FF000000' 
        'Number'             = '#FF800080' 
#        'Operator'           = '#FFA9A9A9' 
        'Operator'           = '#FF3CB371' 
        'Position'           = '#FF000000' 
        'StatementSeparator' = '#FF000000' 
        'String'             = '#FF8B0000' 
        'Type'               = '#FF008080' 
        'Unknown'            = '#FF000000' 
        'Variable'           = '#FFFF4500' 
    }
    # Default is overwrite the defaults with your personal PowerShell ISE colours
    If (-not(($DefaultColour -eq "y") -or ($DefaultColour -eq "Yes"))) { 
        $TokenColours = $psise.Options.TokenColors 
    } 
    # Break the text up into a sequestial array of tokens, one token
    # for each of the Types above that it finds as it reads
    $errors = $null 
    $Tokens = [system.management.automation.psparser]::Tokenize($Text,[ref]$errors) 

    # Initialise the HTML string builder. 
    Add-Type -Assembly System.Web 
    $HTMLBuilder      = new-object system.text.stringbuilder 
   
    # Initialise the RTF builder. 
    $RTFBuilder            = new-object system.text.stringbuilder 
    $RTFTokenTypeColourNos = @{} 
    $RTFBuilder            = RTF-Initialise $RTFBuilder

    # Iterate through the tokens appending the content and colour of the token
    # to the RTF string builder and the HTML string builder.
    $Position = 0 
    ForEach ($Token in $Tokens) { 
        If ($Position -lt $Token.Start) { 
            $TokenContent = $text.Substring($Position, ($Token.Start - $Position)) 
            $TokenType    = 'Unknown' 
            $TokenColNo   = $RTFTokenTypeColourNos.$TokenType
            $RTFBuilder   = RTF-Append-Token $RTFBuilder $TokenContent $TokenColNo
            $CurrentLine  = HTML-Append-Token $CurrentLine $TokenContent $TokenType
        } 
        $TokenContent = $text.Substring($Token.Start, $Token.Length) 
        $TokenType    = $Token.Type.ToString() 
        $TokenColNo   = $RTFTokenTypeColourNos.$TokenType
        $RTFBuilder   = RTF-Append-Token $RTFBuilder $TokenContent $TokenColNo
        $CurrentLine  = HTML-Append-Token $CurrentLine $TokenContent $TokenType
        $Position = $Token.Start + $Token.Length 
    }

    # Append RTF ending brace. 
    $RTFBuilder.Append('}') | Out-Null

    # Build the column of line numbers for the HTML
    $LineNoColBuilder = new-object system.text.stringbuilder 
    For ($LineNoCounter = $FirstLine; $LineNoCounter -lt $CurrentLine; $LineNoCounter++) {
        $LineNoColBuilder.Append("{0:0}<BR />" -f $LineNoCounter) | Out-Null
    }
    
    # Copy console screen buffer contents to clipboard in three formats - 
    # text, HTML and RTF. 
    $ClipboardContent = New-Object Windows.DataObject 
    $ClipboardContent.SetText([string]$Text, [Windows.TextDataFormat]"UnicodeText") 

    $RTF = $RTFBuilder.ToString() 
    $ClipboardContent.SetText([string]$RTF, [Windows.TextDataFormat]"Rtf") 

    $HTMLBuilt = $HTMLBuilder.ToString(); $LineNoColBuilt = $LineNoColBuilder.ToString()
    # Put all the collected HTML info into an HTML page
    $HTML = HTML-For-Clipboard $HTMLBuilt $LineNoColBuilt
    $ClipboardContent.SetText([string]$HTML, [Windows.TextDataFormat]"Html") 

    [Windows.Clipboard]::SetDataObject($ClipboardContent, $true) 
}
} 


# Assign this function to keyboard combo Ctrl+Shift+C for colour selection copying
Function Selection-To-Clip {Script-To-Clip -SelectedText y}


# Uncomment a line to test it, comment again before using outside the script
# otherwise the uncommented function will run whenever the script is added to
# the environment
# Script-To-Clip
# Script-To-Clip -DefaultColour y
# Script-To-Clip -SelectedText y
# Script-To-Clip -DefaultColour y -SelectedText y
# Selection-To-Clip