Last active
August 29, 2015 14:14
-
-
Save josheinstein/cf99bcfdeb573cbbf6a7 to your computer and use it in GitHub Desktop.
Write-Highlight
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #.SYNOPSIS | |
| # Writes text to the host, highlighting portions of the text that | |
| # match one or more regular expression patterns in a different | |
| # color. | |
| # | |
| #.DESCRIPTION | |
| # There are two forms that this command can take: One which specifies | |
| # a single regular expression pattern and a single color (which defaults | |
| # to yellow if not specified), and another that takes a hashtable that | |
| # consists of regular expressions for keys and colors for values. | |
| # See the examples for usage. | |
| # | |
| #.EXAMPLE | |
| # # Phone number will be written in green text | |
| # # Email address will be written in yellow text | |
| # Write-Highlight "Phone: 555-555-9999, Email: [email protected]" -Colors @{ | |
| # '\d{3}-\d{3}-\d{4}' = 'Green' | |
| # '[a-z0-9]+@[a-z0-9]+\.com' = 'Yellow' | |
| # } | |
| # | |
| #.EXAMPLE | |
| # # Numbers will be written in yellow text | |
| # Write-Highlight "Phone: 555-555-9999, Email: [email protected]" -Pattern '\d+' | |
| function Write-Highlight { | |
| [CmdletBinding(DefaultParameterSetName='SinglePattern')] | |
| param( | |
| # The text to write to the host | |
| [Parameter(Position=1, ValueFromPipeline=$true)] | |
| [String]$Text, | |
| # A regular expression that will be matched in the Text | |
| # parameter and highlighted in yellow. | |
| [Parameter(ParameterSetName='SinglePattern', Mandatory=$true)] | |
| [Regex]$Pattern, | |
| # The color to write the matched portion of the text. | |
| # Defaults to Yellow. | |
| [Parameter(ParameterSetName='SinglePattern')] | |
| [ConsoleColor]$MatchColor = 'Yellow', | |
| # A hashtable consisting of keys that are the regular expression | |
| # pattern to match and values that are the color to use. | |
| # Colors must be convertible to ConsoleColor enumeration values. | |
| [Parameter(ParameterSetName='MultiplePatterns', Mandatory=$true)] | |
| [Hashtable]$Colors, | |
| # The default color to write the non-highlighted text. | |
| # Defaults to the current foreground color. | |
| [Parameter()] | |
| [ConsoleColor]$DefaultColor = $Host.UI.RawUI.ForegroundColor, | |
| # Specifies that the content displayed in the console does not | |
| # end with a newline character. | |
| [Parameter()] | |
| [Switch]$NoNewLine | |
| ) | |
| process { | |
| if ([String]::IsNullOrEmpty($Text)) { return; } | |
| # Normalize the parameter sets. | |
| # If a single pattern parameter set was used, pack it | |
| # into the same variable we use for the multi parameter set. | |
| if ($PSCmdlet.ParameterSetName -eq 'SinglePattern') { | |
| $Colors = @{} | |
| $Colors.Add($Pattern.ToString(), [ConsoleColor]::Yellow) | |
| } | |
| # Run each regular expression on the text, sorting the | |
| # regex matches by their Index property. This will be | |
| # important when we start breaking up the text into chunks | |
| # of non-colored and colored text. | |
| $AllMatches = @($Colors.GetEnumerator() | %{ | |
| $Pattern = [Regex]$_.Key | |
| $Color = [ConsoleColor]$_.Value | |
| # Append a new property to the Match objects that holds | |
| # the corresponding color. This makes it easier than | |
| # having to go look up the right color later. | |
| $Pattern.Matches($Text) | | |
| Add-Member -PassThru NoteProperty Color $Color | |
| } | Sort Index) | |
| # Loop through segments of the string, starting at position 0. | |
| $i = 0 | |
| while ($i -lt $Text.Length) { | |
| # Find the closest match that comes after the current | |
| # string position. | |
| $NextMatch = $AllMatches | ?{ $_.Index -ge $i } | Select -First 1 | |
| if ($NextMatch) { | |
| # We still have matches. | |
| # Write the portion of the string that comes before the match. | |
| # (This could potentially be an empty string if our position | |
| # is currently at the beginning of a match.) | |
| Write-Host $Text.Substring($i, $NextMatch.Index-$i) -ForegroundColor $DefaultColor -NoNewline | |
| # Write the portion of the string that matched in its | |
| # designated color. (Note, newline is suppressed.) | |
| Write-Host $NextMatch.Value -ForegroundColor $NextMatch.Color -NoNewline | |
| # Advance the string position | |
| $i = $NextMatch.Index + $NextMatch.Length | |
| } | |
| else { | |
| # No more matches. Write the remainder of the string. | |
| # This could potentially be an empty string. | |
| Write-Host $Text.Substring($i) -ForegroundColor $DefaultColor -NoNewline | |
| break | |
| } | |
| } | |
| # Since we've been suppressing newlines all this time, we | |
| # need to write out one final newline (unless NoNewLine is true) | |
| if (!$NoNewLine) { Write-Host } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment