Functions/Public/Convert-ColourString.ps1
|
<#
.SYNOPSIS Convert string to coloured format .DESCRIPTION Takes a string using custom colour blocks (seee https://github.com/stuartio/writecolour) to ANSI escape sequences which can be used with regular printing functions such as Write-Host .PARAMETER InputObject Input string to convert .EXAMPLE Convert-ColourString "Hello, my name is |red|Inigo Montoya|!|" #> function Convert-ColourString { [Alias('Convert-ColorString')] [CmdletBinding()] Param( [Parameter(Mandatory)] [string] $InputObject ) Process { $e = [char]0x1b $Reset = "$e[0m" $Separator = " " $4BitPattern = '^([0-9]{2})( [0-9]{2})?( [a-z]+)?$' # Begin by removing end values $ParsedInput = $InputObject # Replace reset character set if ($env:DISABLE_WC_COLOURS -eq '1' -or $env:DISABLE_WC_COLORS -eq '1') { $ParsedInput = $ParsedInput.Replace('|!|', '') } else { $ParsedInput = $ParsedInput.Replace('|!|', $Reset) } # Parse Input and extract colours $ColourPattern = '\|([^\|]+)\|' # Find colour matches $ColourMatches = $ParsedInput | Select-String -Pattern $ColourPattern -AllMatches if ($ColourMatches) { Write-Debug "Convert-ColourfulString: Found $($ColourMatches.Matches.count) matches" if ($env:DISABLE_WC_COLOURS -eq '1' -or $env:DISABLE_WC_COLORS -eq '1') { $ColourMatches.Matches | ForEach-Object { Write-Debug "Parsing colour match $($_.Value)" $Value = $_.Value $ParsedInput = $ParsedInput.Replace($Value, '') Write-Debug "ParsedInput is now: $ParsedInput" } } else { $ColourMatches.Matches | ForEach-Object { Write-Debug "Parsing colour match $($_.Value)" $Value = $_.Value $ColourMatch = $_.Groups[1].Value $Foreground = $null $Background = $null $Flags = $null # Split on 4-bit or 8-bit colours if ($ColourMatch -match $4BitPattern) { Write-Debug 'Convert-ColourfulString: Detected 4-bit colour format' # Extract matched components $Foreground = $Matches[1] if ($Matches[2]) { $Background = $Matches[2].Trim() } if ($Matches[3]) { $Flags = $Matches[3].Trim() } Write-Debug "Found $($ColourComponents.count) components" $FormattedValue = "$e[" # Add flags first in 4-bit if ($Flags) { $FlagsArray = $Flags.ToCharArray() foreach ($Flag in $FlagsArray) { $FormattedValue += Convert-Flag -Flag $Flag } } # Add foreground $FormattedValue += ";$Foreground" # Add background if ($Background) { $FormattedValue += ";$Background" } # Add trailing m $FormattedValue += "m" # Fix invalid '[;' sequence $FormattedValue = $FormattedValue.Replace('[;', '[') Write-Debug "Convert-ColourfulString: Foreground = $Foreground" if ($Background) { Write-Debug "Convert-ColourfulString: Background = $Background" } if ($Flags) { Write-Debug "Convert-ColourfulString: Flags = $Flags" } Write-Debug "Convert-ColourfulString: FormattedValue = $($FormattedValue.Substring(1))" # Update input string with formatted value $ParsedInput = $ParsedInput.Replace($Value, $FormattedValue) } else { Write-Debug 'Convert-ColourfulString: Detected 8-bit colour format' # Split value into components $ColourComponents = $ColourMatch.Split($Separator) Write-Debug "Found $($ColourComponents.count) components" # If single element then check between either foreground colour or flags if ($ColourComponents.Count -eq 1) { $Foreground = Get-RGB -Colour $ColourComponents[0] if ($null -eq $Foreground) { Write-Debug "Using single element as flags" $Flags = $ColourComponents[0] } } # If 2 elements, then assume the first is the foreground, the 2nd can be either background or flags elseif ($ColourComponents.Count -eq 2) { $Foreground = Get-RGB -Colour $ColourComponents[0] $Background = Get-RGB -Colour $ColourComponents[1] if ($null -eq $Background) { Write-Debug "Using 2nd element as flags" $Flags = $ColourComponents[1] } } # If 3 elements, then 1st is foreground, 2nd is background, 3rd is flags elseif ($ColourComponents.Count -eq 3) { $Foreground = Get-RGB -Colour $ColourComponents[0] $Background = Get-RGB -Colour $ColourComponents[1] $Flags = $ColourComponents[2] } # Otherwise panic else { Write-Warning "Convert-ColourString: Prefix string is malformed" } # ---- Process foreground $FormattedValue = "$e[38;2;$($Foreground.red);$($Foreground.green);$($Foreground.blue)" # ---- Add background if ($Background) { $FormattedValue += ";48;2;$($Background.red);$($Background.green);$($Background.blue)" } # ---- Add flags, if any if ($Flags) { Write-Debug "Convert-ColourfulString: Flags = $Flags" $FlagsArray = $Flags.ToCharArray() foreach ($Flag in $FlagsArray) { $FormattedValue += Convert-Flag -Flag $Flag } } # Add closing char $FormattedValue += "m" # Update input string with formatted value $ParsedInput = $ParsedInput.Replace($Value, $FormattedValue) # Add trailing reset, just in case $ParsedInput += $Reset } } } return $ParsedInput } else { Write-Warning "Convert-ColourfulString: Found no colour matches" return $InputObject } } } |