Merge branch 'master' of git@github.com:Araq/Nimrod
This commit is contained in:
commit
dc3ace4f37
1 changed files with 53 additions and 53 deletions
|
|
@ -26,19 +26,19 @@ type
|
||||||
const
|
const
|
||||||
Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'}
|
Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'}
|
||||||
## All the characters that count as whitespace.
|
## All the characters that count as whitespace.
|
||||||
|
|
||||||
Letters* = {'A'..'Z', 'a'..'z'}
|
Letters* = {'A'..'Z', 'a'..'z'}
|
||||||
## the set of letters
|
## the set of letters
|
||||||
|
|
||||||
Digits* = {'0'..'9'}
|
Digits* = {'0'..'9'}
|
||||||
## the set of digits
|
## the set of digits
|
||||||
|
|
||||||
HexDigits* = {'0'..'9', 'A'..'F', 'a'..'f'}
|
HexDigits* = {'0'..'9', 'A'..'F', 'a'..'f'}
|
||||||
## the set of hexadecimal digits
|
## the set of hexadecimal digits
|
||||||
|
|
||||||
IdentChars* = {'a'..'z', 'A'..'Z', '0'..'9', '_'}
|
IdentChars* = {'a'..'z', 'A'..'Z', '0'..'9', '_'}
|
||||||
## the set of characters an identifier can consist of
|
## the set of characters an identifier can consist of
|
||||||
|
|
||||||
IdentStartChars* = {'a'..'z', 'A'..'Z', '_'}
|
IdentStartChars* = {'a'..'z', 'A'..'Z', '_'}
|
||||||
## the set of characters an identifier can start with
|
## the set of characters an identifier can start with
|
||||||
|
|
||||||
|
|
@ -192,7 +192,7 @@ proc addf*(s: var string, formatstr: string, a: openarray[string]) {.
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect,
|
proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect,
|
||||||
rtl, extern: "nsuFormatOpenArray".} =
|
rtl, extern: "nsuFormatOpenArray".} =
|
||||||
## The `substitution`:idx: operator performs string substitutions in
|
## The `substitution`:idx: operator performs string substitutions in
|
||||||
## `formatstr` and returns a modified `formatstr`. This is often called
|
## `formatstr` and returns a modified `formatstr`. This is often called
|
||||||
## `string interpolation`:idx:.
|
## `string interpolation`:idx:.
|
||||||
|
|
@ -233,7 +233,7 @@ proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect,
|
||||||
result = newStringOfCap(formatstr.len + a.len shl 4)
|
result = newStringOfCap(formatstr.len + a.len shl 4)
|
||||||
addf(result, formatstr, a)
|
addf(result, formatstr, a)
|
||||||
|
|
||||||
proc `%` *(formatstr, a: string): string {.noSideEffect,
|
proc `%` *(formatstr, a: string): string {.noSideEffect,
|
||||||
rtl, extern: "nsuFormatSingleElem".} =
|
rtl, extern: "nsuFormatSingleElem".} =
|
||||||
## This is the same as ``formatstr % [a]``.
|
## This is the same as ``formatstr % [a]``.
|
||||||
result = newStringOfCap(formatstr.len + a.len)
|
result = newStringOfCap(formatstr.len + a.len)
|
||||||
|
|
@ -249,7 +249,7 @@ proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect,
|
||||||
var
|
var
|
||||||
first = 0
|
first = 0
|
||||||
last = len(s)-1
|
last = len(s)-1
|
||||||
if leading:
|
if leading:
|
||||||
while s[first] in chars: inc(first)
|
while s[first] in chars: inc(first)
|
||||||
if trailing:
|
if trailing:
|
||||||
while last >= 0 and s[last] in chars: dec(last)
|
while last >= 0 and s[last] in chars: dec(last)
|
||||||
|
|
@ -337,7 +337,7 @@ iterator splitLines*(s: string): string =
|
||||||
## Example:
|
## Example:
|
||||||
##
|
##
|
||||||
## .. code-block:: nimrod
|
## .. code-block:: nimrod
|
||||||
## for line in lines("\nthis\nis\nan\n\nexample\n"):
|
## for line in splitLines("\nthis\nis\nan\n\nexample\n"):
|
||||||
## writeln(stdout, line)
|
## writeln(stdout, line)
|
||||||
##
|
##
|
||||||
## Results in:
|
## Results in:
|
||||||
|
|
@ -365,7 +365,7 @@ iterator splitLines*(s: string): string =
|
||||||
|
|
||||||
proc splitLines*(s: string): seq[string] {.noSideEffect,
|
proc splitLines*(s: string): seq[string] {.noSideEffect,
|
||||||
rtl, extern: "nsuSplitLines".} =
|
rtl, extern: "nsuSplitLines".} =
|
||||||
## The same as the `splitLines` iterator, but is a proc that returns a
|
## The same as the `splitLines` iterator, but is a proc that returns a
|
||||||
## sequence of substrings.
|
## sequence of substrings.
|
||||||
accumulateResult(splitLines(s))
|
accumulateResult(splitLines(s))
|
||||||
|
|
||||||
|
|
@ -435,21 +435,21 @@ proc ParseHexInt*(s: string): int {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuParseHexInt".} =
|
rtl, extern: "nsuParseHexInt".} =
|
||||||
## Parses a hexadecimal integer value contained in `s`. If `s` is not
|
## Parses a hexadecimal integer value contained in `s`. If `s` is not
|
||||||
## a valid integer, `EInvalidValue` is raised. `s` can have one of the
|
## a valid integer, `EInvalidValue` is raised. `s` can have one of the
|
||||||
## following optional prefixes: ``0x``, ``0X``, ``#``.
|
## following optional prefixes: ``0x``, ``0X``, ``#``.
|
||||||
## Underscores within `s` are ignored.
|
## Underscores within `s` are ignored.
|
||||||
var i = 0
|
var i = 0
|
||||||
if s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2)
|
if s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2)
|
||||||
elif s[i] == '#': inc(i)
|
elif s[i] == '#': inc(i)
|
||||||
while true:
|
while true:
|
||||||
case s[i]
|
case s[i]
|
||||||
of '_': inc(i)
|
of '_': inc(i)
|
||||||
of '0'..'9':
|
of '0'..'9':
|
||||||
result = result shl 4 or (ord(s[i]) - ord('0'))
|
result = result shl 4 or (ord(s[i]) - ord('0'))
|
||||||
inc(i)
|
inc(i)
|
||||||
of 'a'..'f':
|
of 'a'..'f':
|
||||||
result = result shl 4 or (ord(s[i]) - ord('a') + 10)
|
result = result shl 4 or (ord(s[i]) - ord('a') + 10)
|
||||||
inc(i)
|
inc(i)
|
||||||
of 'A'..'F':
|
of 'A'..'F':
|
||||||
result = result shl 4 or (ord(s[i]) - ord('A') + 10)
|
result = result shl 4 or (ord(s[i]) - ord('A') + 10)
|
||||||
inc(i)
|
inc(i)
|
||||||
of '\0': break
|
of '\0': break
|
||||||
|
|
@ -473,7 +473,7 @@ proc align*(s: string, count: int): string {.
|
||||||
## Aligns a string `s` with spaces, so that is of length `count`. Spaces are
|
## Aligns a string `s` with spaces, so that is of length `count`. Spaces are
|
||||||
## added before `s` resulting in right alignment. If ``s.len >= count``, no
|
## added before `s` resulting in right alignment. If ``s.len >= count``, no
|
||||||
## spaces are added and `s` is returned unchanged.
|
## spaces are added and `s` is returned unchanged.
|
||||||
if s.len < count:
|
if s.len < count:
|
||||||
result = newString(count)
|
result = newString(count)
|
||||||
var spaces = count - s.len
|
var spaces = count - s.len
|
||||||
for i in 0..spaces-1: result[i] = ' '
|
for i in 0..spaces-1: result[i] = ' '
|
||||||
|
|
@ -515,11 +515,11 @@ iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[
|
||||||
break
|
break
|
||||||
i = j
|
i = j
|
||||||
|
|
||||||
proc wordWrap*(s: string, maxLineWidth = 80,
|
proc wordWrap*(s: string, maxLineWidth = 80,
|
||||||
splitLongWords = true,
|
splitLongWords = true,
|
||||||
seps: set[char] = whitespace,
|
seps: set[char] = whitespace,
|
||||||
newLine = "\n"): string {.
|
newLine = "\n"): string {.
|
||||||
noSideEffect, rtl, extern: "nsuWordWrap".} =
|
noSideEffect, rtl, extern: "nsuWordWrap".} =
|
||||||
## word wraps `s`.
|
## word wraps `s`.
|
||||||
result = newStringOfCap(s.len + s.len shr 6)
|
result = newStringOfCap(s.len + s.len shr 6)
|
||||||
var SpaceLeft = maxLineWidth
|
var SpaceLeft = maxLineWidth
|
||||||
|
|
@ -529,7 +529,7 @@ proc wordWrap*(s: string, maxLineWidth = 80,
|
||||||
result.add(substr(word, 0, spaceLeft-1))
|
result.add(substr(word, 0, spaceLeft-1))
|
||||||
var w = spaceLeft+1
|
var w = spaceLeft+1
|
||||||
var wordLeft = len(word) - spaceLeft
|
var wordLeft = len(word) - spaceLeft
|
||||||
while wordLeft > 0:
|
while wordLeft > 0:
|
||||||
result.add(newLine)
|
result.add(newLine)
|
||||||
var L = min(maxLineWidth, wordLeft)
|
var L = min(maxLineWidth, wordLeft)
|
||||||
SpaceLeft = maxLineWidth - L
|
SpaceLeft = maxLineWidth - L
|
||||||
|
|
@ -545,7 +545,7 @@ proc wordWrap*(s: string, maxLineWidth = 80,
|
||||||
result.add(word)
|
result.add(word)
|
||||||
|
|
||||||
proc unindent*(s: string, eatAllIndent = false): string {.
|
proc unindent*(s: string, eatAllIndent = false): string {.
|
||||||
noSideEffect, rtl, extern: "nsuUnindent".} =
|
noSideEffect, rtl, extern: "nsuUnindent".} =
|
||||||
## unindents `s`.
|
## unindents `s`.
|
||||||
result = newStringOfCap(s.len)
|
result = newStringOfCap(s.len)
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
@ -593,17 +593,17 @@ proc endsWith*(s, suffix: string): bool {.noSideEffect,
|
||||||
if suffix[i] == '\0': return true
|
if suffix[i] == '\0': return true
|
||||||
|
|
||||||
proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect,
|
proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect,
|
||||||
inline.} =
|
inline.} =
|
||||||
## A shorthand for:
|
## A shorthand for:
|
||||||
##
|
##
|
||||||
## .. code-block:: nimrod
|
## .. code-block:: nimrod
|
||||||
## if dest.len > startLen: add(dest, sep)
|
## if dest.len > startLen: add(dest, sep)
|
||||||
##
|
##
|
||||||
## This is often useful for generating some code where the items need to
|
## This is often useful for generating some code where the items need to
|
||||||
## be *separated* by `sep`. `sep` is only added if `dest` is longer than
|
## be *separated* by `sep`. `sep` is only added if `dest` is longer than
|
||||||
## `startLen`. The following example creates a string describing
|
## `startLen`. The following example creates a string describing
|
||||||
## an array of integers:
|
## an array of integers:
|
||||||
##
|
##
|
||||||
## .. code-block:: nimrod
|
## .. code-block:: nimrod
|
||||||
## var arr = "["
|
## var arr = "["
|
||||||
## for x in items([2, 3, 5, 7, 11]):
|
## for x in items([2, 3, 5, 7, 11]):
|
||||||
|
|
@ -622,13 +622,13 @@ proc allCharsInSet*(s: string, theSet: TCharSet): bool =
|
||||||
# 345
|
# 345
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
proc abbrev(s: string, possibilities: openarray[string]): int =
|
proc abbrev(s: string, possibilities: openarray[string]): int =
|
||||||
## returns the index of the first item in `possibilities` if not
|
## returns the index of the first item in `possibilities` if not
|
||||||
## ambiguous; -1 if no item has been found; -2 if multiple items
|
## ambiguous; -1 if no item has been found; -2 if multiple items
|
||||||
## match.
|
## match.
|
||||||
result = -1 # none found
|
result = -1 # none found
|
||||||
for i in 0..possibilities.len-1:
|
for i in 0..possibilities.len-1:
|
||||||
if possibilities[i].startsWith(s):
|
if possibilities[i].startsWith(s):
|
||||||
if result >= 0: return -2 # ambiguous
|
if result >= 0: return -2 # ambiguous
|
||||||
result = i
|
result = i
|
||||||
|
|
||||||
|
|
@ -648,7 +648,7 @@ proc join*(a: openArray[string], sep: string): string {.
|
||||||
add(result, a[i])
|
add(result, a[i])
|
||||||
else:
|
else:
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
proc join*(a: openArray[string]): string {.
|
proc join*(a: openArray[string]): string {.
|
||||||
noSideEffect, rtl, extern: "nsuJoin".} =
|
noSideEffect, rtl, extern: "nsuJoin".} =
|
||||||
## concatenates all strings in `a`.
|
## concatenates all strings in `a`.
|
||||||
|
|
@ -706,7 +706,7 @@ proc find*(s: string, chars: set[char], start: int = 0): int {.noSideEffect,
|
||||||
## none of the characters in `chars`, -1 is returned.
|
## none of the characters in `chars`, -1 is returned.
|
||||||
for i in start..s.len-1:
|
for i in start..s.len-1:
|
||||||
if s[i] in chars: return i
|
if s[i] in chars: return i
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
proc quoteIfContainsWhite*(s: string): string =
|
proc quoteIfContainsWhite*(s: string): string =
|
||||||
## returns ``'"' & s & '"'`` if `s` contains a space and does not
|
## returns ``'"' & s & '"'`` if `s` contains a space and does not
|
||||||
|
|
@ -775,10 +775,10 @@ proc ParseOctInt*(s: string): int {.noSideEffect,
|
||||||
## Underscores within `s` are ignored.
|
## Underscores within `s` are ignored.
|
||||||
var i = 0
|
var i = 0
|
||||||
if s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2)
|
if s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2)
|
||||||
while true:
|
while true:
|
||||||
case s[i]
|
case s[i]
|
||||||
of '_': inc(i)
|
of '_': inc(i)
|
||||||
of '0'..'7':
|
of '0'..'7':
|
||||||
result = result shl 3 or (ord(s[i]) - ord('0'))
|
result = result shl 3 or (ord(s[i]) - ord('0'))
|
||||||
inc(i)
|
inc(i)
|
||||||
of '\0': break
|
of '\0': break
|
||||||
|
|
@ -813,17 +813,17 @@ proc toBin*(x: BiggestInt, len: int): string {.noSideEffect,
|
||||||
mask = mask shl 1
|
mask = mask shl 1
|
||||||
|
|
||||||
proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect,
|
proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect,
|
||||||
rtl, extern: "nsuInsertSep".} =
|
rtl, extern: "nsuInsertSep".} =
|
||||||
## inserts the separator `sep` after `digits` digits from right to left.
|
## inserts the separator `sep` after `digits` digits from right to left.
|
||||||
## Even though the algorithm works with any string `s`, it is only useful
|
## Even though the algorithm works with any string `s`, it is only useful
|
||||||
## if `s` contains a number.
|
## if `s` contains a number.
|
||||||
## Example: ``insertSep("1000000") == "1_000_000"``
|
## Example: ``insertSep("1000000") == "1_000_000"``
|
||||||
var L = (s.len-1) div digits + s.len
|
var L = (s.len-1) div digits + s.len
|
||||||
result = newString(L)
|
result = newString(L)
|
||||||
var j = 0
|
var j = 0
|
||||||
dec(L)
|
dec(L)
|
||||||
for i in countdown(len(s)-1, 0):
|
for i in countdown(len(s)-1, 0):
|
||||||
if j == digits:
|
if j == digits:
|
||||||
result[L] = sep
|
result[L] = sep
|
||||||
dec(L)
|
dec(L)
|
||||||
j = 0
|
j = 0
|
||||||
|
|
@ -854,9 +854,9 @@ proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
|
||||||
of '\"': add(result, "\\\"")
|
of '\"': add(result, "\\\"")
|
||||||
else: add(result, c)
|
else: add(result, c)
|
||||||
add(result, suffix)
|
add(result, suffix)
|
||||||
|
|
||||||
proc validIdentifier*(s: string): bool {.noSideEffect,
|
proc validIdentifier*(s: string): bool {.noSideEffect,
|
||||||
rtl, extern: "nsuValidIdentifier".} =
|
rtl, extern: "nsuValidIdentifier".} =
|
||||||
## returns true if `s` is a valid identifier. A valid identifier starts
|
## returns true if `s` is a valid identifier. A valid identifier starts
|
||||||
## with a character of the set `IdentStartChars` and is followed by any
|
## with a character of the set `IdentStartChars` and is followed by any
|
||||||
## number of characters of the set `IdentChars`.
|
## number of characters of the set `IdentChars`.
|
||||||
|
|
@ -864,7 +864,7 @@ proc validIdentifier*(s: string): bool {.noSideEffect,
|
||||||
for i in 1..s.len-1:
|
for i in 1..s.len-1:
|
||||||
if s[i] notin IdentChars: return false
|
if s[i] notin IdentChars: return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc editDistance*(a, b: string): int {.noSideEffect,
|
proc editDistance*(a, b: string): int {.noSideEffect,
|
||||||
rtl, extern: "nsuEditDistance".} =
|
rtl, extern: "nsuEditDistance".} =
|
||||||
## returns the edit distance between `a` and `b`. This uses the Levenshtein
|
## returns the edit distance between `a` and `b`. This uses the Levenshtein
|
||||||
|
|
@ -967,17 +967,17 @@ type
|
||||||
|
|
||||||
proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
|
proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
|
||||||
precision = 16): string {.noSideEffect,
|
precision = 16): string {.noSideEffect,
|
||||||
rtl, extern: "nsu$1".} =
|
rtl, extern: "nsu$1".} =
|
||||||
## converts a floating point value `f` to a string.
|
## converts a floating point value `f` to a string.
|
||||||
##
|
##
|
||||||
## If ``format == ffDecimal`` then precision is the number of digits to
|
## If ``format == ffDecimal`` then precision is the number of digits to
|
||||||
## be printed after the decimal point.
|
## be printed after the decimal point.
|
||||||
## If ``format == ffScientific`` then precision is the maximum number
|
## If ``format == ffScientific`` then precision is the maximum number
|
||||||
## of significant digits to be printed.
|
## of significant digits to be printed.
|
||||||
## `precision`'s default value is the maximum number of meaningful digits
|
## `precision`'s default value is the maximum number of meaningful digits
|
||||||
## after the decimal point for Nimrod's ``biggestFloat`` type.
|
## after the decimal point for Nimrod's ``biggestFloat`` type.
|
||||||
const floatFormatToChar: array[TFloatFormat, char] = ['g', 'f', 'e']
|
const floatFormatToChar: array[TFloatFormat, char] = ['g', 'f', 'e']
|
||||||
var
|
var
|
||||||
frmtstr: array[0..5, char]
|
frmtstr: array[0..5, char]
|
||||||
buf: array[0..80, char]
|
buf: array[0..80, char]
|
||||||
frmtstr[0] = '%'
|
frmtstr[0] = '%'
|
||||||
|
|
@ -988,7 +988,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
|
||||||
frmtstr[4] = floatFormatToChar[format]
|
frmtstr[4] = floatFormatToChar[format]
|
||||||
frmtstr[5] = '\0'
|
frmtstr[5] = '\0'
|
||||||
c_sprintf(buf, frmtstr, precision, f)
|
c_sprintf(buf, frmtstr, precision, f)
|
||||||
else:
|
else:
|
||||||
frmtstr[2] = floatFormatToChar[format]
|
frmtstr[2] = floatFormatToChar[format]
|
||||||
frmtstr[3] = '\0'
|
frmtstr[3] = '\0'
|
||||||
c_sprintf(buf, frmtstr, f)
|
c_sprintf(buf, frmtstr, f)
|
||||||
|
|
@ -996,15 +996,15 @@ proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
|
||||||
|
|
||||||
proc formatFloat*(f: float, format: TFloatFormat = ffDefault,
|
proc formatFloat*(f: float, format: TFloatFormat = ffDefault,
|
||||||
precision = 16): string {.noSideEffect,
|
precision = 16): string {.noSideEffect,
|
||||||
rtl, extern: "nsu$1".} =
|
rtl, extern: "nsu$1".} =
|
||||||
## converts a floating point value `f` to a string.
|
## converts a floating point value `f` to a string.
|
||||||
##
|
##
|
||||||
## If ``format == ffDecimal`` then precision is the number of digits to
|
## If ``format == ffDecimal`` then precision is the number of digits to
|
||||||
## be printed after the decimal point.
|
## be printed after the decimal point.
|
||||||
## If ``format == ffScientific`` then precision is the maximum number
|
## If ``format == ffScientific`` then precision is the maximum number
|
||||||
## of significant digits to be printed.
|
## of significant digits to be printed.
|
||||||
## `precision`'s default value is the maximum number of meaningful digits
|
## `precision`'s default value is the maximum number of meaningful digits
|
||||||
## after the decimal point for Nimrod's ``float`` type.
|
## after the decimal point for Nimrod's ``float`` type.
|
||||||
result = formatBiggestFloat(f, format, precision)
|
result = formatBiggestFloat(f, format, precision)
|
||||||
|
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
@ -1017,6 +1017,6 @@ when isMainModule:
|
||||||
it goes""", 10, false)
|
it goes""", 10, false)
|
||||||
assert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
|
assert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
|
||||||
assert formatBiggestFloat(0.00000000001, ffScientific, 1) == "1.0e-11"
|
assert formatBiggestFloat(0.00000000001, ffScientific, 1) == "1.0e-11"
|
||||||
|
|
||||||
assert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
|
assert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue