@@ -380,6 +380,76 @@ proc write*(f: File, r: BiggestFloat) {.tags: [WriteIOEffect], benign.} =
380380proc write * (f: File , c: char ) {.tags : [WriteIOEffect ], benign .} =
381381 discard c_putc (cint (c), f)
382382
383+ proc isNamedTuple (T: typedesc ): bool {.magic : " TypeTrait" .}
384+ # Taken from typetraits.
385+
386+ proc writeEscapedChar (f: File , c: char ) {.inline .} =
387+ # Analogue to `sysetm.addEscapedChar`.
388+ case c
389+ of '\a ' : f.write " \\ a" # \x07
390+ of '\b ' : f.write " \\ b" # \x08
391+ of '\t ' : f.write " \\ t" # \x09
392+ of '\L ' : f.write " \\ n" # \x0A
393+ of '\v ' : f.write " \\ v" # \x0B
394+ of '\f ' : f.write " \\ f" # \x0C
395+ of '\c ' : f.write " \\ c" # \x0D
396+ of '\e ' : f.write " \\ e" # \x1B
397+ of '\\ ' : f.write (" \\\\ " )
398+ of '\' ' : f.write (" \\ '" )
399+ of '\" ' : f.write (" \\\" " )
400+ of {'\32 ' .. '\126 ' } - {'\\ ' , '\' ' , '\" ' }: f.write (c)
401+ else :
402+ f.write (" \\ x" )
403+ const HexChars = " 0123456789ABCDEF"
404+ let n = ord (c)
405+ f.write (HexChars [int ((n and 0x F0 ) shr 4 )])
406+ f.write (HexChars [int (n and 0x F )])
407+
408+ proc writeQuoted [T](f: File , arg: T) =
409+ # analogue to `addQuoted` in `system`
410+ when T is string or T is cstring :
411+ f.write (" \" " )
412+ for c in arg:
413+ # Only ASCII chars are escaped to avoid butchering
414+ # multibyte UTF-8 characters.
415+ if c <= 127 .char :
416+ f.writeEscapedChar (c)
417+ else :
418+ f.write c
419+ f.write (" \" " )
420+ elif T is char :
421+ f.write (" '" )
422+ f.addEscapedChar (x)
423+ f.write (" '" )
424+ # prevent temporary string allocation
425+ else :
426+ f.write (x)
427+
428+ proc write * [T: tuple | object ](f: File ; arg: T) =
429+ f.write " ("
430+ const isNamed = isNamedTuple (T)
431+ var count = 0
432+ for name, value in fieldPairs (arg):
433+ if count != 0 :
434+ f.write (" , " )
435+
436+ when isNamed:
437+ f.write (name, " : " )
438+
439+ when compiles ($ value):
440+ when value isnot string and value isnot seq and compiles (value.isNil):
441+ if value.isNil: result .add " nil"
442+ else : f.writeQuoted (value)
443+ else :
444+ f.writeQuoted (value)
445+ else :
446+ f.write (" ..." )
447+ inc count
448+
449+ if not isNamed and count == 1 :
450+ f.write (" ," ) # one tuple needs post comma, e.g. ``("abc",)``
451+ f.write (" )" )
452+
383453when defined (harmfulOverloadOfWrite):
384454 proc write * (f: File , a: varargs [string , `$`]) {.tags : [WriteIOEffect ], benign .} =
385455 for x in items (a): write (f, x)
0 commit comments