[feature]strformat: add 2 'fmt' macros that use specified characters instead of '{}' (#11748)

* [feature]strformat: add 2 'fmt' macros that use specified chars instead of '{}'

* strformat: revert documentation comments of `&` and 'fmt'

* strformat: removed single open/close char variant of fmt
This commit is contained in:
Tomohiro 2019-10-28 20:33:44 +09:00 • committed by Andreas Rumpf
commit a9d7796e1c
2 changed files with 57 additions and 14 deletions

View file

@ -523,10 +523,11 @@ template formatValue(result: var string; value: char; specifier: string) =
template formatValue(result: var string; value: cstring; specifier: string) =
result.add value
macro `&`*(pattern: string): untyped =
## For a specification of the ``&`` macro, see the module level documentation.
proc strformatImpl(pattern: NimNode; openChar, closeChar: char): NimNode =
if pattern.kind notin {nnkStrLit..nnkTripleStrLit}:
error "string formatting (fmt(), &) only works with string literals", pattern
if openChar == ':' or closeChar == ':':
error "openChar and closeChar must not be ':'"
let f = pattern.strVal
var i = 0
let res = genSym(nskVar, "fmtRes")
@ -539,18 +540,18 @@ macro `&`*(pattern: string): untyped =
newLit(f.len + expectedGrowth)))
var strlit = ""
while i < f.len:
if f[i] == '{':
if f[i] == openChar:
inc i
if f[i] == '{':
if f[i] == openChar:
inc i
strlit.add '{'
strlit.add openChar
else:
if strlit.len > 0:
result.add newCall(bindSym"add", res, newLit(strlit))
strlit = ""
var subexpr = ""
while i < f.len and f[i] != '}' and f[i] != ':':
while i < f.len and f[i] != closeChar and f[i] != ':':
subexpr.add f[i]
inc i
var x: NimNode
@ -566,17 +567,17 @@ macro `&`*(pattern: string): untyped =
var options = ""
if f[i] == ':':
inc i
while i < f.len and f[i] != '}':
while i < f.len and f[i] != closeChar:
options.add f[i]
inc i
if f[i] == '}':
if f[i] == closeChar:
inc i
else:
doAssert false, "invalid format string: missing '}'"
result.add newCall(formatSym, res, x, newLit(options))
elif f[i] == '}':
if f[i+1] == '}':
strlit.add '}'
elif f[i] == closeChar:
if f[i+1] == closeChar:
strlit.add closeChar
inc i, 2
else:
doAssert false, "invalid format string: '}' instead of '}}'"
@ -590,10 +591,20 @@ macro `&`*(pattern: string): untyped =
when defined(debugFmtDsl):
echo repr result
template fmt*(pattern: string): untyped =
macro `&`*(pattern: string): untyped = strformatImpl(pattern, '{', '}')
## For a specification of the ``&`` macro, see the module level documentation.
macro fmt*(pattern: string): untyped = strformatImpl(pattern, '{', '}')
## An alias for ``&``.
bind `&`
&pattern
macro fmt*(pattern: string; openChar, closeChar: char): untyped =
## Use ``openChar`` instead of '{' and ``closeChar`` instead of '}'
runnableExamples:
let testInt = 123
doAssert "<testInt>".fmt('<', '>') == "123"
doAssert """(()"foo" & "bar"())""".fmt(')', '(') == "(foobar)"
doAssert """ ""{"123+123"}"" """.fmt('"', '"') == " \"{246}\" "
strformatImpl(pattern, openChar.intVal.char, closeChar.intVal.char)
when isMainModule:
template check(actual, expected: string) =