[backport] run nimpretty on the remaining files

(cherry picked from commit 5732bb41ef)
This commit is contained in:
narimiran
2019-09-27 12:30:59 +02:00
parent ac2181c5b9
commit cd3d4b5e05
13 changed files with 457 additions and 414 deletions

View File

@@ -58,11 +58,11 @@ proc xmlEncode*(s: string): string =
for i in 0..len(s)-1: addXmlChar(result, s[i])
type
CgiError* = object of IOError ## exception that is raised if a CGI error occurs
RequestMethod* = enum ## the used request method
methodNone, ## no REQUEST_METHOD environment variable
methodPost, ## query uses the POST method
methodGet ## query uses the GET method
CgiError* = object of IOError ## exception that is raised if a CGI error occurs
RequestMethod* = enum ## the used request method
methodNone, ## no REQUEST_METHOD environment variable
methodPost, ## query uses the POST method
methodGet ## query uses the GET method
proc cgiError*(msg: string) {.noreturn.} =
## raises an ECgi exception with message `msg`.

View File

@@ -23,7 +23,7 @@
when not nimCoroutines and not defined(nimdoc):
when defined(noNimCoroutines):
{.error: "Coroutines can not be used with -d:noNimCoroutines"}
{.error: "Coroutines can not be used with -d:noNimCoroutines".}
else:
{.error: "Coroutines require -d:nimCoroutines".}
@@ -75,13 +75,18 @@ elif coroBackend == CORO_BACKEND_UCONTEXT:
Context = ucontext_t
proc getcontext(context: var ucontext_t): int32 {.importc, header: "<ucontext.h>".}
proc setcontext(context: var ucontext_t): int32 {.importc, header: "<ucontext.h>".}
proc swapcontext(fromCtx, toCtx: var ucontext_t): int32 {.importc, header: "<ucontext.h>".}
proc makecontext(context: var ucontext_t, fn: pointer, argc: int32) {.importc, header: "<ucontext.h>", varargs.}
proc getcontext(context: var ucontext_t): int32 {.importc,
header: "<ucontext.h>".}
proc setcontext(context: var ucontext_t): int32 {.importc,
header: "<ucontext.h>".}
proc swapcontext(fromCtx, toCtx: var ucontext_t): int32 {.importc,
header: "<ucontext.h>".}
proc makecontext(context: var ucontext_t, fn: pointer, argc: int32) {.importc,
header: "<ucontext.h>", varargs.}
elif coroBackend == CORO_BACKEND_SETJMP:
proc coroExecWithStack*(fn: pointer, stack: pointer) {.noreturn, importc: "narch_$1", fastcall.}
proc coroExecWithStack*(fn: pointer, stack: pointer) {.noreturn,
importc: "narch_$1", fastcall.}
when defined(amd64):
{.compile: "../arch/x86/amd64.S".}
elif defined(i386):
@@ -105,14 +110,14 @@ elif coroBackend == CORO_BACKEND_SETJMP:
{.error: "Unsupported architecture.".}
proc setjmp(ctx: var JmpBuf): int {.importc: "narch_$1".}
proc longjmp(ctx: JmpBuf, ret=1) {.importc: "narch_$1".}
proc longjmp(ctx: JmpBuf, ret = 1) {.importc: "narch_$1".}
else:
# Use setjmp/longjmp implementation provided by the system.
type
JmpBuf {.importc: "jmp_buf", header: "<setjmp.h>".} = object
proc setjmp(ctx: var JmpBuf): int {.importc, header: "<setjmp.h>".}
proc longjmp(ctx: JmpBuf, ret=1) {.importc, header: "<setjmp.h>".}
proc longjmp(ctx: JmpBuf, ret = 1) {.importc, header: "<setjmp.h>".}
type
Context = JmpBuf
@@ -134,8 +139,8 @@ const
type
Stack {.pure.} = object
top: pointer # Top of the stack. Pointer used for deallocating stack if we own it.
bottom: pointer # Very bottom of the stack, acts as unique stack identifier.
top: pointer # Top of the stack. Pointer used for deallocating stack if we own it.
bottom: pointer # Very bottom of the stack, acts as unique stack identifier.
size: int
Coroutine {.pure.} = object
@@ -211,7 +216,7 @@ proc switchTo(current, to: CoroutinePtr) =
setFrameState(frame)
GC_setActiveStack(current.stack.bottom)
proc suspend*(sleepTime: float=0) =
proc suspend*(sleepTime: float = 0) =
## Stops coroutine execution and resumes no sooner than after ``sleeptime`` seconds.
## Until then other coroutines are executed.
var current = getCurrent()
@@ -234,15 +239,15 @@ proc runCurrentTask() =
GC_setActiveStack(sp)
current.state = CORO_EXECUTING
try:
current.fn() # Start coroutine execution
current.fn() # Start coroutine execution
except:
echo "Unhandled exception in coroutine."
writeStackTrace()
current.state = CORO_FINISHED
suspend(0) # Exit coroutine without returning from coroExecWithStack()
suspend(0) # Exit coroutine without returning from coroExecWithStack()
doAssert false
proc start*(c: proc(), stacksize: int=defaultStackSize): CoroutineRef {.discardable.} =
proc start*(c: proc(), stacksize: int = defaultStackSize): CoroutineRef {.discardable.} =
## Schedule coroutine for execution. It does not run immediately.
if ctx == nil:
initialize()
@@ -251,7 +256,9 @@ proc start*(c: proc(), stacksize: int=defaultStackSize): CoroutineRef {.discarda
when coroBackend == CORO_BACKEND_FIBERS:
coro = cast[CoroutinePtr](alloc0(sizeof(Coroutine)))
coro.execContext = CreateFiberEx(stacksize, stacksize,
FIBER_FLAG_FLOAT_SWITCH, (proc(p: pointer): void {.stdcall.} = runCurrentTask()), nil)
FIBER_FLAG_FLOAT_SWITCH,
(proc(p: pointer): void {.stdcall.} = runCurrentTask()),
nil)
coro.stack.size = stacksize
else:
coro = cast[CoroutinePtr](alloc0(sizeof(Coroutine) + stacksize))
@@ -313,7 +320,7 @@ proc run*() =
proc alive*(c: CoroutineRef): bool = c.coro != nil and c.coro.state != CORO_FINISHED
## Returns ``true`` if coroutine has not returned, ``false`` otherwise.
proc wait*(c: CoroutineRef, interval=0.01) =
proc wait*(c: CoroutineRef, interval = 0.01) =
## Returns only after coroutine ``c`` has returned. ``interval`` is time in seconds how often.
while alive(c):
suspend(interval)

View File

@@ -18,62 +18,62 @@ type
DbEffect* = object of IOEffect ## effect that denotes a database operation
ReadDbEffect* = object of DbEffect ## effect that denotes a read operation
WriteDbEffect* = object of DbEffect ## effect that denotes a write operation
ReadDbEffect* = object of DbEffect ## effect that denotes a read operation
WriteDbEffect* = object of DbEffect ## effect that denotes a write operation
DbTypeKind* = enum ## a superset of datatypes that might be supported.
dbUnknown, ## unknown datatype
dbSerial, ## datatype used for primary auto-increment keys
dbNull, ## datatype used for the NULL value
dbBit, ## bit datatype
dbBool, ## boolean datatype
dbBlob, ## blob datatype
dbFixedChar, ## string of fixed length
dbVarchar, ## string datatype
dbJson, ## JSON datatype
dbXml, ## XML datatype
dbInt, ## some integer type
dbUInt, ## some unsigned integer type
dbDecimal, ## decimal numbers (fixed-point number)
dbFloat, ## some floating point type
dbDate, ## a year-month-day description
dbTime, ## HH:MM:SS information
dbDatetime, ## year-month-day and HH:MM:SS information,
## plus optional time or timezone information
dbTimestamp, ## Timestamp values are stored as the number of seconds
## since the epoch ('1970-01-01 00:00:00' UTC).
dbTimeInterval, ## an interval [a,b] of times
dbEnum, ## some enum
dbSet, ## set of enum values
dbArray, ## an array of values
dbComposite, ## composite type (record, struct, etc)
dbUrl, ## a URL
dbUuid, ## a UUID
dbInet, ## an IP address
dbMacAddress, ## a MAC address
dbGeometry, ## some geometric type
dbPoint, ## Point on a plane (x,y)
dbLine, ## Infinite line ((x1,y1),(x2,y2))
dbLseg, ## Finite line segment ((x1,y1),(x2,y2))
dbBox, ## Rectangular box ((x1,y1),(x2,y2))
dbPath, ## Closed or open path (similar to polygon) ((x1,y1),...)
dbPolygon, ## Polygon (similar to closed path) ((x1,y1),...)
dbCircle, ## Circle <(x,y),r> (center point and radius)
dbUser1, ## user definable datatype 1 (for unknown extensions)
dbUser2, ## user definable datatype 2 (for unknown extensions)
dbUser3, ## user definable datatype 3 (for unknown extensions)
dbUser4, ## user definable datatype 4 (for unknown extensions)
dbUser5 ## user definable datatype 5 (for unknown extensions)
DbTypeKind* = enum ## a superset of datatypes that might be supported.
dbUnknown, ## unknown datatype
dbSerial, ## datatype used for primary auto-increment keys
dbNull, ## datatype used for the NULL value
dbBit, ## bit datatype
dbBool, ## boolean datatype
dbBlob, ## blob datatype
dbFixedChar, ## string of fixed length
dbVarchar, ## string datatype
dbJson, ## JSON datatype
dbXml, ## XML datatype
dbInt, ## some integer type
dbUInt, ## some unsigned integer type
dbDecimal, ## decimal numbers (fixed-point number)
dbFloat, ## some floating point type
dbDate, ## a year-month-day description
dbTime, ## HH:MM:SS information
dbDatetime, ## year-month-day and HH:MM:SS information,
## plus optional time or timezone information
dbTimestamp, ## Timestamp values are stored as the number of seconds
## since the epoch ('1970-01-01 00:00:00' UTC).
dbTimeInterval, ## an interval [a,b] of times
dbEnum, ## some enum
dbSet, ## set of enum values
dbArray, ## an array of values
dbComposite, ## composite type (record, struct, etc)
dbUrl, ## a URL
dbUuid, ## a UUID
dbInet, ## an IP address
dbMacAddress, ## a MAC address
dbGeometry, ## some geometric type
dbPoint, ## Point on a plane (x,y)
dbLine, ## Infinite line ((x1,y1),(x2,y2))
dbLseg, ## Finite line segment ((x1,y1),(x2,y2))
dbBox, ## Rectangular box ((x1,y1),(x2,y2))
dbPath, ## Closed or open path (similar to polygon) ((x1,y1),...)
dbPolygon, ## Polygon (similar to closed path) ((x1,y1),...)
dbCircle, ## Circle <(x,y),r> (center point and radius)
dbUser1, ## user definable datatype 1 (for unknown extensions)
dbUser2, ## user definable datatype 2 (for unknown extensions)
dbUser3, ## user definable datatype 3 (for unknown extensions)
dbUser4, ## user definable datatype 4 (for unknown extensions)
dbUser5 ## user definable datatype 5 (for unknown extensions)
DbType* = object ## describes a database type
kind*: DbTypeKind ## the kind of the described type
notNull*: bool ## does the type contain NULL?
name*: string ## the name of the type
size*: Natural ## the size of the datatype; 0 if of variable size
maxReprLen*: Natural ## maximal length required for the representation
DbType* = object ## describes a database type
kind*: DbTypeKind ## the kind of the described type
notNull*: bool ## does the type contain NULL?
name*: string ## the name of the type
size*: Natural ## the size of the datatype; 0 if of variable size
maxReprLen*: Natural ## maximal length required for the representation
precision*, scale*: Natural ## precision and scale of the number
min*, max*: BiggestInt ## the minimum and maximum of allowed values
validValues*: seq[string] ## valid values of an enum or a set
min*, max*: BiggestInt ## the minimum and maximum of allowed values
validValues*: seq[string] ## valid values of an enum or a set
DbColumn* = object ## information about a database column
name*: string ## name of the column

View File

@@ -147,7 +147,7 @@ when not defined(js):
import os
type
Level* = enum
Level* = enum ## \
## Enumeration of logging levels.
##
## Debug messages represent the lowest logging level, and fatal error
@@ -173,22 +173,21 @@ type
## any messages with a level lower than the threshold. There is also
## a global filter that applies to all log messages, and it can be changed
## using the `setLogFilter proc<#setLogFilter,Level>`_.
lvlAll, ## All levels active
lvlDebug, ## Debug level and above are active
lvlInfo, ## Info level and above are active
lvlNotice, ## Notice level and above are active
lvlWarn, ## Warn level and above are active
lvlError, ## Error level and above are active
lvlFatal, ## Fatal level and above are active
lvlNone ## No levels active; nothing is logged
lvlAll, ## All levels active
lvlDebug, ## Debug level and above are active
lvlInfo, ## Info level and above are active
lvlNotice, ## Notice level and above are active
lvlWarn, ## Warn level and above are active
lvlError, ## Error level and above are active
lvlFatal, ## Fatal level and above are active
lvlNone ## No levels active; nothing is logged
const
LevelNames*: array[Level, string] = [
"DEBUG", "DEBUG", "INFO", "NOTICE", "WARN", "ERROR", "FATAL", "NONE"
] ## Array of strings representing each logging level.
] ## Array of strings representing each logging level.
defaultFmtStr* = "$levelname " ## \
## The default format string.
defaultFmtStr* = "$levelname " ## The default format string.
verboseFmtStr* = "$levelid, [$datetime] -- $appname: " ## \
## A more verbose format string.
##
@@ -211,8 +210,8 @@ type
## * `ConsoleLogger<#ConsoleLogger>`_
## * `FileLogger<#FileLogger>`_
## * `RollingFileLogger<#RollingFileLogger>`_
levelThreshold*: Level ## Only messages that are at or above this
## threshold will be logged
levelThreshold*: Level ## Only messages that are at or above this
## threshold will be logged
fmtStr*: string ## Format string to prepend to each log message;
## defaultFmtStr is the default
@@ -240,7 +239,7 @@ when not defined(js):
## See also:
## * `ConsoleLogger<#ConsoleLogger>`_
## * `RollingFileLogger<#RollingFileLogger>`_
file*: File ## The wrapped file
file*: File ## The wrapped file
RollingFileLogger* = ref object of FileLogger
## A logger that writes log messages to a file while performing log
@@ -255,17 +254,18 @@ when not defined(js):
## * `ConsoleLogger<#ConsoleLogger>`_
## * `FileLogger<#FileLogger>`_
maxLines: int # maximum number of lines
curLine : int
curLine: int
baseName: string # initial filename
baseMode: FileMode # initial file mode
logFiles: int # how many log files already created, e.g. basename.1, basename.2...
bufSize: int # size of output buffer (-1: use system defaults, 0: unbuffered, >0: fixed buffer size)
var
level {.threadvar.}: Level ## global log filter
level {.threadvar.}: Level ## global log filter
handlers {.threadvar.}: seq[Logger] ## handlers with their own log levels
proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): string =
proc substituteLog*(frmt: string, level: Level,
args: varargs[string, `$`]): string =
## Formats a log message at the specified level with the given format string.
##
## The `format variables<#basic-usage-format-strings>`_ present within
@@ -307,7 +307,7 @@ proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): str
of "date": result.add(getDateStr())
of "time": result.add(getClockStr())
of "datetime": result.add(getDateStr() & "T" & getClockStr())
of "app": result.add(app)
of "app": result.add(app)
of "appdir":
when not defined(js): result.add(app.splitFile.dir)
of "appname":
@@ -369,13 +369,14 @@ method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) =
try:
var handle = stdout
if logger.useStderr:
handle = stderr
handle = stderr
writeLine(handle, ln)
if level in {lvlError, lvlFatal}: flushFile(handle)
except IOError:
discard
proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr, useStderr=false): ConsoleLogger =
proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr,
useStderr = false): ConsoleLogger =
## Creates a new `ConsoleLogger<#ConsoleLogger>`_.
##
## By default, log messages are written to ``stdout``. If ``useStderr`` is
@@ -563,7 +564,7 @@ when not defined(js):
result.fmtStr = fmtStr
result.maxLines = maxLines
result.bufSize = bufSize
result.file = open(filename, mode, bufSize=result.bufSize)
result.file = open(filename, mode, bufSize = result.bufSize)
result.curLine = 0
result.baseName = filename
result.baseMode = mode
@@ -616,7 +617,8 @@ when not defined(js):
rotate(logger)
logger.logFiles.inc
logger.curLine = 0
logger.file = open(logger.baseName, logger.baseMode, bufSize = logger.bufSize)
logger.file = open(logger.baseName, logger.baseMode,
bufSize = logger.bufSize)
writeLine(logger.file, substituteLog(logger.fmtStr, level, args))
if level in {lvlError, lvlFatal}: flushFile(logger.file)

View File

@@ -384,7 +384,7 @@ when not defined(testing) and isMainModule:
test4.b = "ref string test: B"
testit(test4)
var test5 = @[(0,1),(2,3),(4,5)]
var test5 = @[(0, 1), (2, 3), (4, 5)]
testit(test5)
var test6: set[char] = {'A'..'Z', '_'}

View File

@@ -47,16 +47,17 @@ when defined(macosx) and not defined(nimdoc):
export SO_NOSIGPIPE
type
Port* = distinct uint16 ## port type
Port* = distinct uint16 ## port type
Domain* = enum ## domain, which specifies the protocol family of the
## created socket. Other domains than those that are listed
## here are unsupported.
AF_UNSPEC = 0, ## unspecified domain (can be detected automatically by
## some procedures, such as getaddrinfo)
AF_UNIX = 1, ## for local socket (using a file). Unsupported on Windows.
AF_INET = 2, ## for network protocol IPv4 or
AF_INET6 = when defined(macosx): 30 else: 23 ## for network protocol IPv6.
Domain* = enum ## \
## domain, which specifies the protocol family of the
## created socket. Other domains than those that are listed
## here are unsupported.
AF_UNSPEC = 0, ## unspecified domain (can be detected automatically by
## some procedures, such as getaddrinfo)
AF_UNIX = 1, ## for local socket (using a file). Unsupported on Windows.
AF_INET = 2, ## for network protocol IPv4 or
AF_INET6 = when defined(macosx): 30 else: 23 ## for network protocol IPv6.
SockType* = enum ## second argument to `socket` proc
SOCK_STREAM = 1, ## reliable stream-oriented service or Stream Sockets
@@ -64,14 +65,14 @@ type
SOCK_RAW = 3, ## raw protocols atop the network layer.
SOCK_SEQPACKET = 5 ## reliable sequenced packet service
Protocol* = enum ## third argument to `socket` proc
IPPROTO_TCP = 6, ## Transmission control protocol.
IPPROTO_UDP = 17, ## User datagram protocol.
IPPROTO_IP, ## Internet protocol. Unsupported on Windows.
IPPROTO_IPV6, ## Internet Protocol Version 6. Unsupported on Windows.
IPPROTO_RAW, ## Raw IP Packets Protocol. Unsupported on Windows.
IPPROTO_ICMP ## Control message protocol. Unsupported on Windows.
IPPROTO_ICMPV6 ## Control message protocol for IPv6. Unsupported on Windows.
Protocol* = enum ## third argument to `socket` proc
IPPROTO_TCP = 6, ## Transmission control protocol.
IPPROTO_UDP = 17, ## User datagram protocol.
IPPROTO_IP, ## Internet protocol. Unsupported on Windows.
IPPROTO_IPV6, ## Internet Protocol Version 6. Unsupported on Windows.
IPPROTO_RAW, ## Raw IP Packets Protocol. Unsupported on Windows.
IPPROTO_ICMP ## Control message protocol. Unsupported on Windows.
IPPROTO_ICMPV6 ## Control message protocol for IPv6. Unsupported on Windows.
Servent* = object ## information about a service
name*: string
@@ -94,7 +95,7 @@ when useWinVersion:
IOCPARM_MASK* = 127
IOC_IN* = int(-2147483648)
FIONBIO* = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or
(102 shl 8) or 126
(102 shl 8) or 126
nativeAfInet = winlean.AF_INET
nativeAfInet6 = winlean.AF_INET6
@@ -126,36 +127,36 @@ proc toInt*(p: Protocol): cint
when not useWinVersion:
proc toInt(domain: Domain): cint =
case domain
of AF_UNSPEC: result = posix.AF_UNSPEC.cint
of AF_UNIX: result = posix.AF_UNIX.cint
of AF_INET: result = posix.AF_INET.cint
of AF_INET6: result = posix.AF_INET6.cint
of AF_UNSPEC: result = posix.AF_UNSPEC.cint
of AF_UNIX: result = posix.AF_UNIX.cint
of AF_INET: result = posix.AF_INET.cint
of AF_INET6: result = posix.AF_INET6.cint
proc toKnownDomain*(family: cint): Option[Domain] =
## Converts the platform-dependent ``cint`` to the Domain or none(),
## if the ``cint`` is not known.
result = if family == posix.AF_UNSPEC: some(Domain.AF_UNSPEC)
elif family == posix.AF_UNIX: some(Domain.AF_UNIX)
elif family == posix.AF_INET: some(Domain.AF_INET)
elif family == posix.AF_INET6: some(Domain.AF_INET6)
result = if family == posix.AF_UNSPEC: some(Domain.AF_UNSPEC)
elif family == posix.AF_UNIX: some(Domain.AF_UNIX)
elif family == posix.AF_INET: some(Domain.AF_INET)
elif family == posix.AF_INET6: some(Domain.AF_INET6)
else: none(Domain)
proc toInt(typ: SockType): cint =
case typ
of SOCK_STREAM: result = posix.SOCK_STREAM
of SOCK_DGRAM: result = posix.SOCK_DGRAM
of SOCK_STREAM: result = posix.SOCK_STREAM
of SOCK_DGRAM: result = posix.SOCK_DGRAM
of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET
of SOCK_RAW: result = posix.SOCK_RAW
of SOCK_RAW: result = posix.SOCK_RAW
proc toInt(p: Protocol): cint =
case p
of IPPROTO_TCP: result = posix.IPPROTO_TCP
of IPPROTO_UDP: result = posix.IPPROTO_UDP
of IPPROTO_IP: result = posix.IPPROTO_IP
of IPPROTO_IPV6: result = posix.IPPROTO_IPV6
of IPPROTO_RAW: result = posix.IPPROTO_RAW
of IPPROTO_ICMP: result = posix.IPPROTO_ICMP
of IPPROTO_ICMPV6: result = posix.IPPROTO_ICMPV6
of IPPROTO_TCP: result = posix.IPPROTO_TCP
of IPPROTO_UDP: result = posix.IPPROTO_UDP
of IPPROTO_IP: result = posix.IPPROTO_IP
of IPPROTO_IPV6: result = posix.IPPROTO_IPV6
of IPPROTO_RAW: result = posix.IPPROTO_RAW
of IPPROTO_ICMP: result = posix.IPPROTO_ICMP
of IPPROTO_ICMPV6: result = posix.IPPROTO_ICMPV6
else:
proc toInt(domain: Domain): cint =
@@ -164,9 +165,9 @@ else:
proc toKnownDomain*(family: cint): Option[Domain] =
## Converts the platform-dependent ``cint`` to the Domain or none(),
## if the ``cint`` is not known.
result = if family == winlean.AF_UNSPEC: some(Domain.AF_UNSPEC)
elif family == winlean.AF_INET: some(Domain.AF_INET)
elif family == winlean.AF_INET6: some(Domain.AF_INET6)
result = if family == winlean.AF_UNSPEC: some(Domain.AF_UNSPEC)
elif family == winlean.AF_INET: some(Domain.AF_INET)
elif family == winlean.AF_INET6: some(Domain.AF_INET6)
else: none(Domain)
proc toInt(typ: SockType): cint =
@@ -223,10 +224,12 @@ proc close*(socket: SocketHandle) =
# TODO: These values should not be discarded. An OSError should be raised.
# http://stackoverflow.com/questions/12463473/what-happens-if-you-call-close-on-a-bsd-socket-multiple-times
proc bindAddr*(socket: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint =
proc bindAddr*(socket: SocketHandle, name: ptr SockAddr,
namelen: SockLen): cint =
result = bindSocket(socket, name, namelen)
proc listen*(socket: SocketHandle, backlog = SOMAXCONN): cint {.tags: [ReadIOEffect].} =
proc listen*(socket: SocketHandle, backlog = SOMAXCONN): cint {.tags: [
ReadIOEffect].} =
## Marks ``socket`` as accepting connections.
## ``Backlog`` specifies the maximum length of the
## queue of pending connections.
@@ -250,7 +253,8 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET,
# FreeBSD, Haiku don't support AI_V4MAPPED but defines the macro.
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092
# https://dev.haiku-os.org/ticket/14323
when not defined(freebsd) and not defined(openbsd) and not defined(netbsd) and not defined(android) and not defined(haiku):
when not defined(freebsd) and not defined(openbsd) and not defined(netbsd) and
not defined(android) and not defined(haiku):
if domain == AF_INET6:
hints.ai_flags = AI_V4MAPPED
let socketPort = if sockType == SOCK_RAW: "" else: $port
@@ -267,9 +271,9 @@ proc ntohl*(x: uint32): uint32 =
## this is a no-op; otherwise, it performs a 4-byte swap operation.
when cpuEndian == bigEndian: result = x
else: result = (x shr 24'u32) or
(x shr 8'u32 and 0xff00'u32) or
(x shl 8'u32 and 0xff0000'u32) or
(x shl 24'u32)
(x shr 8'u32 and 0xff00'u32) or
(x shl 8'u32 and 0xff0000'u32) or
(x shl 24'u32)
proc ntohs*(x: uint16): uint16 =
## Converts 16-bit unsigned integers from network to host byte order. On
@@ -499,7 +503,7 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
# Cannot use INET6_ADDRSTRLEN here, because it's a C define.
result[0] = newString(64)
if inet_ntop(name.sin6_family.cint,
addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
raiseOSError(osLastError())
setLen(result[0], result[0].cstring.len)
result[1] = Port(nativesockets.ntohs(name.sin6_port))
@@ -536,7 +540,7 @@ proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
# Cannot use INET6_ADDRSTRLEN here, because it's a C define.
result[0] = newString(64)
if inet_ntop(name.sin6_family.cint,
addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
raiseOSError(osLastError())
setLen(result[0], result[0].cstring.len)
result[1] = Port(nativesockets.ntohs(name.sin6_port))

View File

@@ -201,7 +201,8 @@ proc writeProfile() {.noconv.} =
let procname = profileData[i].st[ii]
let filename = profileData[i].st.files[ii]
if isNil(procname): break
writeLine(f, " ", $filename & ": " & $procname, " ", perProc[$procname] // totalCalls)
writeLine(f, " ", $filename & ": " & $procname, " ",
perProc[$procname] // totalCalls)
close(f)
echo "... done"
else:

View File

@@ -258,7 +258,7 @@ proc map*[T, R](self: Option[T], callback: proc (input: T): R): Option[R] =
assert $(b.map(isEven)) == "None[bool]"
if self.isSome:
some[R]( callback(self.val) )
some[R](callback(self.val))
else:
none(R)
@@ -273,7 +273,8 @@ proc flatten*[A](self: Option[Option[A]]): Option[A] =
else:
none(A)
proc flatMap*[A, B](self: Option[A], callback: proc (input: A): Option[B]): Option[B] =
proc flatMap*[A, B](self: Option[A],
callback: proc (input: A): Option[B]): Option[B] =
## Applies a `callback` function to the value of the `Option` and returns an
## `Option` containing the new value.
##

View File

@@ -34,47 +34,47 @@ const
type
PegKind* = enum
pkEmpty,
pkAny, ## any character (.)
pkAnyRune, ## any Unicode character (_)
pkNewLine, ## CR-LF, LF, CR
pkLetter, ## Unicode letter
pkLower, ## Unicode lower case letter
pkUpper, ## Unicode upper case letter
pkTitle, ## Unicode title character
pkWhitespace, ## Unicode whitespace character
pkAny, ## any character (.)
pkAnyRune, ## any Unicode character (_)
pkNewLine, ## CR-LF, LF, CR
pkLetter, ## Unicode letter
pkLower, ## Unicode lower case letter
pkUpper, ## Unicode upper case letter
pkTitle, ## Unicode title character
pkWhitespace, ## Unicode whitespace character
pkTerminal,
pkTerminalIgnoreCase,
pkTerminalIgnoreStyle,
pkChar, ## single character to match
pkChar, ## single character to match
pkCharChoice,
pkNonTerminal,
pkSequence, ## a b c ... --> Internal DSL: peg(a, b, c)
pkOrderedChoice, ## a / b / ... --> Internal DSL: a / b or /[a, b, c]
pkGreedyRep, ## a* --> Internal DSL: *a
## a+ --> (a a*)
pkGreedyRepChar, ## x* where x is a single character (superop)
pkGreedyRepSet, ## [set]* (superop)
pkGreedyAny, ## .* or _* (superop)
pkOption, ## a? --> Internal DSL: ?a
pkAndPredicate, ## &a --> Internal DSL: &a
pkNotPredicate, ## !a --> Internal DSL: !a
pkCapture, ## {a} --> Internal DSL: capture(a)
pkBackRef, ## $i --> Internal DSL: backref(i)
pkSequence, ## a b c ... --> Internal DSL: peg(a, b, c)
pkOrderedChoice, ## a / b / ... --> Internal DSL: a / b or /[a, b, c]
pkGreedyRep, ## a* --> Internal DSL: *a
## a+ --> (a a*)
pkGreedyRepChar, ## x* where x is a single character (superop)
pkGreedyRepSet, ## [set]* (superop)
pkGreedyAny, ## .* or _* (superop)
pkOption, ## a? --> Internal DSL: ?a
pkAndPredicate, ## &a --> Internal DSL: &a
pkNotPredicate, ## !a --> Internal DSL: !a
pkCapture, ## {a} --> Internal DSL: capture(a)
pkBackRef, ## $i --> Internal DSL: backref(i)
pkBackRefIgnoreCase,
pkBackRefIgnoreStyle,
pkSearch, ## @a --> Internal DSL: !*a
pkCapturedSearch, ## {@} a --> Internal DSL: !*\a
pkRule, ## a <- b
pkList, ## a, b
pkStartAnchor ## ^ --> Internal DSL: startAnchor()
pkSearch, ## @a --> Internal DSL: !*a
pkCapturedSearch, ## {@} a --> Internal DSL: !*\a
pkRule, ## a <- b
pkList, ## a, b
pkStartAnchor ## ^ --> Internal DSL: startAnchor()
NonTerminalFlag* = enum
ntDeclared, ntUsed
NonTerminalObj = object ## represents a non terminal symbol
name: string ## the name of the symbol
line: int ## line the symbol has been declared/used in
col: int ## column the symbol has been declared/used in
flags: set[NonTerminalFlag] ## the nonterminal's flags
rule: Peg ## the rule that the symbol refers to
NonTerminalObj = object ## represents a non terminal symbol
name: string ## the name of the symbol
line: int ## line the symbol has been declared/used in
col: int ## column the symbol has been declared/used in
flags: set[NonTerminalFlag] ## the nonterminal's flags
rule: Peg ## the rule that the symbol refers to
Peg* {.shallow.} = object ## type that represents a PEG
case kind: PegKind
of pkEmpty..pkWhitespace: nil
@@ -320,7 +320,7 @@ proc backrefIgnoreCase*(index: range[1..MaxSubpatterns]): Peg {.
result = Peg(kind: pkBackRefIgnoreCase, index: index-1)
proc backrefIgnoreStyle*(index: range[1..MaxSubpatterns]): Peg {.
noSideEffect, rtl, extern: "npegs$1".}=
noSideEffect, rtl, extern: "npegs$1".} =
## constructs a back reference of the given `index`. `index` starts counting
## from 1. Ignores style for matching.
result = Peg(kind: pkBackRefIgnoreStyle, index: index-1)
@@ -544,7 +544,7 @@ when not useUnicode:
inc(i)
template runeLenAt(s, i): untyped = 1
proc isAlpha(a: char): bool {.inline.} = return a in {'a'..'z','A'..'Z'}
proc isAlpha(a: char): bool {.inline.} = return a in {'a'..'z', 'A'..'Z'}
proc isUpper(a: char): bool {.inline.} = return a in {'A'..'Z'}
proc isLower(a: char): bool {.inline.} = return a in {'a'..'z'}
proc isTitle(a: char): bool {.inline.} = return false
@@ -796,7 +796,8 @@ template matchOrParse(mopProc: untyped) =
of pkGreedyRepSet:
enter(pkGreedyRepSet, s, p, start)
result = 0
while start+result < s.len and contains(p.charChoice[], s[start+result]): inc(result)
while start+result < s.len and contains(p.charChoice[], s[start+result]):
inc(result)
leave(pkGreedyRepSet, s, p, start, result)
of pkOption:
enter(pkOption, s, p, start)
@@ -1278,7 +1279,7 @@ proc parallelReplace*(s: string, subs: varargs[
proc replace*(s: string, sub: Peg, cb: proc(
match: int, cnt: int, caps: openArray[string]): string): string {.
rtl, extern: "npegs$1cb".}=
rtl, extern: "npegs$1cb".} =
## Replaces `sub` in `s` by the resulting strings from the callback.
## The callback proc receives the index of the current match (starting with 0),
## the count of captures and an open array with the captures of each match. Examples:
@@ -1381,46 +1382,46 @@ type
modVerbatim,
modIgnoreCase,
modIgnoreStyle
TokKind = enum ## enumeration of all tokens
tkInvalid, ## invalid token
tkEof, ## end of file reached
tkAny, ## .
tkAnyRune, ## _
tkIdentifier, ## abc
tkStringLit, ## "abc" or 'abc'
tkCharSet, ## [^A-Z]
tkParLe, ## '('
tkParRi, ## ')'
tkCurlyLe, ## '{'
tkCurlyRi, ## '}'
tkCurlyAt, ## '{@}'
tkArrow, ## '<-'
tkBar, ## '/'
tkStar, ## '*'
tkPlus, ## '+'
tkAmp, ## '&'
tkNot, ## '!'
tkOption, ## '?'
tkAt, ## '@'
tkBuiltin, ## \identifier
tkEscaped, ## \\
tkBackref, ## '$'
tkDollar, ## '$'
tkHat ## '^'
TokKind = enum ## enumeration of all tokens
tkInvalid, ## invalid token
tkEof, ## end of file reached
tkAny, ## .
tkAnyRune, ## _
tkIdentifier, ## abc
tkStringLit, ## "abc" or 'abc'
tkCharSet, ## [^A-Z]
tkParLe, ## '('
tkParRi, ## ')'
tkCurlyLe, ## '{'
tkCurlyRi, ## '}'
tkCurlyAt, ## '{@}'
tkArrow, ## '<-'
tkBar, ## '/'
tkStar, ## '*'
tkPlus, ## '+'
tkAmp, ## '&'
tkNot, ## '!'
tkOption, ## '?'
tkAt, ## '@'
tkBuiltin, ## \identifier
tkEscaped, ## \\
tkBackref, ## '$'
tkDollar, ## '$'
tkHat ## '^'
Token {.final.} = object ## a token
kind: TokKind ## the type of the token
Token {.final.} = object ## a token
kind: TokKind ## the type of the token
modifier: Modifier
literal: string ## the parsed (string) literal
charset: set[char] ## if kind == tkCharSet
index: int ## if kind == tkBackref
literal: string ## the parsed (string) literal
charset: set[char] ## if kind == tkCharSet
index: int ## if kind == tkBackref
PegLexer {.inheritable.} = object ## the lexer object.
bufpos: int ## the current position within the buffer
buf: cstring ## the buffer itself
lineNumber: int ## the current line number
lineStart: int ## index of last line start in buffer
colOffset: int ## column to add
PegLexer {.inheritable.} = object ## the lexer object.
bufpos: int ## the current position within the buffer
buf: cstring ## the buffer itself
lineNumber: int ## the current line number
lineStart: int ## index of last line start in buffer
colOffset: int ## column to add
filename: string
const
@@ -1542,7 +1543,7 @@ proc skip(c: var PegLexer) =
of '\L':
pos = handleLF(c, pos)
else:
break # EndOfFile also leaves the loop
break # EndOfFile also leaves the loop
c.bufpos = pos
proc getString(c: var PegLexer, tok: var Token) =
@@ -1771,7 +1772,7 @@ proc arrowIsNextTok(c: PegLexer): bool =
type
EInvalidPeg* = object of ValueError ## raised if an invalid
## PEG has been detected
## PEG has been detected
PegParser = object of PegLexer ## the PEG parser object
tok: Token
nonterms: seq[NonTerminal]
@@ -1825,7 +1826,7 @@ proc builtin(p: var PegParser): Peg =
of "s": result = charSet({' ', '\9'..'\13'})
of "S": result = charSet({'\1'..'\xff'} - {' ', '\9'..'\13'})
of "w": result = charSet({'a'..'z', 'A'..'Z', '_', '0'..'9'})
of "W": result = charSet({'\1'..'\xff'} - {'a'..'z','A'..'Z','_','0'..'9'})
of "W": result = charSet({'\1'..'\xff'} - {'a'..'z', 'A'..'Z', '_', '0'..'9'})
of "a": result = charSet({'a'..'z', 'A'..'Z'})
of "A": result = charSet({'\1'..'\xff'} - {'a'..'z', 'A'..'Z'})
of "ident": result = pegs.ident
@@ -2167,8 +2168,8 @@ when isMainModule:
else: ""
assert("Var1=key1;var2=Key2; VAR3".
replace(peg"{\ident}('='{\ident})* ';'* \s*",
handleMatches)=="var1: 'key1', var2: 'Key2', var3: ''")
replace(peg"{\ident}('='{\ident})* ';'* \s*",
handleMatches) == "var1: 'key1', var2: 'Key2', var3: ''")
doAssert "test1".match(peg"""{@}$""")

View File

@@ -48,22 +48,22 @@
from math import FloatClass, sqrt, pow, round
{.push debugger:off .} # the user does not want to trace a part
{.push debugger: off.} # the user does not want to trace a part
# of the standard library!
{.push checks:off, line_dir:off, stack_trace:off.}
{.push checks: off, line_dir: off, stack_trace: off.}
type
RunningStat* = object ## an accumulator for statistical data
n*: int ## number of pushed data
min*, max*, sum*: float ## self-explaining
mom1, mom2, mom3, mom4: float ## statistical moments, mom1 is mean
RunningStat* = object ## an accumulator for statistical data
n*: int ## number of pushed data
min*, max*, sum*: float ## self-explaining
mom1, mom2, mom3, mom4: float ## statistical moments, mom1 is mean
RunningRegress* = object ## an accumulator for regression calculations
n*: int ## number of pushed data
x_stats*: RunningStat ## stats for first set of data
y_stats*: RunningStat ## stats for second set of data
s_xy: float ## accumulated data for combined xy
RunningRegress* = object ## an accumulator for regression calculations
n*: int ## number of pushed data
x_stats*: RunningStat ## stats for first set of data
y_stats*: RunningStat ## stats for second set of data
s_xy: float ## accumulated data for combined xy
# ----------- RunningStat --------------------------
proc clear*(s: var RunningStat) =
@@ -264,7 +264,7 @@ proc clear*(r: var RunningRegress) =
proc push*(r: var RunningRegress, x, y: float) =
## pushes two values `x` and `y` for processing
r.s_xy += (r.x_stats.mean() - x)*(r.y_stats.mean() - y)*
r.s_xy += (r.x_stats.mean() - x)*(r.y_stats.mean() - y) *
toFloat(r.n) / toFloat(r.n + 1)
r.x_stats.push(x)
r.y_stats.push(y)
@@ -296,7 +296,7 @@ proc correlation*(r: RunningRegress): float =
## computes the current correlation of the two data
## sets pushed into `r`
let t = r.x_stats.standardDeviation() * r.y_stats.standardDeviation()
result = r.s_xy / ( toFloat(r.n) * t )
result = r.s_xy / (toFloat(r.n) * t)
proc `+`*(a, b: RunningRegress): RunningRegress =
## combine two `RunningRegress` objects.
@@ -354,13 +354,13 @@ when isMainModule:
when not defined(cpu32):
# XXX For some reason on 32bit CPUs these results differ
var rr: RunningRegress
rr.push(@[0.0,1.0,2.8,3.0,4.0], @[0.0,1.0,2.3,3.0,4.0])
rr.push(@[0.0, 1.0, 2.8, 3.0, 4.0], @[0.0, 1.0, 2.3, 3.0, 4.0])
doAssert(rr.slope() == 0.9695585996955861)
doAssert(rr.intercept() == -0.03424657534246611)
doAssert(rr.correlation() == 0.9905100362239381)
var rr1, rr2: RunningRegress
rr1.push(@[0.0,1.0], @[0.0,1.0])
rr2.push(@[2.8,3.0,4.0], @[2.3,3.0,4.0])
rr1.push(@[0.0, 1.0], @[0.0, 1.0])
rr2.push(@[2.8, 3.0, 4.0], @[2.3, 3.0, 4.0])
let rr3 = rr1 + rr2
doAssert(rr3.correlation() == rr.correlation())
doAssert(clean(rr3.slope()) == clean(rr.slope()))

View File

@@ -126,17 +126,17 @@ when defined(windows):
proc terminalWidth*(): int =
var w: int = 0
w = terminalWidthIoctl([ getStdHandle(STD_INPUT_HANDLE),
w = terminalWidthIoctl([getStdHandle(STD_INPUT_HANDLE),
getStdHandle(STD_OUTPUT_HANDLE),
getStdHandle(STD_ERROR_HANDLE) ] )
getStdHandle(STD_ERROR_HANDLE)])
if w > 0: return w
return 80
proc terminalHeight*(): int =
var h: int = 0
h = terminalHeightIoctl([ getStdHandle(STD_INPUT_HANDLE),
h = terminalHeightIoctl([getStdHandle(STD_INPUT_HANDLE),
getStdHandle(STD_OUTPUT_HANDLE),
getStdHandle(STD_ERROR_HANDLE) ] )
getStdHandle(STD_ERROR_HANDLE)])
if h > 0: return h
return 0
@@ -164,7 +164,7 @@ when defined(windows):
proc setConsoleMode(hConsoleHandle: Handle, dwMode: DWORD): WINBOOL{.
stdcall, dynlib: "kernel32", importc: "SetConsoleMode".}
proc getCursorPos(h: Handle): tuple [x,y: int] =
proc getCursorPos(h: Handle): tuple [x, y: int] =
var c: CONSOLE_SCREEN_BUFFER_INFO
if getConsoleScreenBufferInfo(h, addr(c)) == 0:
raiseOSError(osLastError())
@@ -241,36 +241,36 @@ else:
## Returns some reasonable terminal width from either standard file
## descriptors, controlling terminal, environment variables or tradition.
var w = terminalWidthIoctl([0, 1, 2]) #Try standard file descriptors
var w = terminalWidthIoctl([0, 1, 2]) #Try standard file descriptors
if w > 0: return w
var cterm = newString(L_ctermid) #Try controlling tty
var cterm = newString(L_ctermid) #Try controlling tty
var fd = open(ctermid(cstring(cterm)), O_RDONLY)
if fd != -1:
w = terminalWidthIoctl([ int(fd) ])
w = terminalWidthIoctl([int(fd)])
discard close(fd)
if w > 0: return w
var s = getEnv("COLUMNS") #Try standard env var
var s = getEnv("COLUMNS") #Try standard env var
if len(s) > 0 and parseInt(string(s), w) > 0 and w > 0:
return w
return 80 #Finally default to venerable value
return 80 #Finally default to venerable value
proc terminalHeight*(): int =
## Returns some reasonable terminal height from either standard file
## descriptors, controlling terminal, environment variables or tradition.
## Zero is returned if the height could not be determined.
var h = terminalHeightIoctl([0, 1, 2]) # Try standard file descriptors
var h = terminalHeightIoctl([0, 1, 2]) # Try standard file descriptors
if h > 0: return h
var cterm = newString(L_ctermid) # Try controlling tty
var cterm = newString(L_ctermid) # Try controlling tty
var fd = open(ctermid(cstring(cterm)), O_RDONLY)
if fd != -1:
h = terminalHeightIoctl([ int(fd) ])
h = terminalHeightIoctl([int(fd)])
discard close(fd)
if h > 0: return h
var s = getEnv("LINES") # Try standard env var
var s = getEnv("LINES") # Try standard env var
if len(s) > 0 and parseInt(string(s), h) > 0 and h > 0:
return h
return 0 # Could not determine height
return 0 # Could not determine height
proc terminalSize*(): tuple[w, h: int] =
## Returns the terminal width and height as a tuple. Internally calls
@@ -342,7 +342,7 @@ when defined(windows):
else:
discard
proc cursorUp*(f: File, count=1) =
proc cursorUp*(f: File, count = 1) =
## Moves the cursor up by `count` rows.
when defined(windows):
let h = conHandle(f)
@@ -352,7 +352,7 @@ proc cursorUp*(f: File, count=1) =
else:
f.write("\e[" & $count & 'A')
proc cursorDown*(f: File, count=1) =
proc cursorDown*(f: File, count = 1) =
## Moves the cursor down by `count` rows.
when defined(windows):
let h = conHandle(f)
@@ -362,7 +362,7 @@ proc cursorDown*(f: File, count=1) =
else:
f.write(fmt"{stylePrefix}{count}B")
proc cursorForward*(f: File, count=1) =
proc cursorForward*(f: File, count = 1) =
## Moves the cursor forward by `count` columns.
when defined(windows):
let h = conHandle(f)
@@ -372,7 +372,7 @@ proc cursorForward*(f: File, count=1) =
else:
f.write(fmt"{stylePrefix}{count}C")
proc cursorBackward*(f: File, count=1) =
proc cursorBackward*(f: File, count = 1) =
## Moves the cursor backward by `count` columns.
when defined(windows):
let h = conHandle(f)
@@ -470,16 +470,16 @@ proc resetAttributes*(f: File) =
f.write(ansiResetCode)
type
Style* = enum ## different styles for text output
styleBright = 1, ## bright text
styleDim, ## dim text
styleItalic, ## italic (or reverse on terminals not supporting)
styleUnderscore, ## underscored text
styleBlink, ## blinking/bold text
styleBlinkRapid, ## rapid blinking/bold text (not widely supported)
styleReverse, ## reverse
styleHidden, ## hidden text
styleStrikethrough ## strikethrough
Style* = enum ## different styles for text output
styleBright = 1, ## bright text
styleDim, ## dim text
styleItalic, ## italic (or reverse on terminals not supporting)
styleUnderscore, ## underscored text
styleBlink, ## blinking/bold text
styleBlinkRapid, ## rapid blinking/bold text (not widely supported)
styleReverse, ## reverse
styleHidden, ## hidden text
styleStrikethrough ## strikethrough
when not defined(windows):
var
@@ -529,34 +529,34 @@ proc writeStyled*(txt: string, style: set[Style] = {styleBright}) =
stdout.write(ansiStyleCode(gBG))
type
ForegroundColor* = enum ## terminal's foreground colors
fgBlack = 30, ## black
fgRed, ## red
fgGreen, ## green
fgYellow, ## yellow
fgBlue, ## blue
fgMagenta, ## magenta
fgCyan, ## cyan
fgWhite, ## white
fg8Bit, ## 256-color (not supported, see ``enableTrueColors`` instead.)
fgDefault ## default terminal foreground color
ForegroundColor* = enum ## terminal's foreground colors
fgBlack = 30, ## black
fgRed, ## red
fgGreen, ## green
fgYellow, ## yellow
fgBlue, ## blue
fgMagenta, ## magenta
fgCyan, ## cyan
fgWhite, ## white
fg8Bit, ## 256-color (not supported, see ``enableTrueColors`` instead.)
fgDefault ## default terminal foreground color
BackgroundColor* = enum ## terminal's background colors
bgBlack = 40, ## black
bgRed, ## red
bgGreen, ## green
bgYellow, ## yellow
bgBlue, ## blue
bgMagenta, ## magenta
bgCyan, ## cyan
bgWhite, ## white
bg8Bit, ## 256-color (not supported, see ``enableTrueColors`` instead.)
bgDefault ## default terminal background color
BackgroundColor* = enum ## terminal's background colors
bgBlack = 40, ## black
bgRed, ## red
bgGreen, ## green
bgYellow, ## yellow
bgBlue, ## blue
bgMagenta, ## magenta
bgCyan, ## cyan
bgWhite, ## white
bg8Bit, ## 256-color (not supported, see ``enableTrueColors`` instead.)
bgDefault ## default terminal background color
when defined(windows):
var defaultForegroundColor, defaultBackgroundColor: int16 = 0xFFFF'i16 # Default to an invalid value 0xFFFF
proc setForegroundColor*(f: File, fg: ForegroundColor, bright=false) =
proc setForegroundColor*(f: File, fg: ForegroundColor, bright = false) =
## Sets the terminal's foreground color.
when defined(windows):
let h = conHandle(f)
@@ -564,7 +564,7 @@ proc setForegroundColor*(f: File, fg: ForegroundColor, bright=false) =
if defaultForegroundColor == 0xFFFF'i16:
defaultForegroundColor = old
old = if bright: old or FOREGROUND_INTENSITY
else: old and not(FOREGROUND_INTENSITY)
else: old and not(FOREGROUND_INTENSITY)
const lookup: array[ForegroundColor, int] = [
0, # ForegroundColor enum with ordinal 30
(FOREGROUND_RED),
@@ -585,7 +585,7 @@ proc setForegroundColor*(f: File, fg: ForegroundColor, bright=false) =
if bright: inc(gFG, 60)
f.write(ansiStyleCode(gFG))
proc setBackgroundColor*(f: File, bg: BackgroundColor, bright=false) =
proc setBackgroundColor*(f: File, bg: BackgroundColor, bright = false) =
## Sets the terminal's background color.
when defined(windows):
let h = conHandle(f)
@@ -593,7 +593,7 @@ proc setBackgroundColor*(f: File, bg: BackgroundColor, bright=false) =
if defaultBackgroundColor == 0xFFFF'i16:
defaultBackgroundColor = old
old = if bright: old or BACKGROUND_INTENSITY
else: old and not(BACKGROUND_INTENSITY)
else: old and not(BACKGROUND_INTENSITY)
const lookup: array[BackgroundColor, int] = [
0, # BackgroundColor enum with ordinal 40
(BACKGROUND_RED),
@@ -614,7 +614,7 @@ proc setBackgroundColor*(f: File, bg: BackgroundColor, bright=false) =
if bright: inc(gBG, 60)
f.write(ansiStyleCode(gBG))
proc ansiForegroundColorCode*(fg: ForegroundColor, bright=false): string =
proc ansiForegroundColorCode*(fg: ForegroundColor, bright = false): string =
var style = ord(fg)
if bright: inc(style, 60)
return ansiStyleCode(style)
@@ -670,10 +670,10 @@ proc isatty*(f: File): bool =
result = isatty(getFileHandle(f)) != 0'i32
type
TerminalCmd* = enum ## commands that can be expressed as arguments
resetStyle, ## reset attributes
fgColor, ## set foreground's true color
bgColor ## set background's true color
TerminalCmd* = enum ## commands that can be expressed as arguments
resetStyle, ## reset attributes
fgColor, ## set foreground's true color
bgColor ## set background's true color
template styledEchoProcessArg(f: File, s: string) = write f, s
template styledEchoProcessArg(f: File, style: Style) = setStyle(f, {style})
@@ -822,20 +822,20 @@ proc readPasswordFromStdin*(prompt = "password: "): TaintedString =
template hideCursor*() = hideCursor(stdout)
template showCursor*() = showCursor(stdout)
template setCursorPos*(x, y: int) = setCursorPos(stdout, x, y)
template setCursorXPos*(x: int) = setCursorXPos(stdout, x)
template setCursorXPos*(x: int) = setCursorXPos(stdout, x)
when defined(windows):
template setCursorYPos*(x: int) = setCursorYPos(stdout, x)
template cursorUp*(count=1) = cursorUp(stdout, count)
template cursorDown*(count=1) = cursorDown(stdout, count)
template cursorForward*(count=1) = cursorForward(stdout, count)
template cursorBackward*(count=1) = cursorBackward(stdout, count)
template eraseLine*() = eraseLine(stdout)
template eraseScreen*() = eraseScreen(stdout)
template setCursorYPos*(x: int) = setCursorYPos(stdout, x)
template cursorUp*(count = 1) = cursorUp(stdout, count)
template cursorDown*(count = 1) = cursorDown(stdout, count)
template cursorForward*(count = 1) = cursorForward(stdout, count)
template cursorBackward*(count = 1) = cursorBackward(stdout, count)
template eraseLine*() = eraseLine(stdout)
template eraseScreen*() = eraseScreen(stdout)
template setStyle*(style: set[Style]) =
setStyle(stdout, style)
template setForegroundColor*(fg: ForegroundColor, bright=false) =
template setForegroundColor*(fg: ForegroundColor, bright = false) =
setForegroundColor(stdout, fg, bright)
template setBackgroundColor*(bg: BackgroundColor, bright=false) =
template setBackgroundColor*(bg: BackgroundColor, bright = false) =
setBackgroundColor(stdout, bg, bright)
template setForegroundColor*(color: Color) =
setForegroundColor(stdout, color)
@@ -883,7 +883,8 @@ proc enableTrueColors*() =
else:
term.trueColorIsEnabled = true
else:
term.trueColorIsSupported = string(getEnv("COLORTERM")).toLowerAscii() in ["truecolor", "24bit"]
term.trueColorIsSupported = string(getEnv("COLORTERM")).toLowerAscii() in [
"truecolor", "24bit"]
term.trueColorIsEnabled = term.trueColorIsSupported
proc disableTrueColors*() =
@@ -944,5 +945,6 @@ when not defined(testing) and isMainModule:
echo ""
echo "ordinary text"
stdout.styledWriteLine(fgRed, "red text ", styleBright, "bold red", fgDefault, " bold text")
stdout.styledWriteLine(bgYellow, "text in yellow bg", styleBright, " bold text in yellow bg", bgDefault, " bold text")
stdout.styledWriteLine(bgYellow, "text in yellow bg", styleBright,
" bold text in yellow bg", bgDefault, " bold text")
echo "ordinary text"

View File

@@ -307,7 +307,7 @@ type
seconds: int64
nanosecond: NanosecondRange
DateTime* = object of RootObj ## \
DateTime* = object of RootObj ## \
## Represents a time in different parts. Although this type can represent
## leap seconds, they are generally not supported in this module. They are
## not ignored, but the ``DateTime``'s returned by procedures in this
@@ -323,37 +323,37 @@ type
## for changing a specific field.
nanosecond*: NanosecondRange ## The number of nanoseconds after the second,
## in the range 0 to 999_999_999.
second*: SecondRange ## The number of seconds after the minute,
## normally in the range 0 to 59, but can
## be up to 60 to allow for a leap second.
minute*: MinuteRange ## The number of minutes after the hour,
## in the range 0 to 59.
hour*: HourRange ## The number of hours past midnight,
## in the range 0 to 23.
monthday*: MonthdayRange ## The day of the month, in the range 1 to 31.
month*: Month ## The month.
year*: int ## The year, using astronomical year numbering
## (meaning that before year 1 is year 0,
## then year -1 and so on).
weekday*: WeekDay ## The day of the week.
yearday*: YeardayRange ## The number of days since January 1,
## in the range 0 to 365.
isDst*: bool ## Determines whether DST is in effect.
## Always false for the JavaScript backend.
timezone*: Timezone ## The timezone represented as an implementation
## of ``Timezone``.
utcOffset*: int ## The offset in seconds west of UTC, including
## any offset due to DST. Note that the sign of
## this number is the opposite of the one in a
## formatted offset string like ``+01:00`` (which
## would be equivalent to the UTC offset
## ``-3600``).
second*: SecondRange ## The number of seconds after the minute,
## normally in the range 0 to 59, but can
## be up to 60 to allow for a leap second.
minute*: MinuteRange ## The number of minutes after the hour,
## in the range 0 to 59.
hour*: HourRange ## The number of hours past midnight,
## in the range 0 to 23.
monthday*: MonthdayRange ## The day of the month, in the range 1 to 31.
month*: Month ## The month.
year*: int ## The year, using astronomical year numbering
## (meaning that before year 1 is year 0,
## then year -1 and so on).
weekday*: WeekDay ## The day of the week.
yearday*: YeardayRange ## The number of days since January 1,
## in the range 0 to 365.
isDst*: bool ## Determines whether DST is in effect.
## Always false for the JavaScript backend.
timezone*: Timezone ## The timezone represented as an implementation
## of ``Timezone``.
utcOffset*: int ## The offset in seconds west of UTC, including
## any offset due to DST. Note that the sign of
## this number is the opposite of the one in a
## formatted offset string like ``+01:00`` (which
## would be equivalent to the UTC offset
## ``-3600``).
Duration* = object ## Represents a fixed duration of time, meaning a duration
## that has constant length independent of the context.
##
## To create a new ``Duration``, use `initDuration proc
## <#initDuration,int64,int64,int64,int64,int64,int64,int64,int64>`_.
## that has constant length independent of the context.
##
## To create a new ``Duration``, use `initDuration proc
## <#initDuration,int64,int64,int64,int64,int64,int64,int64,int64>`_.
seconds: int64
nanosecond: NanosecondRange
@@ -381,16 +381,16 @@ type
## Note that ``TimeInterval``'s returned from the ``times`` module are
## never normalized. If you want to normalize a time unit,
## `Duration <#Duration>`_ should be used instead.
nanoseconds*: int ## The number of nanoseconds
microseconds*: int ## The number of microseconds
milliseconds*: int ## The number of milliseconds
seconds*: int ## The number of seconds
minutes*: int ## The number of minutes
hours*: int ## The number of hours
days*: int ## The number of days
weeks*: int ## The number of weeks
months*: int ## The number of months
years*: int ## The number of years
nanoseconds*: int ## The number of nanoseconds
microseconds*: int ## The number of microseconds
milliseconds*: int ## The number of milliseconds
seconds*: int ## The number of seconds
minutes*: int ## The number of minutes
hours*: int ## The number of hours
days*: int ## The number of days
weeks*: int ## The number of weeks
months*: int ## The number of months
years*: int ## The number of years
Timezone* = ref object ## \
## Timezone interface for supporting `DateTime <#DateTime>`_\s of arbitrary
@@ -405,10 +405,10 @@ type
ZonedTime* = object ## Represents a point in time with an associated
## UTC offset and DST flag. This type is only used for
## implementing timezones.
time*: Time ## The point in time being represented.
utcOffset*: int ## The offset in seconds west of UTC,
## including any offset due to DST.
isDst*: bool ## Determines whether DST is in effect.
time*: Time ## The point in time being represented.
utcOffset*: int ## The offset in seconds west of UTC,
## including any offset due to DST.
isDst*: bool ## Determines whether DST is in effect.
DurationParts* = array[FixedTimeUnit, int64] # Array of Duration parts starts
TimeIntervalParts* = array[TimeUnit, int] # Array of Duration parts starts
@@ -419,8 +419,8 @@ const
secondsInHour = 60*60
secondsInDay = 60*60*24
rateDiff = 10000000'i64 # 100 nsecs
# The number of hectonanoseconds between 1601/01/01 (windows epoch)
# and 1970/01/01 (unix epoch).
# The number of hectonanoseconds between 1601/01/01 (windows epoch)
# and 1970/01/01 (unix epoch).
epochDiff = 116444736000000000'i64
const unitWeights: array[FixedTimeUnit, int64] = [
@@ -435,10 +435,13 @@ const unitWeights: array[FixedTimeUnit, int64] = [
]
const DefaultLocale* = DateTimeLocale(
MMM: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
MMMM: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
MMM: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
"Nov", "Dec"],
MMMM: ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"],
ddd: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
dddd: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
dddd: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday",
"Sunday"],
)
proc convert*[T: SomeInteger](unitFrom, unitTo: FixedTimeUnit, quantity: T): T
@@ -854,21 +857,24 @@ proc `==`*(a, b: Duration): bool {.operator, extern: "ntEqDuration".} =
doAssert d1 == d2
eqImpl(a, b)
proc `*`*(a: int64, b: Duration): Duration {.operator, extern: "ntMulInt64Duration".} =
proc `*`*(a: int64, b: Duration): Duration {.operator,
extern: "ntMulInt64Duration".} =
## Multiply a duration by some scalar.
runnableExamples:
doAssert 5 * initDuration(seconds = 1) == initDuration(seconds = 5)
doAssert 3 * initDuration(minutes = 45) == initDuration(hours = 2, minutes = 15)
normalize[Duration](a * b.seconds, a * b.nanosecond)
proc `*`*(a: Duration, b: int64): Duration {.operator, extern: "ntMulDuration".} =
proc `*`*(a: Duration, b: int64): Duration {.operator,
extern: "ntMulDuration".} =
## Multiply a duration by some scalar.
runnableExamples:
doAssert initDuration(seconds = 1) * 5 == initDuration(seconds = 5)
doAssert initDuration(minutes = 45) * 3 == initDuration(hours = 2, minutes = 15)
b * a
proc `div`*(a: Duration, b: int64): Duration {.operator, extern: "ntDivDuration".} =
proc `div`*(a: Duration, b: int64): Duration {.operator,
extern: "ntDivDuration".} =
## Integer division for durations.
runnableExamples:
doAssert initDuration(seconds = 3) div 2 ==
@@ -1304,7 +1310,7 @@ proc getClockStr*(dt = now()): string {.rtl, extern: "nt$1", tags: [TimeEffect].
result = intToStr(dt.hour, 2) & ':' & intToStr(dt.minute, 2) &
':' & intToStr(dt.second, 2)
proc toParts* (ti: TimeInterval): TimeIntervalParts =
proc toParts*(ti: TimeInterval): TimeIntervalParts =
## Converts a ``TimeInterval`` into an array consisting of its time units,
## starting with nanoseconds and ending with years.
##
@@ -1753,11 +1759,11 @@ type
# See the doc comment for ``TimeFormat.patterns``.
Lit
TimeFormat* = object ## Represents a format for parsing and printing
## time types.
##
## To create a new ``TimeFormat`` use `initTimeFormat proc
## <#initTimeFormat,string>`_.
TimeFormat* = object ## Represents a format for parsing and printing
## time types.
##
## To create a new ``TimeFormat`` use `initTimeFormat proc
## <#initTimeFormat,string>`_.
patterns: seq[byte] ## \
## Contains the patterns encoded as bytes.
## Literal values are encoded in a special way.
@@ -1783,7 +1789,8 @@ proc `$`*(f: TimeFormat): string =
proc raiseParseException(f: TimeFormat, input: string, msg: string) =
raise newException(TimeParseError,
"Failed to parse '" & input & "' with format '" & $f & "'. " & msg)
"Failed to parse '" & input & "' with format '" & $f &
"'. " & msg)
proc parseInt(s: string, b: var int, start = 0, maxLen = int.high,
allowSign = false): int =
@@ -1919,7 +1926,8 @@ proc initTimeFormat*(format: string): TimeFormat =
of tkPattern:
result.patterns.add(stringToPattern(token).byte)
proc formatPattern(dt: DateTime, pattern: FormatPattern, result: var string, loc: DateTimeLocale) =
proc formatPattern(dt: DateTime, pattern: FormatPattern, result: var string,
loc: DateTimeLocale) =
template yearOfEra(dt: DateTime): int =
if dt.year <= 0: abs(dt.year) + 1 else: dt.year
@@ -1934,15 +1942,15 @@ proc formatPattern(dt: DateTime, pattern: FormatPattern, result: var string, loc
result.add loc.dddd[dt.weekday]
of h:
result.add(
if dt.hour == 0: "12"
if dt.hour == 0: "12"
elif dt.hour > 12: $(dt.hour - 12)
else: $dt.hour
else: $dt.hour
)
of hh:
result.add(
if dt.hour == 0: "12"
if dt.hour == 0: "12"
elif dt.hour > 12: (dt.hour - 12).intToStr(2)
else: dt.hour.intToStr(2)
else: dt.hour.intToStr(2)
)
of H:
result.add $dt.hour
@@ -2087,7 +2095,7 @@ proc parsePattern(input: string, pattern: FormatPattern, i: var int,
parsed.month = some(month)
of MMM:
result = false
for n,v in loc.MMM:
for n, v in loc.MMM:
if input.substr(i, i+v.len-1).cmpIgnoreCase(v) == 0:
result = true
i.inc v.len
@@ -2095,7 +2103,7 @@ proc parsePattern(input: string, pattern: FormatPattern, i: var int,
break
of MMMM:
result = false
for n,v in loc.MMMM:
for n, v in loc.MMMM:
if input.substr(i, i+v.len-1).cmpIgnoreCase(v) == 0:
result = true
i.inc v.len
@@ -2270,7 +2278,8 @@ proc toDateTime(p: ParsedTime, zone: Timezone, f: TimeFormat,
result.utcOffset = p.utcOffset.get()
result = result.toTime.inZone(zone)
proc format*(dt: DateTime, f: TimeFormat, loc: DateTimeLocale = DefaultLocale): string {.raises: [].} =
proc format*(dt: DateTime, f: TimeFormat,
loc: DateTimeLocale = DefaultLocale): string {.raises: [].} =
## Format ``dt`` using the format specified by ``f``.
runnableExamples:
let f = initTimeFormat("yyyy-MM-dd")
@@ -2334,7 +2343,8 @@ template formatValue*(result: var string; value: Time, specifier: string) =
## adapter for ``strformat``. Not intended to be called directly.
result.add format(value, specifier)
proc parse*(input: string, f: TimeFormat, zone: Timezone = local(), loc: DateTimeLocale = DefaultLocale): DateTime
proc parse*(input: string, f: TimeFormat, zone: Timezone = local(),
loc: DateTimeLocale = DefaultLocale): DateTime
{.raises: [TimeParseError, Defect].} =
## Parses ``input`` as a ``DateTime`` using the format specified by ``f``.
## If no UTC offset was parsed, then ``input`` is assumed to be specified in
@@ -2377,7 +2387,8 @@ proc parse*(input: string, f: TimeFormat, zone: Timezone = local(), loc: DateTim
result = toDateTime(parsed, zone, f, input)
proc parse*(input, f: string, tz: Timezone = local(), loc: DateTimeLocale = DefaultLocale): DateTime
proc parse*(input, f: string, tz: Timezone = local(),
loc: DateTimeLocale = DefaultLocale): DateTime
{.raises: [TimeParseError, TimeFormatParseError, Defect].} =
## Shorthand for constructing a ``TimeFormat`` and using it to parse
## ``input`` as a ``DateTime``.
@@ -2390,8 +2401,9 @@ proc parse*(input, f: string, tz: Timezone = local(), loc: DateTimeLocale = Defa
let dtFormat = initTimeFormat(f)
result = input.parse(dtFormat, tz, loc = loc)
proc parse*(input: string, f: static[string], zone: Timezone = local(), loc: DateTimeLocale = DefaultLocale):
DateTime {.raises: [TimeParseError, Defect].} =
proc parse*(input: string, f: static[string], zone: Timezone = local(),
loc: DateTimeLocale = DefaultLocale):
DateTime {.raises: [TimeParseError, Defect].} =
## Overload that validates ``f`` at compile time.
const f2 = initTimeFormat(f)
result = input.parse(f2, zone, loc = loc)
@@ -2530,7 +2542,8 @@ when not defined(JS):
when defined(macosx):
var a: Timeval
gettimeofday(a)
result = toBiggestFloat(a.tv_sec.int64) + toBiggestFloat(a.tv_usec)*0.00_0001
result = toBiggestFloat(a.tv_sec.int64) + toBiggestFloat(
a.tv_usec)*0.00_0001
elif defined(posix):
var ts: Timespec
discard clock_gettime(CLOCK_REALTIME, ts)
@@ -2575,7 +2588,7 @@ proc days*(dur: Duration): int64
dur.inDays
proc hours*(dur: Duration): int64
{.inline,deprecated: "Use `inHours` instead".} =
{.inline, deprecated: "Use `inHours` instead".} =
## Number of whole hours represented by the duration.
##
## **Deprecated since version v0.20.0**: Use the `inHours proc
@@ -2647,7 +2660,8 @@ proc fractional*(dur: Duration): Duration {.inline, deprecated.} =
runnableExamples:
let dur = initDuration(minutes = 5, seconds = 6, milliseconds = 7,
microseconds = 8, nanoseconds = 9)
doAssert dur.fractional == initDuration(milliseconds = 7, microseconds = 8, nanoseconds = 9)
doAssert dur.fractional == initDuration(milliseconds = 7, microseconds = 8,
nanoseconds = 9)
initDuration(nanoseconds = dur.nanosecond)
when not defined(JS):

View File

@@ -108,10 +108,10 @@ type
FAILED,
SKIPPED
OutputLevel* = enum ## The output verbosity of the tests.
PRINT_ALL, ## Print as much as possible.
PRINT_FAILURES, ## Print only the failed tests.
PRINT_NONE ## Print nothing.
OutputLevel* = enum ## The output verbosity of the tests.
PRINT_ALL, ## Print as much as possible.
PRINT_FAILURES, ## Print only the failed tests.
PRINT_NONE ## Print nothing.
TestResult* = object
suiteName*: string
@@ -169,7 +169,8 @@ method suiteStarted*(formatter: OutputFormatter, suiteName: string) {.base, gcsa
discard
method testStarted*(formatter: OutputFormatter, testName: string) {.base, gcsafe.} =
discard
method failureOccurred*(formatter: OutputFormatter, checkpoints: seq[string], stackTrace: string) {.base, gcsafe.} =
method failureOccurred*(formatter: OutputFormatter, checkpoints: seq[string],
stackTrace: string) {.base, gcsafe.} =
## ``stackTrace`` is provided only if the failure occurred due to an exception.
## ``checkpoints`` is never ``nil``.
discard
@@ -182,7 +183,7 @@ proc addOutputFormatter*(formatter: OutputFormatter) =
formatters.add(formatter)
proc delOutputFormatter*(formatter: OutputFormatter) =
keepIf(formatters, proc (x: OutputFormatter) : bool =
keepIf(formatters, proc (x: OutputFormatter): bool =
x != formatter)
proc newConsoleOutputFormatter*(outputLevel: OutputLevel = PRINT_ALL,
@@ -197,7 +198,7 @@ proc defaultConsoleFormatter*(): <//>ConsoleOutputFormatter =
# Reading settings
# On a terminal this branch is executed
var envOutLvl = os.getEnv("NIMTEST_OUTPUT_LVL").string
var colorOutput = isatty(stdout)
var colorOutput = isatty(stdout)
if existsEnv("NIMTEST_COLOR"):
let colorEnv = getEnv("NIMTEST_COLOR")
if colorEnv == "never":
@@ -228,7 +229,8 @@ method suiteStarted*(formatter: ConsoleOutputFormatter, suiteName: string) =
method testStarted*(formatter: ConsoleOutputFormatter, testName: string) =
formatter.isInTest = true
method failureOccurred*(formatter: ConsoleOutputFormatter, checkpoints: seq[string], stackTrace: string) =
method failureOccurred*(formatter: ConsoleOutputFormatter,
checkpoints: seq[string], stackTrace: string) =
if stackTrace.len > 0:
echo stackTrace
let prefix = if formatter.isInSuite: " " else: ""
@@ -239,16 +241,18 @@ method testEnded*(formatter: ConsoleOutputFormatter, testResult: TestResult) =
formatter.isInTest = false
if formatter.outputLevel != PRINT_NONE and
(formatter.outputLevel == PRINT_ALL or testResult.status == FAILED):
(formatter.outputLevel == PRINT_ALL or testResult.status == FAILED):
let prefix = if testResult.suiteName.len > 0: " " else: ""
template rawPrint() = echo(prefix, "[", $testResult.status, "] ", testResult.testName)
template rawPrint() = echo(prefix, "[", $testResult.status, "] ",
testResult.testName)
when not defined(ECMAScript):
if formatter.colorOutput and not defined(ECMAScript):
var color = case testResult.status
of OK: fgGreen
of FAILED: fgRed
of SKIPPED: fgYellow
styledEcho styleBright, color, prefix, "[", $testResult.status, "] ", resetStyle, testResult.testName
of OK: fgGreen
of FAILED: fgRed
of SKIPPED: fgYellow
styledEcho styleBright, color, prefix, "[", $testResult.status, "] ",
resetStyle, testResult.testName
else:
rawPrint()
else:
@@ -300,7 +304,8 @@ method testStarted*(formatter: JUnitOutputFormatter, testName: string) =
formatter.testStackTrace.setLen(0)
formatter.testStartTime = epochTime()
method failureOccurred*(formatter: JUnitOutputFormatter, checkpoints: seq[string], stackTrace: string) =
method failureOccurred*(formatter: JUnitOutputFormatter,
checkpoints: seq[string], stackTrace: string) =
## ``stackTrace`` is provided only if the failure occurred due to an exception.
## ``checkpoints`` is never ``nil``.
formatter.testErrors.add(checkpoints)
@@ -310,7 +315,8 @@ method failureOccurred*(formatter: JUnitOutputFormatter, checkpoints: seq[string
method testEnded*(formatter: JUnitOutputFormatter, testResult: TestResult) =
let time = epochTime() - formatter.testStartTime
let timeStr = time.formatFloat(ffDecimal, precision = 8)
formatter.stream.writeLine("\t\t<testcase name=\"$#\" time=\"$#\">" % [xmlEscape(testResult.testName), timeStr])
formatter.stream.writeLine("\t\t<testcase name=\"$#\" time=\"$#\">" % [
xmlEscape(testResult.testName), timeStr])
case testResult.status
of OK:
discard
@@ -327,8 +333,9 @@ method testEnded*(formatter: JUnitOutputFormatter, testResult: TestResult) =
var errs = ""
if formatter.testErrors.len > 1:
var startIdx = if formatter.testStackTrace.len > 0: 0 else: 1
var endIdx = if formatter.testStackTrace.len > 0: formatter.testErrors.len - 2
else: formatter.testErrors.len - 1
var endIdx = if formatter.testStackTrace.len > 0:
formatter.testErrors.len - 2
else: formatter.testErrors.len - 1
for errIdx in startIdx..endIdx:
if errs.len > 0:
@@ -336,11 +343,13 @@ method testEnded*(formatter: JUnitOutputFormatter, testResult: TestResult) =
errs.add(xmlEscape(formatter.testErrors[errIdx]))
if formatter.testStackTrace.len > 0:
formatter.stream.writeLine("\t\t\t<error message=\"$#\">$#</error>" % [failureMsg, xmlEscape(formatter.testStackTrace)])
formatter.stream.writeLine("\t\t\t<error message=\"$#\">$#</error>" % [
failureMsg, xmlEscape(formatter.testStackTrace)])
if errs.len > 0:
formatter.stream.writeLine("\t\t\t<system-err>$#</system-err>" % errs)
else:
formatter.stream.writeLine("\t\t\t<failure message=\"$#\">$#</failure>" % [failureMsg, errs])
formatter.stream.writeLine("\t\t\t<failure message=\"$#\">$#</failure>" %
[failureMsg, errs])
formatter.stream.writeLine("\t\t</testcase>")
@@ -355,15 +364,16 @@ proc glob(matcher, filter: string): bool =
if not filter.contains('*'):
return matcher == filter
let beforeAndAfter = filter.split('*', maxsplit=1)
let beforeAndAfter = filter.split('*', maxsplit = 1)
if beforeAndAfter.len == 1:
# "foo*"
return matcher.startsWith(beforeAndAfter[0])
if matcher.len < filter.len - 1:
return false # "12345" should not match "123*345"
return false # "12345" should not match "123*345"
return matcher.startsWith(beforeAndAfter[0]) and matcher.endsWith(beforeAndAfter[1])
return matcher.startsWith(beforeAndAfter[0]) and matcher.endsWith(
beforeAndAfter[1])
proc matchFilter(suiteName, testName, filter: string): bool =
if filter == "":
@@ -371,14 +381,15 @@ proc matchFilter(suiteName, testName, filter: string): bool =
if testName == filter:
# corner case for tests containing "::" in their name
return true
let suiteAndTestFilters = filter.split("::", maxsplit=1)
let suiteAndTestFilters = filter.split("::", maxsplit = 1)
if suiteAndTestFilters.len == 1:
# no suite specified
let testFilter = suiteAndTestFilters[0]
return glob(testName, testFilter)
return glob(suiteName, suiteAndTestFilters[0]) and glob(testName, suiteAndTestFilters[1])
return glob(suiteName, suiteAndTestFilters[0]) and
glob(testName, suiteAndTestFilters[1])
when defined(testing): export matchFilter
@@ -626,7 +637,7 @@ macro check*(conditions: untyped): untyped =
let paramAst = exp[i]
if exp[i].kind == nnkIdent:
result.printOuts.add getAst(print(argStr, paramAst))
if exp[i].kind in nnkCallKinds + { nnkDotExpr, nnkBracketExpr }:
if exp[i].kind in nnkCallKinds + {nnkDotExpr, nnkBracketExpr}:
let callVar = newIdentNode(":c" & $counter)
result.assigns.add getAst(asgn(callVar, paramAst))
result.check[i] = callVar