Skip to content

Instantly share code, notes, and snippets.

@josheinstein
Last active August 29, 2015 14:14
Show Gist options
  • Select an option

  • Save josheinstein/cf99bcfdeb573cbbf6a7 to your computer and use it in GitHub Desktop.

Select an option

Save josheinstein/cf99bcfdeb573cbbf6a7 to your computer and use it in GitHub Desktop.
Write-Highlight
#.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