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

(cherry picked from commit afd9d8dd8d)
This commit is contained in:
eqperes
2018-10-16 17:30:38 +02:00
committed by narimiran
parent 6ad4022b5e
commit 2e2a2754a4

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) =
@@ -124,6 +146,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,
@@ -134,6 +160,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,
@@ -144,6 +174,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,
@@ -152,6 +185,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) =
@@ -183,6 +219,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 =
@@ -199,15 +239,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:
@@ -225,6 +272,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,
@@ -234,6 +283,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:
@@ -246,6 +298,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,
@@ -253,6 +307,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)
@@ -262,6 +319,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:
@@ -280,6 +340,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:
@@ -301,6 +365,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:
@@ -344,6 +411,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):
@@ -687,6 +756,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:
@@ -813,6 +884,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
@@ -826,6 +900,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.} =
@@ -847,6 +923,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
@@ -858,6 +937,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)
@@ -894,6 +975,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)
@@ -1155,6 +1239,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():
@@ -1170,6 +1256,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():
@@ -1264,14 +1352,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):
@@ -1286,6 +1382,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)
@@ -1301,6 +1399,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: