Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 104 additions & 2 deletions lib/system/io.nim
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,110 @@ proc write*(f: File, r: BiggestFloat) {.tags: [WriteIOEffect], benign.} =
proc write*(f: File, c: char) {.tags: [WriteIOEffect], benign.} =
discard c_putc(cint(c), f)

proc write*(f: File, a: varargs[string, `$`]) {.tags: [WriteIOEffect], benign.} =
for x in items(a): write(f, x)
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
# Taken from typetraits.

proc writeEscapedChar(f: File, c: char) {.inline.} =
# Analogue to `sysetm.addEscapedChar`.
case c
of '\a': f.write "\\a" # \x07
of '\b': f.write "\\b" # \x08
of '\t': f.write "\\t" # \x09
of '\L': f.write "\\n" # \x0A
of '\v': f.write "\\v" # \x0B
of '\f': f.write "\\f" # \x0C
of '\c': f.write "\\c" # \x0D
of '\e': f.write "\\e" # \x1B
of '\\': f.write("\\\\")
of '\'': f.write("\\'")
of '\"': f.write("\\\"")
of {'\32'..'\126'} - {'\\', '\'', '\"'}: f.write(c)
else:
f.write("\\x")
const HexChars = "0123456789ABCDEF"
let n = ord(c)
f.write(HexChars[int((n and 0xF0) shr 4)])
f.write(HexChars[int(n and 0xF)])

proc writeQuoted[T](f: File, arg: T) =
# analogue to `addQuoted` in `system`
when T is string or T is cstring:
f.write("\"")
for c in arg:
# Only ASCII chars are escaped to avoid butchering
# multibyte UTF-8 characters.
if c <= 127.char:
f.writeEscapedChar(c)
else:
f.write c
f.write("\"")
elif T is char:
f.write("'")
f.addEscapedChar(x)
f.write("'")
# prevent temporary string allocation
else:
f.write(x)

proc write*[T: tuple|object](f: File; arg: T) =
f.write "("
const isNamed = T is object or isNamedTuple(T)
var count = 0
for name, value in fieldPairs(arg):
if count != 0:
f.write(", ")

when isNamed:
f.write(name, ": ")

when compiles($value):
when value isnot string and value isnot seq and compiles(value.isNil):
if value.isNil: f.write "nil"
else: f.writeQuoted(value)
else:
f.writeQuoted(value)
else:
f.write("...")
inc count

if not isNamed and count == 1:
f.write(",") # one tuple needs post comma, e.g. ``("abc",)``
f.write(")")

when defined(harmfulOverloadOfWrite):
proc write*(f: File, a: varargs[string, `$`]) {.tags: [WriteIOEffect], benign.} =
for x in items(a): write(f, x)
else:
# no macros available
proc write*[T1,T2](f: File, arg1: T1, arg2: T2) =
f.write(arg1)
f.write(arg2)

proc write*[T1,T2,T3](f: File, arg1: T1, arg2: T2, arg3: T3) =
f.write(arg1)
f.write(arg2)
f.write(arg3)

proc write*[T1,T2,T3,T4](f: File, arg1: T1, arg2: T2, arg3: T3, arg4: T4) =
f.write(arg1)
f.write(arg2)
f.write(arg3)
f.write(arg4)

proc write*[T1,T2,T3,T4,T5](f: File, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) =
f.write(arg1)
f.write(arg2)
f.write(arg3)
f.write(arg4)
f.write(arg5)

proc write*[T1,T2,T3,T4,T5,T6](f: File, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) =
f.write(arg1)
f.write(arg2)
f.write(arg3)
f.write(arg4)
f.write(arg5)
f.write(arg6)

proc readAllBuffer(file: File): string =
# This proc is for File we want to read but don't know how many
Expand Down
2 changes: 1 addition & 1 deletion tests/parser/tmultiline_comments.nim
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ proc writeln(a: auto, x: varargs[string, `$`]) =
write a, x
stdout.write "\n"

proc write() = write(stdout)
proc write() = discard
proc writeln() =
stdout.write "\n"

Expand Down