diff --git a/balls.nimble b/balls.nimble index 1a828f0..867b50a 100644 --- a/balls.nimble +++ b/balls.nimble @@ -1,4 +1,4 @@ -version = "2.4.3" +version = "2.4.4" author = "disruptek" description = "a unittest framework with balls 🔴🟡🟢" license = "MIT" diff --git a/balls/runner.nim b/balls/runner.nim index 55ca344..8ac151a 100644 --- a/balls/runner.nim +++ b/balls/runner.nim @@ -118,15 +118,19 @@ proc matrixTable*(matrix: Matrix): string = let status = matrix[profile] row.add: if useColor(): - $statusStyles[status] & "●" + $statusStyles[status] & $status else: - $status # without color; this will be bland + $status matrix.del profile else: row.add " " tab.rows.add row break - result = render tab + + # pass the length of StatusKind.None; this corresponds to the width + # of the other StatusKind values, in characters, which is 1 for bland + # values and 2 for wide emojis + result = render(tab, size = len $None) proc hints*(p: Profile; ci: bool): string = ## Compute `--hint` and `--warning` flags as appropriate given Profile diff --git a/balls/spec.nim b/balls/spec.nim index 1feb7bc..4a113bc 100644 --- a/balls/spec.nim +++ b/balls/spec.nim @@ -2,6 +2,7 @@ import std/times import std/macros import std/os +import grok import grok/mem # for quiesceMemory() when defined(js): @@ -59,7 +60,7 @@ when ballsDry: None = " " ## (undefined) Info = "⊚" ## may prefix information Pass = "●" ## total success - Skip = "↣" ## test was skipped + Skip = "⸮" ## test was skipped Part = "◐" ## partial success Fail = "○" ## assertion failure Died = "✷" ## unexpected exception @@ -129,10 +130,12 @@ proc dollar*(n: NimNode): NimNode = ## If it's not a string literal, dollar it. if n.kind == nnkStrLit: result = n - elif n.kind == nnkCall and $n[0] in ["$", "&"]: + elif n.kind == nnkCall and n[0].strVal in ["$", "&"]: result = n else: - result = newCall(bindSym"$", n) + result = nnkCall.newTreeFrom n: + bindSym"$" + n proc flushStderr*() {.noconv, used.} = ## Convenience for flushing stderr during process exit. diff --git a/balls/style.nim b/balls/style.nim index 3e2d545..ba07d36 100644 --- a/balls/style.nim +++ b/balls/style.nim @@ -1,6 +1,8 @@ import std/macros import std/colors +import grok + import balls/spec type @@ -93,10 +95,14 @@ proc `$`*(style: Styling): string = proc `&`*(style: Styling; n: NimNode): NimNode = ## combine style and something $able, but only output the ## style if you find that the program is on a tty at runtime - let useColor = bindSym"useColor" let n = dollar n - let text = newStmtList(newLit($style), n, newLit($resetStyle)) - result = nnkIfStmt.newNimNode(n) - result.add nnkElifBranch.newTree(newCall(useColor), - nestList(ident"&", text)) - result.add nnkElse.newTree(n) + result = nnkIfStmt.newTreeFrom n: + nnkElifBranch.newTreeFrom n: + bindSym"useColor".newCall + nestList ident"&": + nnkStmtList.newTreeFrom n: + newLit $style + n + newLit $resetStyle + nnkElse.newTree: + n diff --git a/balls/tabouli.nim b/balls/tabouli.nim index 2ae2522..570fd70 100644 --- a/balls/tabouli.nim +++ b/balls/tabouli.nim @@ -8,8 +8,10 @@ type rows*: seq[seq[string]] freeze*: int # column freeze, like in a spreadsheet -proc render*(t: Tabouli): string = - ## render a table as a string, perhaps with style +proc render*(t: Tabouli; size = 1): string = + ## render a table as a string, perhaps with style; the size argument + ## defines the the anticipated width of unfrozen columns without regard + ## to styling. this allows us to handle 2-char wide emojis properly. const pad = " " result = $headerStyle @@ -44,7 +46,7 @@ proc render*(t: Tabouli): string = else: # NOTE: later columns are aligned, but we don't use align() # 'cause it won't understand our embedded style controls - result.add spaces(widths[i] - 1) + result.add spaces(widths[i] - min(size, s.len)) result.add s if i == 0: result.add $resetStyle # reset the style after the leader