src/common/ColorString.ps1
# Copyright 2021, Adam Edwards # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. . (import-script PreferenceHelper) . (import-script ColorScheme) ScriptClass ColorString { static { const ALLOWED_COLOR_MODES 2bit, 4bit const ESCAPE_CHAR "$([char]0x1b)" const END_COLOR "$($ESCAPE_CHAR)[0m" $supportsColor = $host.ui.SupportsVirtualTerminal $standardColorings = @('Emphasis1', 'Emphasis2', 'Containment', 'EnabledState', 'Success', 'Error1', 'Error2', 'Error3', 'Contrast', 'Scheme') $standardMapping = @{ '2Bit' = @{} '4bit' = @{ Emphasis1 = 11 Emphasis2 = 14 Containment = 14 Disabled = 8 Enabled = 10 Success = 10 Error1 = 1 Error2 = 9 Error3 = 1 Contrast = @(14, 12, 13) } } $colorMaps = @{ '2bit' = @{} '4bit' = @{} } $color16NameMap = @{ Black = 0 DarkBlue = 4 DarkGreen = 2 DarkCyan = 6 DarkRed = 1 DarkMagenta = 5 DarkYellow = 3 Gray = 7 DarkGray = 8 Blue = 12 Green = 10 Cyan = 14 Red = 9 Magenta = 13 Yellow = 11 White = 15 } $color16Contrast = @{ 0 = 15 1 = 15 2 = 15 3 = 0 4 = 15 5 = 15 6 = 0 7 = 0 8 = 0 9 = 0 10 = 0 11 = 0 12 = 15 13 = 15 14 = 0 15 = 0 } function GetColorFromName([string] $colorName) { $this.color16NameMap[$colorName] } function GetColorContrast($color) { $this.color16Contrast[$color] } function UpdateColorScheme([PSCustomObject[]] $colorInfoObjects) { $newScheme = new-so ColorScheme @($colorInfoObjects) foreach ( $colorMode in $this.colorMaps.Keys ) { $colorMap = $newScheme |=> GetColorMap $colorMode if ( $colorMap ) { foreach ( $colorName in $colorMap.keys ) { $this.colorMaps[$colorMode][$colorName] = $colorMap[$colorName] } } } } function ToStandardColorString($output, [string] $coloring, $criterion, [object[]] $highlightedValues, $disabledValue) { if ( $this.standardColorings -notcontains $coloring ) { $output return } $targetCriterion = if ( $criterion ) { $criterion } else { $output } $colors = GetStandardColors $coloring $targetCriterion $highlightedValues $disabledValue if ( ( $colors[0] -ne $null ) -or ( $colors[1] -ne $null ) ) { ToColorString $output $colors[0] $colors[1] } else { $output } } function GetStandardColors([string] $coloring, $criterion, [object[]] $highlightedValues, $disabledValue) { if ( $this.standardColorings -notcontains $coloring ) { $null, $null return } $colorMode = GetColorMode $colorMapping = $this.standardMapping[$colorMode] $standardColor = switch ( $coloring ) { 'Scheme' { if ( $this.colorMaps[$colorMode] -ne $null ) { $this.colorMaps[$colorMode][$criterion] } } 'Emphasis1' { $colorMapping['Emphasis1'] } 'Emphasis2' { $colorMapping['Emphasis2'] } 'Containment' { $colorMapping['Containment'] } 'EnabledState' { if ( $criterion -eq $disabledValue ) { $colorMapping['Disabled'] } elseif ( $criterion -in $highlightedValues ) { $colorMapping['Enabled'] } } 'Success' { $colorMapping['Success'] } 'Error1' { $colorMapping['Error1'] } 'Error2' { $colorMapping['Error2'] } 'Error3' { $colorMapping['Error3'] } 'Contrast' { if ( $criterion -eq $disabledValue ) { $colorMapping['Disabled'] } elseif ( $highlightedValues ) { $valueIndex = $highlightedValues.IndexOf($criterion) if ( $valueIndex -ge 0 ) { $colorVector = $colorMapping['Contrast'] $colorVector[$valueIndex % $colorVector.Length] } } } } $foregroundColor = $null $backgroundColor = $null if ( $standardColor ) { if ( $coloring -eq 'Containment' -or $coloring -eq 'Error1' ) { $backgroundColor = $standardColor $foregroundColor = 0 } else { $foregroundColor = $standardColor } } $foregroundColor, $backgroundColor } function ToColorString([string] $text, $foreColor, $backColor) { $colorMode = GetColorMode if ( ! $colorMode -or $colorMode -eq '2bit' ) { $text return } $colorString = GetColorStringFromIndex $foreColor $backColor if ( $colorString ) { "$colorString$($text)$END_COLOR" } else { $text } } function GetColorStringFromIndex($foreColor, $backColor) { $hasColor = $false $hasBoth = $false $backValue = 0 if ( $backColor -ne $null ) { $backOffset = RemapColorIndex $backColor if ( $backOffset -ne $null ) { $hasColor = $true $backValue = 40 + $backOffset } } $foreValue = 0 if ( $foreColor -ne $null ) { $frontOffset = RemapColorIndex $foreColor if ( $frontOffset -ne $null ) { $hasBoth = $hasColor $hasColor = $true $foreValue = 30 + $frontOffset } } if ( $hasColor ) { $colorString = "$ESCAPE_CHAR[" if ( $foreColor -ne $null ) { $colorString += "$foreValue" } if ( $hasBoth ) { $colorString += ";" } if ( $backColor -ne $null ) { $colorString += "$backValue" } "$($colorString)m" } } function RemapColorIndex([int32] $index) { if ( $index -lt 8 ) { $index } elseif ( $index -lt 16 ) { $index - 8 + 60 } } function GetColorMode { if ( $this.supportsColor ) { $colorVar = get-variable AutoGraphColorModePreference -value -erroraction ignore if ( $colorVar -eq '4bit' ) { '4bit' } else { '2bit' } } else { '2bit' } } } } |