[backport] run nimpretty on the remaining files
This commit is contained in:
parent
34d0be2ec1
commit
5732bb41ef
13 changed files with 457 additions and 414 deletions
|
|
@ -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`.
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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":
|
||||||
|
|
@ -369,13 +369,14 @@ method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) =
|
||||||
try:
|
try:
|
||||||
var handle = stdout
|
var handle = stdout
|
||||||
if logger.useStderr:
|
if logger.useStderr:
|
||||||
handle = stderr
|
handle = stderr
|
||||||
writeLine(handle, ln)
|
writeLine(handle, ln)
|
||||||
if level in {lvlError, lvlFatal}: flushFile(handle)
|
if level in {lvlError, lvlFatal}: flushFile(handle)
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -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', '_'}
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
##
|
##
|
||||||
|
|
|
||||||
|
|
@ -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"""{@}$""")
|
||||||
|
|
|
||||||
|
|
@ -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()))
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue