summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKaushal Modi <kaushal.modi@gmail.com>2018-06-15 11:26:09 -0400
committerKaushal Modi <kaushal.modi@gmail.com>2018-06-18 09:09:23 -0400
commit3b5b3deecd8d49515dfa4836c452647c7ab7a506 (patch)
tree31948f20574a4ce0fb548f7fbd9fadcd4cfb2691
parent70664bd1a25cac6ce1a3d49ff82796153abbbc4f (diff)
downloadNim-3b5b3deecd8d49515dfa4836c452647c7ab7a506.tar.gz
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.
-rw-r--r--lib/pure/terminal.nim86
1 files changed, 74 insertions, 12 deletions
diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim
index 8ee95957d..3cdfe466d 100644
--- a/lib/pure/terminal.nim
+++ b/lib/pure/terminal.nim
@@ -692,6 +692,40 @@ template styledEchoProcessArg(f: File, cmd: TerminalCmd) =
   when cmd == bgColor:
     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 =
   ## Similar to ``writeLine``, but treating terminal style arguments specially.
   ## When some argument is ``Style``, ``set[Style]``, ``ForegroundColor``,
@@ -781,7 +815,7 @@ when defined(windows):
           inc i, x
         password.string.setLen(max(password.len - x, 0))
       of chr(0x0):
-        # modifier key - ignore - for details see 
+        # modifier key - ignore - for details see
         # https://github.com/nim-lang/Nim/issues/7764
         continue
       else:
@@ -840,17 +874,6 @@ proc resetAttributes*() {.noconv.} =
   ## ``system.addQuitProc(resetAttributes)``.
   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 =
   ## Returns true if a terminal supports true color.
   return trueColorIsSupported
@@ -901,3 +924,42 @@ proc disableTrueColors*() =
       trueColorIsEnabled = false
   else:
     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"