diff options
author | Araq <rumpf_a@web.de> | 2018-01-14 23:49:53 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2018-01-14 23:49:53 +0100 |
commit | 9a60eae631e9f778d3920f3a66de0e726e687eef (patch) | |
tree | e0067a6a66dbaec4f667966748803bd119657277 /lib/pure/strformat.nim | |
parent | bba6d624205fbfe695b146fb63c00a2854199ee8 (diff) | |
download | Nim-9a60eae631e9f778d3920f3a66de0e726e687eef.tar.gz |
fixes #7078
Diffstat (limited to 'lib/pure/strformat.nim')
-rw-r--r-- | lib/pure/strformat.nim | 222 |
1 files changed, 111 insertions, 111 deletions
diff --git a/lib/pure/strformat.nim b/lib/pure/strformat.nim index 62b095cb1..ba21f894f 100644 --- a/lib/pure/strformat.nim +++ b/lib/pure/strformat.nim @@ -15,27 +15,27 @@ Examples: .. code-block:: nim - doAssert %"""{"abc":>4}""" == " abc" - doAssert %"""{"abc":<4}""" == "abc " + doAssert &"""{"abc":>4}""" == " abc" + doAssert &"""{"abc":<4}""" == "abc " - doAssert %"{-12345:08}" == "-0012345" - doAssert %"{-1:3}" == " -1" - doAssert %"{-1:03}" == "-01" - doAssert %"{16:#X}" == "0x10" + doAssert &"{-12345:08}" == "-0012345" + doAssert &"{-1:3}" == " -1" + doAssert &"{-1:03}" == "-01" + doAssert &"{16:#X}" == "0x10" - doAssert %"{123.456}" == "123.456" - doAssert %"{123.456:>9.3f}" == " 123.456" - doAssert %"{123.456:9.3f}" == " 123.456" - doAssert %"{123.456:9.4f}" == " 123.4560" - doAssert %"{123.456:>9.0f}" == " 123." - doAssert %"{123.456:<9.4f}" == "123.4560 " + doAssert &"{123.456}" == "123.456" + doAssert &"{123.456:>9.3f}" == " 123.456" + doAssert &"{123.456:9.3f}" == " 123.456" + doAssert &"{123.456:9.4f}" == " 123.4560" + doAssert &"{123.456:>9.0f}" == " 123." + doAssert &"{123.456:<9.4f}" == "123.4560 " - doAssert %"{123.456:e}" == "1.234560e+02" - doAssert %"{123.456:>13e}" == " 1.234560e+02" - doAssert %"{123.456:13e}" == " 1.234560e+02" + doAssert &"{123.456:e}" == "1.234560e+02" + doAssert &"{123.456:>13e}" == " 1.234560e+02" + doAssert &"{123.456:13e}" == " 1.234560e+02" -An expression like ``%"{key} is {value:arg} {{z}}"`` is transformed into: +An expression like ``&"{key} is {value:arg} {{z}}"`` is transformed into: .. code-block:: nim var temp = newStringOfCap(educatedCapGuess) @@ -48,13 +48,13 @@ An expression like ``%"{key} is {value:arg} {{z}}"`` is transformed into: Parts of the string that are enclosed in the curly braces are interpreted as Nim code, to escape an ``{`` or ``}`` double it. -``%`` delegates most of the work to an open overloaded set +``&`` delegates most of the work to an open overloaded set of ``format`` procs. The required signature for a type ``T`` that supports formatting is usually ``proc format(x: T; result: var string)`` for efficiency but can also be ``proc format(x: T): string``. ``add`` and ``$`` procs are used as the fallback implementation. -This is the concrete lookup algorithm that ``%`` uses: +This is the concrete lookup algorithm that ``&`` uses: .. code-block:: nim @@ -69,7 +69,7 @@ This is the concrete lookup algorithm that ``%`` uses: The subexpression after the colon -(``arg`` in ``%"{key} is {value:arg} {{z}}"``) is an optional argument +(``arg`` in ``&"{key} is {value:arg} {{z}}"``) is an optional argument passed to ``format``. If an optional argument is present the following lookup algorithm is used: @@ -226,8 +226,8 @@ template callFormatOption(res, arg, option) {.dirty.} = else: format($arg, option, res) -macro `%`*(pattern: string): untyped = - ## For a specification of the ``%`` macro, see the module level documentation. +macro `&`*(pattern: string): untyped = + ## For a specification of the ``&`` macro, see the module level documentation. runnableExamples: template check(actual, expected: string) = doAssert actual == expected @@ -236,113 +236,113 @@ macro `%`*(pattern: string): untyped = # Basic tests let s = "string" - check %"{0} {s}", "0 string" - check %"{s[0..2].toUpperAscii}", "STR" - check %"{-10:04}", "-010" - check %"{-10:<04}", "-010" - check %"{-10:>04}", "-010" - check %"0x{10:02X}", "0x0A" + check &"{0} {s}", "0 string" + check &"{s[0..2].toUpperAscii}", "STR" + check &"{-10:04}", "-010" + check &"{-10:<04}", "-010" + check &"{-10:>04}", "-010" + check &"0x{10:02X}", "0x0A" - check %"{10:#04X}", "0x0A" + check &"{10:#04X}", "0x0A" - check %"""{"test":#>5}""", "#test" - check %"""{"test":>5}""", " test" + check &"""{"test":#>5}""", "#test" + check &"""{"test":>5}""", " test" - check %"""{"test":#^7}""", "#test##" + check &"""{"test":#^7}""", "#test##" - check %"""{"test": <5}""", "test " - check %"""{"test":<5}""", "test " - check %"{1f:.3f}", "1.000" - check %"Hello, {s}!", "Hello, string!" + check &"""{"test": <5}""", "test " + check &"""{"test":<5}""", "test " + check &"{1f:.3f}", "1.000" + check &"Hello, {s}!", "Hello, string!" # Tests for identifers without parenthesis - check %"{s} works{s}", "string worksstring" - check %"{s:>7}", " string" - doAssert(not compiles(%"{s_works}")) # parsed as identifier `s_works` + check &"{s} works{s}", "string worksstring" + check &"{s:>7}", " string" + doAssert(not compiles(&"{s_works}")) # parsed as identifier `s_works` # Misc general tests - check %"{{}}", "{}" - check %"{0}%", "0%" - check %"{0}%asdf", "0%asdf" - check %("\n{\"\\n\"}\n"), "\n\n\n" - check %"""{"abc"}s""", "abcs" + check &"{{}}", "{}" + check &"{0}%", "0%" + check &"{0}%asdf", "0%asdf" + check &("\n{\"\\n\"}\n"), "\n\n\n" + check &"""{"abc"}s""", "abcs" # String tests - check %"""{"abc"}""", "abc" - check %"""{"abc":>4}""", " abc" - check %"""{"abc":<4}""", "abc " - check %"""{"":>4}""", " " - check %"""{"":<4}""", " " + check &"""{"abc"}""", "abc" + check &"""{"abc":>4}""", " abc" + check &"""{"abc":<4}""", "abc " + check &"""{"":>4}""", " " + check &"""{"":<4}""", " " # Int tests - check %"{12345}", "12345" - check %"{ - 12345}", "-12345" - check %"{12345:6}", " 12345" - check %"{12345:>6}", " 12345" - check %"{12345:4}", "12345" - check %"{12345:08}", "00012345" - check %"{-12345:08}", "-0012345" - check %"{0:0}", "0" - check %"{0:02}", "00" - check %"{-1:3}", " -1" - check %"{-1:03}", "-01" - check %"{10}", "10" - check %"{16:#X}", "0x10" - check %"{16:^#7X}", " 0x10 " - check %"{16:^+#7X}", " +0x10 " + check &"{12345}", "12345" + check &"{ - 12345}", "-12345" + check &"{12345:6}", " 12345" + check &"{12345:>6}", " 12345" + check &"{12345:4}", "12345" + check &"{12345:08}", "00012345" + check &"{-12345:08}", "-0012345" + check &"{0:0}", "0" + check &"{0:02}", "00" + check &"{-1:3}", " -1" + check &"{-1:03}", "-01" + check &"{10}", "10" + check &"{16:#X}", "0x10" + check &"{16:^#7X}", " 0x10 " + check &"{16:^+#7X}", " +0x10 " # Hex tests - check %"{0:x}", "0" - check %"{-0:x}", "0" - check %"{255:x}", "ff" - check %"{255:X}", "FF" - check %"{-255:x}", "-ff" - check %"{-255:X}", "-FF" - check %"{255:x} uNaffeCteD CaSe", "ff uNaffeCteD CaSe" - check %"{255:X} uNaffeCteD CaSe", "FF uNaffeCteD CaSe" - check %"{255:4x}", " ff" - check %"{255:04x}", "00ff" - check %"{-255:4x}", " -ff" - check %"{-255:04x}", "-0ff" + check &"{0:x}", "0" + check &"{-0:x}", "0" + check &"{255:x}", "ff" + check &"{255:X}", "FF" + check &"{-255:x}", "-ff" + check &"{-255:X}", "-FF" + check &"{255:x} uNaffeCteD CaSe", "ff uNaffeCteD CaSe" + check &"{255:X} uNaffeCteD CaSe", "FF uNaffeCteD CaSe" + check &"{255:4x}", " ff" + check &"{255:04x}", "00ff" + check &"{-255:4x}", " -ff" + check &"{-255:04x}", "-0ff" # Float tests - check %"{123.456}", "123.456" - check %"{-123.456}", "-123.456" - check %"{123.456:.3f}", "123.456" - check %"{123.456:+.3f}", "+123.456" - check %"{-123.456:+.3f}", "-123.456" - check %"{-123.456:.3f}", "-123.456" - check %"{123.456:1g}", "123.456" - check %"{123.456:.1f}", "123.5" - check %"{123.456:.0f}", "123." - #check %"{123.456:.0f}", "123." - check %"{123.456:>9.3f}", " 123.456" - check %"{123.456:9.3f}", " 123.456" - check %"{123.456:>9.4f}", " 123.4560" - check %"{123.456:>9.0f}", " 123." - check %"{123.456:<9.4f}", "123.4560 " + check &"{123.456}", "123.456" + check &"{-123.456}", "-123.456" + check &"{123.456:.3f}", "123.456" + check &"{123.456:+.3f}", "+123.456" + check &"{-123.456:+.3f}", "-123.456" + check &"{-123.456:.3f}", "-123.456" + check &"{123.456:1g}", "123.456" + check &"{123.456:.1f}", "123.5" + check &"{123.456:.0f}", "123." + #check &"{123.456:.0f}", "123." + check &"{123.456:>9.3f}", " 123.456" + check &"{123.456:9.3f}", " 123.456" + check &"{123.456:>9.4f}", " 123.4560" + check &"{123.456:>9.0f}", " 123." + check &"{123.456:<9.4f}", "123.4560 " # Float (scientific) tests - check %"{123.456:e}", "1.234560e+02" - check %"{123.456:>13e}", " 1.234560e+02" - check %"{123.456:<13e}", "1.234560e+02 " - check %"{123.456:.1e}", "1.2e+02" - check %"{123.456:.2e}", "1.23e+02" - check %"{123.456:.3e}", "1.235e+02" + check &"{123.456:e}", "1.234560e+02" + check &"{123.456:>13e}", " 1.234560e+02" + check &"{123.456:<13e}", "1.234560e+02 " + check &"{123.456:.1e}", "1.2e+02" + check &"{123.456:.2e}", "1.23e+02" + check &"{123.456:.3e}", "1.235e+02" # Note: times.format adheres to the format protocol. Test that this # works: import times var nullTime: DateTime - check %"{nullTime:yyyy-mm-dd}", "0000-00-00" + check &"{nullTime:yyyy-mm-dd}", "0000-00-00" # Unicode string tests - check %"""{"αβγ"}""", "αβγ" - check %"""{"αβγ":>5}""", " αβγ" - check %"""{"αβγ":<5}""", "αβγ " - check %"""a{"a"}α{"α"}€{"€"}𐍈{"𐍈"}""", "aaαα€€𐍈𐍈" - check %"""a{"a":2}α{"α":2}€{"€":2}𐍈{"𐍈":2}""", "aa αα €€ 𐍈𐍈 " + check &"""{"αβγ"}""", "αβγ" + check &"""{"αβγ":>5}""", " αβγ" + check &"""{"αβγ":<5}""", "αβγ " + check &"""a{"a"}α{"α"}€{"€"}𐍈{"𐍈"}""", "aaαα€€𐍈𐍈" + check &"""a{"a":2}α{"α":2}€{"€":2}𐍈{"𐍈":2}""", "aa αα €€ 𐍈𐍈 " # Invalid unicode sequences should be handled as plain strings. # Invalid examples taken from: https://stackoverflow.com/a/3886015/1804173 let invalidUtf8 = [ @@ -351,10 +351,10 @@ macro `%`*(pattern: string): untyped = "\xf0\x28\x8c\xbc", "\xf0\x90\x28\xbc", "\xf0\x28\x8c\x28" ] for s in invalidUtf8: - check %"{s:>5}", repeat(" ", 5-s.len) & s + check &"{s:>5}", repeat(" ", 5-s.len) & s if pattern.kind notin {nnkStrLit..nnkTripleStrLit}: - error "% only works with string literals", pattern + error "& only works with string literals", pattern let f = pattern.strVal var i = 0 let res = genSym(nskVar, "fmtRes") @@ -408,17 +408,17 @@ macro `%`*(pattern: string): untyped = echo repr result template fmt*(pattern: string): untyped = - ## An alias for ``%``. Helps to avoid conflicts with ``json``'s ``%`` operator. + ## An alias for ``&``. ## **Examples:** ## ## .. code-block:: nim ## import json - ## import strformat except `%` + ## import strformat except `&` ## ## let example = "oh, look no conflicts anymore" ## echo fmt"{example}" - bind `%` - %pattern + bind `&` + &pattern proc mkDigit(v: int, typ: char): string {.inline.} = assert(v < 26) @@ -573,7 +573,7 @@ proc parseStandardFormatSpecifier*(s: string; start = 0; proc format*(value: SomeInteger; specifier: string; res: var string) = ## Standard format implementation for ``SomeInteger``. It makes little ## sense to call this directly, but it is required to exist - ## by the ``%`` macro. + ## by the ``&`` macro. let spec = parseStandardFormatSpecifier(specifier) var radix = 10 case spec.typ @@ -590,7 +590,7 @@ proc format*(value: SomeInteger; specifier: string; res: var string) = proc format*(value: SomeReal; specifier: string; res: var string) = ## Standard format implementation for ``SomeReal``. It makes little ## sense to call this directly, but it is required to exist - ## by the ``%`` macro. + ## by the ``&`` macro. let spec = parseStandardFormatSpecifier(specifier) var fmode = ffDefault @@ -622,7 +622,7 @@ proc format*(value: SomeReal; specifier: string; res: var string) = proc format*(value: string; specifier: string; res: var string) = ## Standard format implementation for ``string``. It makes little ## sense to call this directly, but it is required to exist - ## by the ``%`` macro. + ## by the ``&`` macro. let spec = parseStandardFormatSpecifier(specifier) case spec.typ of 's', '\0': discard |