Add styledWrite macro

Also:

- Move the tests block to the end of the file
- Fix the older tests
- Add tests for existing styledEcho
- Add new tests for styledWrite

Fixes https://github.com/nim-lang/Nim/issues/8046.
This commit is contained in:
Kaushal Modi 2018-06-15 11:26:09 -04:00
commit 3b5b3deecd

View file

@ -692,6 +692,40 @@ template styledEchoProcessArg(f: File, cmd: TerminalCmd) =
when cmd == bgColor: when cmd == bgColor:
fgSetColor = false fgSetColor = false
macro styledWrite*(f: File, m: varargs[typed]): untyped =
## Similar to ``write``, but treating terminal style arguments specially.
## When some argument is ``Style``, ``set[Style]``, ``ForegroundColor``,
## ``BackgroundColor`` or ``TerminalCmd`` then it is not sent directly to
## ``f``, but instead corresponding terminal style proc is called.
##
## Example:
##
## .. code-block:: nim
##
## stdout.styledWrite(fgRed, "red text ")
## stdout.styledWrite(fgGreen, "green text")
##
let m = callsite()
var reset = false
result = newNimNode(nnkStmtList)
for i in countup(2, m.len - 1):
let item = m[i]
case item.kind
of nnkStrLit..nnkTripleStrLit:
if i == m.len - 1:
# optimize if string literal is last, just call write
result.add(newCall(bindSym"write", f, item))
if reset: result.add(newCall(bindSym"resetAttributes", f))
return
else:
# if it is string literal just call write, do not enable reset
result.add(newCall(bindSym"write", f, item))
else:
result.add(newCall(bindSym"styledEchoProcessArg", f, item))
reset = true
if reset: result.add(newCall(bindSym"resetAttributes", f))
macro styledWriteLine*(f: File, m: varargs[typed]): untyped = macro styledWriteLine*(f: File, m: varargs[typed]): untyped =
## Similar to ``writeLine``, but treating terminal style arguments specially. ## Similar to ``writeLine``, but treating terminal style arguments specially.
## When some argument is ``Style``, ``set[Style]``, ``ForegroundColor``, ## When some argument is ``Style``, ``set[Style]``, ``ForegroundColor``,
@ -781,7 +815,7 @@ when defined(windows):
inc i, x inc i, x
password.string.setLen(max(password.len - x, 0)) password.string.setLen(max(password.len - x, 0))
of chr(0x0): of chr(0x0):
# modifier key - ignore - for details see # modifier key - ignore - for details see
# https://github.com/nim-lang/Nim/issues/7764 # https://github.com/nim-lang/Nim/issues/7764
continue continue
else: else:
@ -840,17 +874,6 @@ proc resetAttributes*() {.noconv.} =
## ``system.addQuitProc(resetAttributes)``. ## ``system.addQuitProc(resetAttributes)``.
resetAttributes(stdout) resetAttributes(stdout)
when not defined(testing) and isMainModule:
#system.addQuitProc(resetAttributes)
write(stdout, "never mind")
stdout.eraseLine()
stdout.styledWriteLine("styled text ", {styleBright, styleBlink, styleUnderscore})
stdout.styledWriteLine("italic text ", {styleItalic})
stdout.setBackGroundColor(bgCyan, true)
stdout.setForeGroundColor(fgBlue)
stdout.writeLine("ordinary text")
stdout.resetAttributes()
proc isTrueColorSupported*(): bool = proc isTrueColorSupported*(): bool =
## Returns true if a terminal supports true color. ## Returns true if a terminal supports true color.
return trueColorIsSupported return trueColorIsSupported
@ -901,3 +924,42 @@ proc disableTrueColors*() =
trueColorIsEnabled = false trueColorIsEnabled = false
else: else:
trueColorIsEnabled = false trueColorIsEnabled = false
when not defined(testing) and isMainModule:
#system.addQuitProc(resetAttributes)
write(stdout, "never mind")
stdout.eraseLine()
stdout.styledWriteLine({styleBright, styleBlink, styleUnderscore}, "styled text ")
stdout.styledWriteLine("italic text ", {styleItalic})
stdout.setBackGroundColor(bgCyan, true)
stdout.setForeGroundColor(fgBlue)
stdout.write("blue text in cyan background")
stdout.resetAttributes()
echo ""
stdout.writeLine("ordinary text")
echo "more ordinary text"
styledEcho styleBright, fgGreen, "[PASS]", resetStyle, fgGreen, " Yay!"
echo "ordinary text again"
styledEcho styleBright, fgRed, "[FAIL]", resetStyle, fgRed, " Nay :("
echo "ordinary text again"
setForeGroundColor(fgGreen)
echo "green text"
echo "more green text"
setForeGroundColor(fgBlue)
echo "blue text"
resetAttributes()
echo "ordinary text"
stdout.styledWriteLine(fgRed, "red text ")
# Below, resetStyle is needed to prevent leaking the set bgRed to the next
# newline.
stdout.styledWriteLine(fgWhite, bgRed, "white text in red background", resetStyle)
stdout.styledWriteLine(" ordinary text ")
stdout.styledWriteLine(fgGreen, "green text")
stdout.styledWrite(fgRed, "red text ")
stdout.styledWrite(fgWhite, bgRed, "white text in red background")
stdout.styledWrite(" ordinary text ")
stdout.styledWrite(fgGreen, "green text")
echo ""
echo "ordinary text"