Some documentation added to strutils (#9379)

* wip documentation strutils

* some runnableExamples in strutils

* assert -> doAssert

* corrected doc for abbrev; some more runnable examples

* runnableExamples for join

* fix c&p error

* corrections
This commit is contained in:
eqperes
2018-10-16 17:30:38 +02:00
committed by Andreas Rumpf
parent 480d228603
commit afd9d8dd8d

View File

@@ -75,6 +75,10 @@ proc isAlphaAscii*(c: char): bool {.noSideEffect, procvar,
## Checks whether or not `c` is alphabetical.
##
## This checks a-z, A-Z ASCII characters only.
runnableExamples:
doAssert isAlphaAscii('e') == true
doAssert isAlphaAscii('E') == true
doAssert isAlphaAscii('8') == false
return c in Letters
proc isAlphaNumeric*(c: char): bool {.noSideEffect, procvar,
@@ -82,6 +86,10 @@ proc isAlphaNumeric*(c: char): bool {.noSideEffect, procvar,
## Checks whether or not `c` is alphanumeric.
##
## This checks a-z, A-Z, 0-9 ASCII characters only.
runnableExamples:
doAssert isAlphaNumeric('n') == true
doAssert isAlphaNumeric('8') == true
doAssert isAlphaNumeric(' ') == false
return c in Letters+Digits
proc isDigit*(c: char): bool {.noSideEffect, procvar,
@@ -89,11 +97,17 @@ proc isDigit*(c: char): bool {.noSideEffect, procvar,
## Checks whether or not `c` is a number.
##
## This checks 0-9 ASCII characters only.
runnableExamples:
doAssert isDigit('n') == false
doAssert isDigit('8') == true
return c in Digits
proc isSpaceAscii*(c: char): bool {.noSideEffect, procvar,
rtl, extern: "nsuIsSpaceAsciiChar".} =
## Checks whether or not `c` is a whitespace character.
runnableExamples:
doAssert isSpaceAscii('n') == false
doAssert isSpaceAscii(' ') == true
return c in Whitespace
proc isLowerAscii*(c: char): bool {.noSideEffect, procvar,
@@ -101,6 +115,10 @@ proc isLowerAscii*(c: char): bool {.noSideEffect, procvar,
## Checks whether or not `c` is a lower case character.
##
## This checks ASCII characters only.
runnableExamples:
doAssert isLowerAscii('e') == true
doAssert isLowerAscii('E') == false
doAssert isLowerAscii('7') == false
return c in {'a'..'z'}
proc isUpperAscii*(c: char): bool {.noSideEffect, procvar,
@@ -108,6 +126,10 @@ proc isUpperAscii*(c: char): bool {.noSideEffect, procvar,
## Checks whether or not `c` is an upper case character.
##
## This checks ASCII characters only.
runnableExamples:
doAssert isUpperAscii('e') == false
doAssert isUpperAscii('E') == true
doAssert isUpperAscii('7') == false
return c in {'A'..'Z'}
template isImpl(call) =
@@ -125,6 +147,10 @@ proc isAlphaAscii*(s: string): bool {.noSideEffect, procvar,
## Returns true if all characters in `s` are
## alphabetic and there is at least one character
## in `s`.
runnableExamples:
doAssert isAlphaAscii("fooBar") == true
doAssert isAlphaAscii("fooBar1") == false
doAssert isAlphaAscii("foo Bar") == false
isImpl isAlphaAscii
proc isAlphaNumeric*(s: string): bool {.noSideEffect, procvar,
@@ -136,6 +162,10 @@ proc isAlphaNumeric*(s: string): bool {.noSideEffect, procvar,
## Returns true if all characters in `s` are
## alpanumeric and there is at least one character
## in `s`.
runnableExamples:
doAssert isAlphaNumeric("fooBar") == true
doAssert isAlphaNumeric("fooBar") == true
doAssert isAlphaNumeric("foo Bar") == false
isImpl isAlphaNumeric
proc isDigit*(s: string): bool {.noSideEffect, procvar,
@@ -147,6 +177,9 @@ proc isDigit*(s: string): bool {.noSideEffect, procvar,
## Returns true if all characters in `s` are
## numeric and there is at least one character
## in `s`.
runnableExamples:
doAssert isDigit("1908") == true
doAssert isDigit("fooBar1") == false
isImpl isDigit
proc isSpaceAscii*(s: string): bool {.noSideEffect, procvar,
@@ -156,6 +189,9 @@ proc isSpaceAscii*(s: string): bool {.noSideEffect, procvar,
##
## Returns true if all characters in `s` are whitespace
## characters and there is at least one character in `s`.
runnableExamples:
doAssert isSpaceAscii(" ") == true
doAssert isSpaceAscii("") == false
isImpl isSpaceAscii
template isCaseImpl(s, charProc, skipNonAlpha) =
@@ -188,6 +224,10 @@ proc isLowerAscii*(s: string, skipNonAlpha: bool): bool {.
##
## For either value of ``skipNonAlpha``, returns false if ``s`` is
## an empty string.
runnableExamples:
doAssert isLowerAscii("1foobar", false) == false
doAssert isLowerAscii("1foobar", true) == true
doAssert isLowerAscii("1fooBar", true) == false
isCaseImpl(s, isLowerAscii, skipNonAlpha)
proc isUpperAscii*(s: string, skipNonAlpha: bool): bool {.
@@ -205,15 +245,22 @@ proc isUpperAscii*(s: string, skipNonAlpha: bool): bool {.
##
## For either value of ``skipNonAlpha``, returns false if ``s`` is
## an empty string.
runnableExamples:
doAssert isUpperAscii("1FOO", false) == false
doAssert isUpperAscii("1FOO", true) == true
doAssert isUpperAscii("1Foo", true) == false
isCaseImpl(s, isUpperAscii, skipNonAlpha)
proc toLowerAscii*(c: char): char {.noSideEffect, procvar,
rtl, extern: "nsuToLowerAsciiChar".} =
## Converts `c` into lower case.
## Returns the lower case version of ``c``.
##
## This works only for the letters ``A-Z``. See `unicode.toLower
## <unicode.html#toLower>`_ for a version that works for any Unicode
## character.
runnableExamples:
doAssert toLowerAscii('A') == 'a'
doAssert toLowerAscii('e') == 'e'
if c in {'A'..'Z'}:
result = chr(ord(c) + (ord('a') - ord('A')))
else:
@@ -231,6 +278,8 @@ proc toLowerAscii*(s: string): string {.noSideEffect, procvar,
## This works only for the letters ``A-Z``. See `unicode.toLower
## <unicode.html#toLower>`_ for a version that works for any Unicode
## character.
runnableExamples:
doAssert toLowerAscii("FooBar!") == "foobar!"
toImpl toLowerAscii
proc toUpperAscii*(c: char): char {.noSideEffect, procvar,
@@ -240,6 +289,9 @@ proc toUpperAscii*(c: char): char {.noSideEffect, procvar,
## This works only for the letters ``A-Z``. See `unicode.toUpper
## <unicode.html#toUpper>`_ for a version that works for any Unicode
## character.
runnableExamples:
doAssert toUpperAscii('a') == 'A'
doAssert toUpperAscii('E') == 'E'
if c in {'a'..'z'}:
result = chr(ord(c) - (ord('a') - ord('A')))
else:
@@ -252,6 +304,8 @@ proc toUpperAscii*(s: string): string {.noSideEffect, procvar,
## This works only for the letters ``A-Z``. See `unicode.toUpper
## <unicode.html#toUpper>`_ for a version that works for any Unicode
## character.
runnableExamples:
doAssert toUpperAscii("FooBar!") == "FOOBAR!"
toImpl toUpperAscii
proc capitalizeAscii*(s: string): string {.noSideEffect, procvar,
@@ -259,6 +313,9 @@ proc capitalizeAscii*(s: string): string {.noSideEffect, procvar,
## Converts the first character of `s` into upper case.
##
## This works only for the letters ``A-Z``.
runnableExamples:
doAssert capitalizeAscii("foo") == "Foo"
doAssert capitalizeAscii("-bar") == "-bar"
if s.len == 0: result = ""
else: result = toUpperAscii(s[0]) & substr(s, 1)
@@ -268,6 +325,9 @@ proc normalize*(s: string): string {.noSideEffect, procvar,
##
## That means to convert it to lower case and remove any '_'. This
## should NOT be used to normalize Nim identifier names.
runnableExamples:
doAssert normalize("Foo_bar") == "foobar"
doAssert normalize("Foo Bar") == "foo bar"
result = newString(s.len)
var j = 0
for i in 0..len(s) - 1:
@@ -286,6 +346,10 @@ proc cmpIgnoreCase*(a, b: string): int {.noSideEffect,
## | 0 iff a == b
## | < 0 iff a < b
## | > 0 iff a > b
runnableExamples:
doAssert cmpIgnoreCase("FooBar", "foobar") == 0
doAssert cmpIgnoreCase("bar", "Foo") < 0
doAssert cmpIgnoreCase("Foo5", "foo4") > 0
var i = 0
var m = min(a.len, b.len)
while i < m:
@@ -307,6 +371,9 @@ proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect,
## | 0 iff a == b
## | < 0 iff a < b
## | > 0 iff a > b
runnableExamples:
doAssert cmpIgnoreStyle("foo_bar", "FooBar") == 0
doAssert cmpIgnoreStyle("foo_bar_5", "FooBar4") > 0
var i = 0
var j = 0
while true:
@@ -352,6 +419,8 @@ proc toOctal*(c: char): string {.noSideEffect, rtl, extern: "nsuToOctal".} =
##
## The resulting string may not have a leading zero. Its length is always
## exactly 3.
runnableExamples:
doAssert toOctal('!') == "041"
result = newString(3)
var val = ord(c)
for i in countdown(2, 0):
@@ -695,6 +764,8 @@ proc countLines*(s: string): int {.noSideEffect,
##
## In this context, a line is any string seperated by a newline combination.
## A line can be an empty string.
runnableExamples:
doAssert countLines("First line\l and second line.") == 2
result = 1
var i = 0
while i < s.len:
@@ -821,6 +892,9 @@ proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect,
##
## The resulting string will be exactly `len` characters long. No prefix like
## ``0x`` is generated. `x` is treated as an unsigned value.
runnableExamples:
doAssert toHex(1984, 6) == "0007C0"
doAssert toHex(1984, 2) == "C0"
const
HexChars = "0123456789ABCDEF"
var
@@ -834,6 +908,8 @@ proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect,
proc toHex*[T: SomeInteger](x: T): string =
## Shortcut for ``toHex(x, T.sizeOf * 2)``
runnableExamples:
doAssert toHex(1984) == "00000000000007C0"
toHex(BiggestInt(x), T.sizeOf * 2)
proc toHex*(s: string): string {.noSideEffect, rtl.} =
@@ -855,6 +931,9 @@ proc intToStr*(x: int, minchars: Positive = 1): string {.noSideEffect,
##
## The resulting string will be minimally `minchars` characters long. This is
## achieved by adding leading zeros.
runnableExamples:
doAssert intToStr(1984) == "1984"
doAssert intToStr(1984, 6) == "001984"
result = $abs(x)
for i in 1 .. minchars - len(result):
result = '0' & result
@@ -866,6 +945,8 @@ proc parseInt*(s: string): int {.noSideEffect, procvar,
## Parses a decimal integer value contained in `s`.
##
## If `s` is not a valid integer, `ValueError` is raised.
runnableExamples:
doAssert parseInt("-0042") == -42
let L = parseutils.parseInt(s, result, 0)
if L != s.len or L == 0:
raise newException(ValueError, "invalid integer: " & s)
@@ -902,6 +983,9 @@ proc parseFloat*(s: string): float {.noSideEffect, procvar,
## Parses a decimal floating point value contained in `s`. If `s` is not
## a valid floating point number, `ValueError` is raised. ``NAN``,
## ``INF``, ``-INF`` are also supported (case insensitive comparison).
runnableExamples:
doAssert parseFloat("3.14") == 3.14
doAssert parseFloat("inf") == 1.0/0
let L = parseutils.parseFloat(s, result, 0)
if L != s.len or L == 0:
raise newException(ValueError, "invalid float: " & s)
@@ -1163,6 +1247,8 @@ proc indent*(s: string, count: Natural, padding: string = " "): string
## Indents each line in ``s`` by ``count`` amount of ``padding``.
##
## **Note:** This does not preserve the new line characters used in ``s``.
runnableExamples:
doAssert indent("First line\c\l and second line.", 2) == " First line\l and second line."
result = ""
var i = 0
for line in s.splitLines():
@@ -1178,6 +1264,8 @@ proc unindent*(s: string, count: Natural, padding: string = " "): string
## Unindents each line in ``s`` by ``count`` amount of ``padding``.
##
## **Note:** This does not preserve the new line characters used in ``s``.
runnableExamples:
doAssert unindent(" First line\l and second line", 3) == "First line\land second line"
result = ""
var i = 0
for line in s.splitLines():
@@ -1272,14 +1360,22 @@ proc addSep*(dest: var string, sep = ", ", startLen: Natural = 0)
proc allCharsInSet*(s: string, theSet: set[char]): bool =
## Returns true iff each character of `s` is in the set `theSet`.
runnableExamples:
doAssert allCharsInSet("aeea", {'a', 'e'}) == true
doAssert allCharsInSet("", {'a', 'e'}) == true
for c in items(s):
if c notin theSet: return false
return true
proc abbrev*(s: string, possibilities: openArray[string]): int =
## Returns the index of the first item in `possibilities` if not ambiguous.
## Returns the index of the first item in ``possibilities`` which starts with ``s``, if not ambiguous.
##
## Returns -1 if no item has been found and -2 if multiple items match.
runnableExamples:
doAssert abbrev("fac", ["college", "faculty", "industry"]) == 1
doAssert abbrev("foo", ["college", "faculty", "industry"]) == -1 # Not found
doAssert abbrev("fac", ["college", "faculty", "faculties"]) == -2 # Ambiguous
doAssert abbrev("college", ["college", "colleges", "industry"]) == 0
result = -1 # none found
for i in 0..possibilities.len-1:
if possibilities[i].startsWith(s):
@@ -1294,6 +1390,8 @@ proc abbrev*(s: string, possibilities: openArray[string]): int =
proc join*(a: openArray[string], sep: string = ""): string {.
noSideEffect, rtl, extern: "nsuJoinSep".} =
## Concatenates all strings in `a` separating them with `sep`.
runnableExamples:
doAssert join(["A", "B", "Conclusion"], " -> ") == "A -> B -> Conclusion"
if len(a) > 0:
var L = sep.len * (a.len-1)
for i in 0..high(a): inc(L, a[i].len)
@@ -1309,6 +1407,8 @@ proc join*[T: not string](a: openArray[T], sep: string = ""): string {.
noSideEffect, rtl.} =
## Converts all elements in `a` to strings using `$` and concatenates them
## with `sep`.
runnableExamples:
doAssert join([1, 2, 3], " -> ") == "1 -> 2 -> 3"
result = ""
for i, x in a:
if i > 0: