[backport] run nimpretty on the remaining files

This commit is contained in:
narimiran 2019-09-27 12:30:59 +02:00
commit 5732bb41ef
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]) for i in 0..len(s)-1: addXmlChar(result, s[i])
type type
CgiError* = object of IOError ## exception that is raised if a CGI error occurs CgiError* = object of IOError ## exception that is raised if a CGI error occurs
RequestMethod* = enum ## the used request method RequestMethod* = enum ## the used request method
methodNone, ## no REQUEST_METHOD environment variable methodNone, ## no REQUEST_METHOD environment variable
methodPost, ## query uses the POST method methodPost, ## query uses the POST method
methodGet ## query uses the GET method methodGet ## query uses the GET method
proc cgiError*(msg: string) {.noreturn.} = proc cgiError*(msg: string) {.noreturn.} =
## raises an ECgi exception with message `msg`. ## raises an ECgi exception with message `msg`.

View file

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

View file

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

View file

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

View file

@ -47,16 +47,17 @@ when defined(macosx) and not defined(nimdoc):
export SO_NOSIGPIPE export SO_NOSIGPIPE
type type
Port* = distinct uint16 ## port type Port* = distinct uint16 ## port type
Domain* = enum ## domain, which specifies the protocol family of the Domain* = enum ## \
## created socket. Other domains than those that are listed ## domain, which specifies the protocol family of the
## here are unsupported. ## created socket. Other domains than those that are listed
AF_UNSPEC = 0, ## unspecified domain (can be detected automatically by ## here are unsupported.
## some procedures, such as getaddrinfo) AF_UNSPEC = 0, ## unspecified domain (can be detected automatically by
AF_UNIX = 1, ## for local socket (using a file). Unsupported on Windows. ## some procedures, such as getaddrinfo)
AF_INET = 2, ## for network protocol IPv4 or AF_UNIX = 1, ## for local socket (using a file). Unsupported on Windows.
AF_INET6 = when defined(macosx): 30 else: 23 ## for network protocol IPv6. 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 SockType* = enum ## second argument to `socket` proc
SOCK_STREAM = 1, ## reliable stream-oriented service or Stream Sockets 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_RAW = 3, ## raw protocols atop the network layer.
SOCK_SEQPACKET = 5 ## reliable sequenced packet service SOCK_SEQPACKET = 5 ## reliable sequenced packet service
Protocol* = enum ## third argument to `socket` proc Protocol* = enum ## third argument to `socket` proc
IPPROTO_TCP = 6, ## Transmission control protocol. IPPROTO_TCP = 6, ## Transmission control protocol.
IPPROTO_UDP = 17, ## User datagram protocol. IPPROTO_UDP = 17, ## User datagram protocol.
IPPROTO_IP, ## Internet protocol. Unsupported on Windows. IPPROTO_IP, ## Internet protocol. Unsupported on Windows.
IPPROTO_IPV6, ## Internet Protocol Version 6. Unsupported on Windows. IPPROTO_IPV6, ## Internet Protocol Version 6. Unsupported on Windows.
IPPROTO_RAW, ## Raw IP Packets Protocol. Unsupported on Windows. IPPROTO_RAW, ## Raw IP Packets Protocol. Unsupported on Windows.
IPPROTO_ICMP ## Control message protocol. Unsupported on Windows. IPPROTO_ICMP ## Control message protocol. Unsupported on Windows.
IPPROTO_ICMPV6 ## Control message protocol for IPv6. Unsupported on Windows. IPPROTO_ICMPV6 ## Control message protocol for IPv6. Unsupported on Windows.
Servent* = object ## information about a service Servent* = object ## information about a service
name*: string name*: string
@ -94,7 +95,7 @@ when useWinVersion:
IOCPARM_MASK* = 127 IOCPARM_MASK* = 127
IOC_IN* = int(-2147483648) IOC_IN* = int(-2147483648)
FIONBIO* = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or 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 nativeAfInet = winlean.AF_INET
nativeAfInet6 = winlean.AF_INET6 nativeAfInet6 = winlean.AF_INET6
@ -126,36 +127,36 @@ proc toInt*(p: Protocol): cint
when not useWinVersion: when not useWinVersion:
proc toInt(domain: Domain): cint = proc toInt(domain: Domain): cint =
case domain case domain
of AF_UNSPEC: result = posix.AF_UNSPEC.cint of AF_UNSPEC: result = posix.AF_UNSPEC.cint
of AF_UNIX: result = posix.AF_UNIX.cint of AF_UNIX: result = posix.AF_UNIX.cint
of AF_INET: result = posix.AF_INET.cint of AF_INET: result = posix.AF_INET.cint
of AF_INET6: result = posix.AF_INET6.cint of AF_INET6: result = posix.AF_INET6.cint
proc toKnownDomain*(family: cint): Option[Domain] = proc toKnownDomain*(family: cint): Option[Domain] =
## Converts the platform-dependent ``cint`` to the Domain or none(), ## Converts the platform-dependent ``cint`` to the Domain or none(),
## if the ``cint`` is not known. ## if the ``cint`` is not known.
result = if family == posix.AF_UNSPEC: some(Domain.AF_UNSPEC) result = if family == posix.AF_UNSPEC: some(Domain.AF_UNSPEC)
elif family == posix.AF_UNIX: some(Domain.AF_UNIX) elif family == posix.AF_UNIX: some(Domain.AF_UNIX)
elif family == posix.AF_INET: some(Domain.AF_INET) elif family == posix.AF_INET: some(Domain.AF_INET)
elif family == posix.AF_INET6: some(Domain.AF_INET6) elif family == posix.AF_INET6: some(Domain.AF_INET6)
else: none(Domain) else: none(Domain)
proc toInt(typ: SockType): cint = proc toInt(typ: SockType): cint =
case typ case typ
of SOCK_STREAM: result = posix.SOCK_STREAM of SOCK_STREAM: result = posix.SOCK_STREAM
of SOCK_DGRAM: result = posix.SOCK_DGRAM of SOCK_DGRAM: result = posix.SOCK_DGRAM
of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET 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 = proc toInt(p: Protocol): cint =
case p case p
of IPPROTO_TCP: result = posix.IPPROTO_TCP of IPPROTO_TCP: result = posix.IPPROTO_TCP
of IPPROTO_UDP: result = posix.IPPROTO_UDP of IPPROTO_UDP: result = posix.IPPROTO_UDP
of IPPROTO_IP: result = posix.IPPROTO_IP of IPPROTO_IP: result = posix.IPPROTO_IP
of IPPROTO_IPV6: result = posix.IPPROTO_IPV6 of IPPROTO_IPV6: result = posix.IPPROTO_IPV6
of IPPROTO_RAW: result = posix.IPPROTO_RAW of IPPROTO_RAW: result = posix.IPPROTO_RAW
of IPPROTO_ICMP: result = posix.IPPROTO_ICMP of IPPROTO_ICMP: result = posix.IPPROTO_ICMP
of IPPROTO_ICMPV6: result = posix.IPPROTO_ICMPV6 of IPPROTO_ICMPV6: result = posix.IPPROTO_ICMPV6
else: else:
proc toInt(domain: Domain): cint = proc toInt(domain: Domain): cint =
@ -164,9 +165,9 @@ else:
proc toKnownDomain*(family: cint): Option[Domain] = proc toKnownDomain*(family: cint): Option[Domain] =
## Converts the platform-dependent ``cint`` to the Domain or none(), ## Converts the platform-dependent ``cint`` to the Domain or none(),
## if the ``cint`` is not known. ## if the ``cint`` is not known.
result = if family == winlean.AF_UNSPEC: some(Domain.AF_UNSPEC) result = if family == winlean.AF_UNSPEC: some(Domain.AF_UNSPEC)
elif family == winlean.AF_INET: some(Domain.AF_INET) elif family == winlean.AF_INET: some(Domain.AF_INET)
elif family == winlean.AF_INET6: some(Domain.AF_INET6) elif family == winlean.AF_INET6: some(Domain.AF_INET6)
else: none(Domain) else: none(Domain)
proc toInt(typ: SockType): cint = 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. # 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 # 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) 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. ## Marks ``socket`` as accepting connections.
## ``Backlog`` specifies the maximum length of the ## ``Backlog`` specifies the maximum length of the
## queue of pending connections. ## 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. # FreeBSD, Haiku don't support AI_V4MAPPED but defines the macro.
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092 # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092
# https://dev.haiku-os.org/ticket/14323 # 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: if domain == AF_INET6:
hints.ai_flags = AI_V4MAPPED hints.ai_flags = AI_V4MAPPED
let socketPort = if sockType == SOCK_RAW: "" else: $port 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. ## this is a no-op; otherwise, it performs a 4-byte swap operation.
when cpuEndian == bigEndian: result = x when cpuEndian == bigEndian: result = x
else: result = (x shr 24'u32) or else: result = (x shr 24'u32) or
(x shr 8'u32 and 0xff00'u32) or (x shr 8'u32 and 0xff00'u32) or
(x shl 8'u32 and 0xff0000'u32) or (x shl 8'u32 and 0xff0000'u32) or
(x shl 24'u32) (x shl 24'u32)
proc ntohs*(x: uint16): uint16 = proc ntohs*(x: uint16): uint16 =
## Converts 16-bit unsigned integers from network to host byte order. On ## 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. # Cannot use INET6_ADDRSTRLEN here, because it's a C define.
result[0] = newString(64) result[0] = newString(64)
if inet_ntop(name.sin6_family.cint, 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()) raiseOSError(osLastError())
setLen(result[0], result[0].cstring.len) setLen(result[0], result[0].cstring.len)
result[1] = Port(nativesockets.ntohs(name.sin6_port)) 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. # Cannot use INET6_ADDRSTRLEN here, because it's a C define.
result[0] = newString(64) result[0] = newString(64)
if inet_ntop(name.sin6_family.cint, 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()) raiseOSError(osLastError())
setLen(result[0], result[0].cstring.len) setLen(result[0], result[0].cstring.len)
result[1] = Port(nativesockets.ntohs(name.sin6_port)) result[1] = Port(nativesockets.ntohs(name.sin6_port))

View file

@ -201,7 +201,8 @@ proc writeProfile() {.noconv.} =
let procname = profileData[i].st[ii] let procname = profileData[i].st[ii]
let filename = profileData[i].st.files[ii] let filename = profileData[i].st.files[ii]
if isNil(procname): break if isNil(procname): break
writeLine(f, " ", $filename & ": " & $procname, " ", perProc[$procname] // totalCalls) writeLine(f, " ", $filename & ": " & $procname, " ",
perProc[$procname] // totalCalls)
close(f) close(f)
echo "... done" echo "... done"
else: 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]" assert $(b.map(isEven)) == "None[bool]"
if self.isSome: if self.isSome:
some[R]( callback(self.val) ) some[R](callback(self.val))
else: else:
none(R) none(R)
@ -273,7 +273,8 @@ proc flatten*[A](self: Option[Option[A]]): Option[A] =
else: else:
none(A) 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 ## Applies a `callback` function to the value of the `Option` and returns an
## `Option` containing the new value. ## `Option` containing the new value.
## ##

View file

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

View file

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

View file

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

View file

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

View file

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