Support setting foreground/background colors to terminal defaults (#8073)

* Support setting foreground/background colors to terminal defaults

Adds fgDefault to ForegroundColor and bgDefault to BackgroundColor
enums.

For Windows console, the default foreground color is assumed to be
white, and the default background color black.

* Add default fg/bg color caching for Windows Console
This commit is contained in:
Kaushal Modi
2018-06-24 03:53:20 -04:00
committed by Varriount
parent fbac233dae
commit 4c2e712056

View File

@@ -542,7 +542,9 @@ type
fgBlue, ## blue
fgMagenta, ## magenta
fgCyan, ## cyan
fgWhite ## white
fgWhite, ## white
fg8Bit, ## 256-color (not supported, see ``enableTrueColors`` instead.)
fgDefault ## default terminal foreground color
BackgroundColor* = enum ## terminal's background colors
bgBlack = 40, ## black
@@ -552,28 +554,40 @@ type
bgBlue, ## blue
bgMagenta, ## magenta
bgCyan, ## cyan
bgWhite ## white
bgWhite, ## white
bg8Bit, ## 256-color (not supported, see ``enableTrueColors`` instead.)
bgDefault ## default terminal background color
{.deprecated: [TForegroundColor: ForegroundColor,
TBackgroundColor: BackgroundColor].}
when defined(windows):
var defaultForegroundColor, defaultBackgroundColor: int16 = 0xFFFF'i16 # Default to an invalid value 0xFFFF
proc setForegroundColor*(f: File, fg: ForegroundColor, bright=false) =
## Sets the terminal's foreground color.
when defined(windows):
let h = conHandle(f)
var old = getAttributes(h) and not FOREGROUND_RGB
if defaultForegroundColor == 0xFFFF'i16:
defaultForegroundColor = old
old = if bright: old or FOREGROUND_INTENSITY
else: old and not(FOREGROUND_INTENSITY)
const lookup: array[ForegroundColor, int] = [
0,
0, # ForegroundColor enum with ordinal 30
(FOREGROUND_RED),
(FOREGROUND_GREEN),
(FOREGROUND_RED or FOREGROUND_GREEN),
(FOREGROUND_BLUE),
(FOREGROUND_RED or FOREGROUND_BLUE),
(FOREGROUND_BLUE or FOREGROUND_GREEN),
(FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED)]
discard setConsoleTextAttribute(h, toU16(old or lookup[fg]))
(FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED),
0, # fg8Bit not supported, see ``enableTrueColors`` instead.
0] # unused
if fg == fgDefault:
discard setConsoleTextAttribute(h, toU16(old or defaultForegroundColor))
else:
discard setConsoleTextAttribute(h, toU16(old or lookup[fg]))
else:
gFG = ord(fg)
if bright: inc(gFG, 60)
@@ -584,18 +598,25 @@ proc setBackgroundColor*(f: File, bg: BackgroundColor, bright=false) =
when defined(windows):
let h = conHandle(f)
var old = getAttributes(h) and not BACKGROUND_RGB
if defaultBackgroundColor == 0xFFFF'i16:
defaultBackgroundColor = old
old = if bright: old or BACKGROUND_INTENSITY
else: old and not(BACKGROUND_INTENSITY)
const lookup: array[BackgroundColor, int] = [
0,
0, # BackgroundColor enum with ordinal 40
(BACKGROUND_RED),
(BACKGROUND_GREEN),
(BACKGROUND_RED or BACKGROUND_GREEN),
(BACKGROUND_BLUE),
(BACKGROUND_RED or BACKGROUND_BLUE),
(BACKGROUND_BLUE or BACKGROUND_GREEN),
(BACKGROUND_BLUE or BACKGROUND_GREEN or BACKGROUND_RED)]
discard setConsoleTextAttribute(h, toU16(old or lookup[bg]))
(BACKGROUND_BLUE or BACKGROUND_GREEN or BACKGROUND_RED),
0, # bg8Bit not supported, see ``enableTrueColors`` instead.
0] # unused
if bg == bgDefault:
discard setConsoleTextAttribute(h, toU16(old or defaultBackgroundColor))
else:
discard setConsoleTextAttribute(h, toU16(old or lookup[bg]))
else:
gBG = ord(bg)
if bright: inc(gBG, 60)
@@ -935,3 +956,6 @@ when not defined(testing) and isMainModule:
stdout.styledWrite(fgGreen, "green text")
echo ""
echo "ordinary text"
stdout.styledWriteLine(fgRed, "red text ", styleBright, "bold red", fgDefault, " bold text")
stdout.styledWriteLine(bgYellow, "text in yellow bg", styleBright, " bold text in yellow bg", bgDefault, " bold text")
echo "ordinary text"