W3cubDocs

/Nim

Module strutils

This module contains various string utility routines. See the module re for regular expression support. See the module pegs for PEG support. This module is available for the JavaScript target.

Imports

parseutils, math, algorithm

Types

CharSet = set[char]
FloatFormatMode = enum
  ffDefault,                  ## use the shorter floating point notation
  ffDecimal,                  ## use decimal floating point notation
  ffScientific                ## use scientific notation (using ``e`` character)
the different modes of floating point formating
BinaryPrefixMode = enum
  bpIEC, bpColloquial
the different names for binary prefixes

Consts

Whitespace = {' ', '\x09', '\x0B', '\x0D', '\x0A', '\x0C'}
All the characters that count as whitespace.
Letters = {'A'..'Z', 'a'..'z'}
the set of letters
Digits = {'0'..'9'}
the set of digits
HexDigits = {'0'..'9', 'A'..'F', 'a'..'f'}
the set of hexadecimal digits
IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'}
the set of characters an identifier can consist of
IdentStartChars = {'a'..'z', 'A'..'Z', '_'}
the set of characters an identifier can start with
NewLines = {'\x0D', '\x0A'}
the set of characters a newline terminator can start with
AllChars = {'\0'..'\xFF'}

A set with all the possible characters.

Not very useful by its own, you can use it to create inverted sets to make the find() proc find invalid characters in strings. Example:

let invalid = AllChars - Digits
doAssert "01234".find(invalid) == -1
doAssert "01A34".find(invalid) == 2

Procs

proc isAlphaAscii(c: char): bool {.noSideEffect, procvar, gcsafe,
                               extern: "nsuIsAlphaAsciiChar", raises: [], tags: [].}

Checks whether or not c is alphabetical.

This checks a-z, A-Z ASCII characters only.

proc isAlphaNumeric(c: char): bool {.noSideEffect, procvar, gcsafe,
                                 extern: "nsuIsAlphaNumericChar", raises: [],
                                 tags: [].}

Checks whether or not c is alphanumeric.

This checks a-z, A-Z, 0-9 ASCII characters only.

proc isDigit(c: char): bool {.noSideEffect, procvar, gcsafe, extern: "nsuIsDigitChar",
                          raises: [], tags: [].}

Checks whether or not c is a number.

This checks 0-9 ASCII characters only.

proc isSpaceAscii(c: char): bool {.noSideEffect, procvar, gcsafe,
                               extern: "nsuIsSpaceAsciiChar", raises: [], tags: [].}
Checks whether or not c is a whitespace character.
proc isLowerAscii(c: char): bool {.noSideEffect, procvar, gcsafe,
                               extern: "nsuIsLowerAsciiChar", raises: [], tags: [].}

Checks whether or not c is a lower case character.

This checks ASCII characters only.

proc isUpperAscii(c: char): bool {.noSideEffect, procvar, gcsafe,
                               extern: "nsuIsUpperAsciiChar", raises: [], tags: [].}

Checks whether or not c is an upper case character.

This checks ASCII characters only.

proc isAlphaAscii(s: string): bool {.noSideEffect, procvar, gcsafe,
                                 extern: "nsuIsAlphaAsciiStr", raises: [], tags: [].}

Checks whether or not s is alphabetical.

This checks a-z, A-Z ASCII characters only. Returns true if all characters in s are alphabetic and there is at least one character in s.

proc isAlphaNumeric(s: string): bool {.noSideEffect, procvar, gcsafe,
                                   extern: "nsuIsAlphaNumericStr", raises: [],
                                   tags: [].}

Checks whether or not s is alphanumeric.

This checks a-z, A-Z, 0-9 ASCII characters only. Returns true if all characters in s are alpanumeric and there is at least one character in s.

proc isDigit(s: string): bool {.noSideEffect, procvar, gcsafe, extern: "nsuIsDigitStr",
                            raises: [], tags: [].}

Checks whether or not s is a numeric value.

This checks 0-9 ASCII characters only. Returns true if all characters in s are numeric and there is at least one character in s.

proc isSpaceAscii(s: string): bool {.noSideEffect, procvar, gcsafe,
                                 extern: "nsuIsSpaceAsciiStr", raises: [], tags: [].}

Checks whether or not s is completely whitespace.

Returns true if all characters in s are whitespace characters and there is at least one character in s.

proc isLowerAscii(s: string): bool {.noSideEffect, procvar, gcsafe,
                                 extern: "nsuIsLowerAsciiStr", raises: [], tags: [].}

Checks whether or not s contains all lower case characters.

This checks ASCII characters only. Returns true if all characters in s are lower case and there is at least one character in s.

proc isUpperAscii(s: string): bool {.noSideEffect, procvar, gcsafe,
                                 extern: "nsuIsUpperAsciiStr", raises: [], tags: [].}

Checks whether or not s contains all upper case characters.

This checks ASCII characters only. Returns true if all characters in s are upper case and there is at least one character in s.

proc toLowerAscii(c: char): char {.noSideEffect, procvar, gcsafe,
                               extern: "nsuToLowerAsciiChar", raises: [], tags: [].}

Converts c into lower case.

This works only for the letters A-Z. See unicode.toLower for a version that works for any Unicode character.

proc toLowerAscii(s: string): string {.noSideEffect, procvar, gcsafe,
                                   extern: "nsuToLowerAsciiStr", raises: [],
                                   tags: [].}

Converts s into lower case.

This works only for the letters A-Z. See unicode.toLower for a version that works for any Unicode character.

proc toUpperAscii(c: char): char {.noSideEffect, procvar, gcsafe,
                               extern: "nsuToUpperAsciiChar", raises: [], tags: [].}

Converts c into upper case.

This works only for the letters A-Z. See unicode.toUpper for a version that works for any Unicode character.

proc toUpperAscii(s: string): string {.noSideEffect, procvar, gcsafe,
                                   extern: "nsuToUpperAsciiStr", raises: [],
                                   tags: [].}

Converts s into upper case.

This works only for the letters A-Z. See unicode.toUpper for a version that works for any Unicode character.

proc capitalizeAscii(s: string): string {.noSideEffect, procvar, gcsafe,
                                      extern: "nsuCapitalizeAscii", raises: [],
                                      tags: [].}

Converts the first character of s into upper case.

This works only for the letters A-Z.

proc isSpace(c: char): bool {.noSideEffect, procvar, gcsafe, deprecated,
                          extern: "nsuIsSpaceChar", raises: [], tags: [].}

Checks whether or not c is a whitespace character.

Deprecated since version 0.15.0: use isSpaceAscii instead.

proc isLower(c: char): bool {.noSideEffect, procvar, gcsafe, deprecated,
                          extern: "nsuIsLowerChar", raises: [], tags: [].}

Checks whether or not c is a lower case character.

This checks ASCII characters only.

Deprecated since version 0.15.0: use isLowerAscii instead.

proc isUpper(c: char): bool {.noSideEffect, procvar, gcsafe, deprecated,
                          extern: "nsuIsUpperChar", raises: [], tags: [].}

Checks whether or not c is an upper case character.

This checks ASCII characters only.

Deprecated since version 0.15.0: use isUpperAscii instead.

proc isAlpha(c: char): bool {.noSideEffect, procvar, gcsafe, deprecated,
                          extern: "nsuIsAlphaChar", raises: [], tags: [].}

Checks whether or not c is alphabetical.

This checks a-z, A-Z ASCII characters only.

Deprecated since version 0.15.0: use isAlphaAscii instead.

proc isAlpha(s: string): bool {.noSideEffect, procvar, gcsafe, deprecated,
                            extern: "nsuIsAlphaStr", raises: [], tags: [].}

Checks whether or not s is alphabetical.

This checks a-z, A-Z ASCII characters only. Returns true if all characters in s are alphabetic and there is at least one character in s.

Deprecated since version 0.15.0: use isAlphaAscii instead.

proc isSpace(s: string): bool {.noSideEffect, procvar, gcsafe, deprecated,
                            extern: "nsuIsSpaceStr", raises: [], tags: [].}

Checks whether or not s is completely whitespace.

Returns true if all characters in s are whitespace characters and there is at least one character in s.

Deprecated since version 0.15.0: use isSpaceAscii instead.

proc isLower(s: string): bool {.noSideEffect, procvar, gcsafe, deprecated,
                            extern: "nsuIsLowerStr", raises: [], tags: [].}

Checks whether or not s contains all lower case characters.

This checks ASCII characters only. Returns true if all characters in s are lower case and there is at least one character in s.

Deprecated since version 0.15.0: use isLowerAscii instead.

proc isUpper(s: string): bool {.noSideEffect, procvar, gcsafe, deprecated,
                            extern: "nsuIsUpperStr", raises: [], tags: [].}

Checks whether or not s contains all upper case characters.

This checks ASCII characters only. Returns true if all characters in s are upper case and there is at least one character in s.

Deprecated since version 0.15.0: use isUpperAscii instead.

proc toLower(c: char): char {.noSideEffect, procvar, gcsafe, deprecated,
                          extern: "nsuToLowerChar", raises: [], tags: [].}

Converts c into lower case.

This works only for the letters A-Z. See unicode.toLower for a version that works for any Unicode character.

Deprecated since version 0.15.0: use toLowerAscii instead.

proc toLower(s: string): string {.noSideEffect, procvar, gcsafe, deprecated,
                              extern: "nsuToLowerStr", raises: [], tags: [].}

Converts s into lower case.

This works only for the letters A-Z. See unicode.toLower for a version that works for any Unicode character.

Deprecated since version 0.15.0: use toLowerAscii instead.

proc toUpper(c: char): char {.noSideEffect, procvar, gcsafe, deprecated,
                          extern: "nsuToUpperChar", raises: [], tags: [].}

Converts c into upper case.

This works only for the letters A-Z. See unicode.toUpper for a version that works for any Unicode character.

Deprecated since version 0.15.0: use toUpperAscii instead.

proc toUpper(s: string): string {.noSideEffect, procvar, gcsafe, deprecated,
                              extern: "nsuToUpperStr", raises: [], tags: [].}

Converts s into upper case.

This works only for the letters A-Z. See unicode.toUpper for a version that works for any Unicode character.

Deprecated since version 0.15.0: use toUpperAscii instead.

proc capitalize(s: string): string {.noSideEffect, procvar, gcsafe, deprecated,
                                 extern: "nsuCapitalize", raises: [], tags: [].}

Converts the first character of s into upper case.

This works only for the letters A-Z.

Deprecated since version 0.15.0: use capitalizeAscii instead.

proc normalize(s: string): string {.noSideEffect, procvar, gcsafe,
                                extern: "nsuNormalize", raises: [], tags: [].}

Normalizes the string s.

That means to convert it to lower case and remove any '_'. This is needed for Nim identifiers for example.

proc cmpIgnoreCase(a, b: string): int {.noSideEffect, gcsafe,
                                   extern: "nsuCmpIgnoreCase", procvar, raises: [],
                                   tags: [].}
Compares two strings in a case insensitive manner. Returns:

0 iff a == b
< 0 iff a < b
> 0 iff a > b

proc cmpIgnoreStyle(a, b: string): int {.noSideEffect, gcsafe,
                                    extern: "nsuCmpIgnoreStyle", procvar,
                                    raises: [], tags: [].}
Compares two strings normalized (i.e. case and underscores do not matter). Returns:

0 iff a == b
< 0 iff a < b
> 0 iff a > b

proc strip(s: string; leading = true; trailing = true; chars: set[char] = Whitespace): string {.
    noSideEffect, gcsafe, extern: "nsuStrip", raises: [], tags: [].}

Strips chars from s and returns the resulting string.

If leading is true, leading chars are stripped. If trailing is true, trailing chars are stripped.

proc toOctal(c: char): string {.noSideEffect, gcsafe, extern: "nsuToOctal", raises: [],
                            tags: [].}

Converts a character c to its octal representation.

The resulting string may not have a leading zero. Its length is always exactly 3.

proc isNilOrEmpty(s: string): bool {.noSideEffect, procvar, gcsafe,
                                 extern: "nsuIsNilOrEmpty", raises: [], tags: [].}
Checks if s is nil or empty.
proc isNilOrWhitespace(s: string): bool {.noSideEffect, procvar, gcsafe,
                                      extern: "nsuIsNilOrWhitespace", raises: [],
                                      tags: [].}
Checks if s is nil or consists entirely of whitespace characters.
proc splitWhitespace(s: string): seq[string] {.noSideEffect, gcsafe,
    extern: "nsuSplitWhitespace", raises: [], tags: [].}
The same as the splitWhitespace iterator, but is a proc that returns a sequence of substrings.
proc splitLines(s: string): seq[string] {.noSideEffect, gcsafe,
                                      extern: "nsuSplitLines", raises: [], tags: [].}
The same as the splitLines iterator, but is a proc that returns a sequence of substrings.
proc countLines(s: string): int {.noSideEffect, gcsafe, extern: "nsuCountLines",
                              raises: [], tags: [].}

Returns the number of lines in the string s.

This is the same as len(splitLines(s)), but much more efficient because it doesn't modify the string creating temporal objects. Every character literal newline combination (CR, LF, CR-LF) is supported.

In this context, a line is any string seperated by a newline combination. A line can be an empty string.

proc split(s: string; seps: set[char] = Whitespace; maxsplit: int = - 1): seq[string] {.
    noSideEffect, gcsafe, extern: "nsuSplitCharSet", raises: [], tags: [].}
The same as the split iterator, but is a proc that returns a sequence of substrings.
proc split(s: string; sep: char; maxsplit: int = - 1): seq[string] {.noSideEffect,
    gcsafe, extern: "nsuSplitChar", raises: [], tags: [].}
The same as the split iterator, but is a proc that returns a sequence of substrings.
proc split(s: string; sep: string; maxsplit: int = - 1): seq[string] {.noSideEffect,
    gcsafe, extern: "nsuSplitString", raises: [AssertionError], tags: [].}

Splits the string s into substrings using a string separator.

Substrings are separated by the string sep. This is a wrapper around the split iterator.

proc rsplit(s: string; seps: set[char] = Whitespace; maxsplit: int = - 1): seq[string] {.
    noSideEffect, gcsafe, extern: "nsuRSplitCharSet", raises: [], tags: [].}

The same as the rsplit iterator, but is a proc that returns a sequence of substrings.

A possible common use case for rsplit is path manipulation, particularly on systems that don't use a common delimiter.

For example, if a system had # as a delimiter, you could do the following to get the tail of the path:

var tailSplit = rsplit("Root#Object#Method#Index", {'#'}, maxsplit=1)

Results in tailSplit containing:

@["Root#Object#Method", "Index"]
proc rsplit(s: string; sep: char; maxsplit: int = - 1): seq[string] {.noSideEffect,
    gcsafe, extern: "nsuRSplitChar", raises: [], tags: [].}

The same as the split iterator, but is a proc that returns a sequence of substrings.

A possible common use case for rsplit is path manipulation, particularly on systems that don't use a common delimiter.

For example, if a system had # as a delimiter, you could do the following to get the tail of the path:

var tailSplit = rsplit("Root#Object#Method#Index", '#', maxsplit=1)

Results in tailSplit containing:

@["Root#Object#Method", "Index"]
proc rsplit(s: string; sep: string; maxsplit: int = - 1): seq[string] {.noSideEffect,
    gcsafe, extern: "nsuRSplitString", raises: [], tags: [].}

The same as the split iterator, but is a proc that returns a sequence of substrings.

A possible common use case for rsplit is path manipulation, particularly on systems that don't use a common delimiter.

For example, if a system had # as a delimiter, you could do the following to get the tail of the path:

var tailSplit = rsplit("Root#Object#Method#Index", "#", maxsplit=1)

Results in tailSplit containing:

@["Root#Object#Method", "Index"]
proc toHex(x: BiggestInt; len: Positive): string {.noSideEffect, gcsafe,
    extern: "nsuToHex", raises: [], tags: [].}

Converts x to its hexadecimal representation.

The resulting string will be exactly len characters long. No prefix like 0x is generated. x is treated as an unsigned value.

proc toHex[T](x: T): string
Shortcut for toHex(x, T.sizeOf * 2)
proc intToStr(x: int; minchars: Positive = 1): string {.noSideEffect, gcsafe,
    extern: "nsuIntToStr", raises: [], tags: [].}

Converts x to its decimal representation.

The resulting string will be minimally minchars characters long. This is achieved by adding leading zeros.

proc parseInt(s: string): int {.noSideEffect, procvar, gcsafe, extern: "nsuParseInt",
                            raises: [OverflowError, ValueError], tags: [].}

Parses a decimal integer value contained in s.

If s is not a valid integer, ValueError is raised.

proc parseBiggestInt(s: string): BiggestInt {.noSideEffect, procvar, gcsafe,
    extern: "nsuParseBiggestInt", raises: [ValueError], tags: [].}

Parses a decimal integer value contained in s.

If s is not a valid integer, ValueError is raised.

proc parseUInt(s: string): uint {.noSideEffect, procvar, gcsafe,
                              extern: "nsuParseUInt", raises: [ValueError], tags: [].}

Parses a decimal unsigned integer value contained in s.

If s is not a valid integer, ValueError is raised.

proc parseBiggestUInt(s: string): BiggestUInt {.noSideEffect, procvar, gcsafe,
    extern: "nsuParseBiggestUInt", raises: [ValueError], tags: [].}

Parses a decimal unsigned integer value contained in s.

If s is not a valid integer, ValueError is raised.

proc parseFloat(s: string): float {.noSideEffect, procvar, gcsafe,
                                extern: "nsuParseFloat", raises: [ValueError],
                                tags: [].}
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).
proc parseHexInt(s: string): int {.noSideEffect, procvar, gcsafe,
                               extern: "nsuParseHexInt", raises: [ValueError],
                               tags: [].}

Parses a hexadecimal integer value contained in s.

If s is not a valid integer, ValueError is raised. s can have one of the following optional prefixes: 0x, 0X, #. Underscores within s are ignored.

proc parseBool(s: string): bool {.raises: [ValueError], tags: [].}

Parses a value into a bool.

If s is one of the following values: y, yes, true, 1, on, then returns true. If s is one of the following values: n, no, false, 0, off, then returns false. If s is something else a ValueError exception is raised.

proc parseEnum[T: enum](s: string): T

Parses an enum T.

Raises ValueError for an invalid value in s. The comparison is done in a style insensitive way.

proc parseEnum[T: enum](s: string; default: T): T

Parses an enum T.

Uses default for an invalid value in s. The comparison is done in a style insensitive way.

proc repeat(c: char; count: Natural): string {.noSideEffect, gcsafe,
    extern: "nsuRepeatChar", raises: [], tags: [].}
Returns a string of length count consisting only of the character c. You can use this proc to left align strings. Example:
proc tabexpand(indent: int, text: string, tabsize: int = 4) =
  echo '\t'.repeat(indent div tabsize), ' '.repeat(indent mod tabsize),
      text

tabexpand(4, "At four")
tabexpand(5, "At five")
tabexpand(6, "At six")
proc repeat(s: string; n: Natural): string {.noSideEffect, gcsafe,
                                       extern: "nsuRepeatStr", raises: [], tags: [].}
Returns String s concatenated n times. Example:
echo "+++ STOP ".repeat(4), "+++"
proc repeatChar(count: Natural; c: char = ' '): string {.deprecated, raises: [], tags: [].}
deprecated: use repeat() or spaces()
proc repeatStr(count: Natural; s: string): string {.deprecated, raises: [], tags: [].}
deprecated: use repeat(string, count) or string.repeat(count)
proc align(s: string; count: Natural; padding = ' '): string {.noSideEffect, gcsafe,
    extern: "nsuAlignString", raises: [], tags: [].}

Aligns a string s with padding, so that it is of length count.

padding characters (by default spaces) are added before s resulting in right alignment. If s.len >= count, no spaces are added and s is returned unchanged. If you need to left align a string use the repeatChar proc. Example:

assert align("abc", 4) == " abc"
assert align("a", 0) == "a"
assert align("1232", 6) == "  1232"
assert align("1232", 6, '#') == "##1232"
proc wordWrap(s: string; maxLineWidth = 80; splitLongWords = true;
             seps: set[char] = Whitespace; newLine = "\x0D\x0A"): string {.noSideEffect,
    gcsafe, extern: "nsuWordWrap", raises: [], tags: [].}
Word wraps s.
proc indent(s: string; count: Natural; padding: string = " "): string {.noSideEffect,
    gcsafe, extern: "nsuIndent", raises: [], tags: [].}

Indents each line in s by count amount of padding.

Note: This does not preserve the new line characters used in s.

proc unindent(s: string; count: Natural; padding: string = " "): string {.noSideEffect,
    gcsafe, extern: "nsuUnindent", raises: [], tags: [].}

Unindents each line in s by count amount of padding.

Note: This does not preserve the new line characters used in s.

proc unindent(s: string): string {.noSideEffect, gcsafe, extern: "nsuUnindentAll",
                               raises: [], tags: [].}

Removes all indentation composed of whitespace from each line in s.

For example:

const x = """
  Hello
  There
""".unindent()

doAssert x == "Hello\nThere\n"
proc startsWith(s, prefix: string): bool {.noSideEffect, gcsafe,
                                      extern: "nsuStartsWith", raises: [], tags: [].}

Returns true iff s starts with prefix.

If prefix == "" true is returned.

proc startsWith(s: string; prefix: char): bool {.noSideEffect, inline, raises: [],
    tags: [].}
Returns true iff s starts with prefix.
proc endsWith(s, suffix: string): bool {.noSideEffect, gcsafe, extern: "nsuEndsWith",
                                    raises: [], tags: [].}

Returns true iff s ends with suffix.

If suffix == "" true is returned.

proc endsWith(s: string; suffix: char): bool {.noSideEffect, inline, raises: [], tags: [].}
Returns true iff s ends with suffix.
proc continuesWith(s, substr: string; start: Natural): bool {.noSideEffect, gcsafe,
    extern: "nsuContinuesWith", raises: [], tags: [].}

Returns true iff s continues with substr at position start.

If substr == "" true is returned.

proc addSep(dest: var string; sep = ", "; startLen: Natural = 0) {.noSideEffect, inline,
    raises: [], tags: [].}

Adds a separator to dest only if its length is bigger than startLen.

A shorthand for:

if dest.len > startLen: add(dest, sep)

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 startLen. The following example creates a string describing an array of integers:

var arr = "["
for x in items([2, 3, 5, 7, 11]):
  addSep(arr, startLen=len("["))
  add(arr, $x)
add(arr, "]")
proc allCharsInSet(s: string; theSet: set[char]): bool {.raises: [], tags: [].}
Returns true iff each character of s is in the set theSet.
proc abbrev(s: string; possibilities: openArray[string]): int {.raises: [], tags: [].}

Returns the index of the first item in possibilities if not ambiguous.

Returns -1 if no item has been found and -2 if multiple items match.

proc join(a: openArray[string]; sep: string = ""): string {.noSideEffect, gcsafe,
    extern: "nsuJoinSep", raises: [], tags: [].}
Concatenates all strings in a separating them with sep.
proc join[T: not string](a: openArray[T]; sep: string = ""): string {.noSideEffect,
    gcsafe.}
Converts all elements in a to strings using $ and concatenates them with sep.
proc find(s, sub: string; start: Natural = 0; last: Natural = 0): int {.noSideEffect,
    gcsafe, extern: "nsuFindStr", raises: [], tags: [].}

Searches for sub in s inside range start..`last`. If last is unspecified, it defaults to s.high.

Searching is case-sensitive. If sub is not in s, -1 is returned.

proc find(s: string; sub: char; start: Natural = 0; last: Natural = 0): int {.noSideEffect,
    gcsafe, extern: "nsuFindChar", raises: [], tags: [].}

Searches for sub in s inside range start..`last`. If last is unspecified, it defaults to s.high.

Searching is case-sensitive. If sub is not in s, -1 is returned.

proc find(s: string; chars: set[char]; start: Natural = 0; last: Natural = 0): int {.
    noSideEffect, gcsafe, extern: "nsuFindCharSet", raises: [], tags: [].}

Searches for chars in s inside range start..`last`. If last is unspecified, it defaults to s.high.

If s contains none of the characters in chars, -1 is returned.

proc rfind(s, sub: string; start: int = - 1): int {.noSideEffect, raises: [], tags: [].}

Searches for sub in s in reverse, starting at start and going backwards to 0.

Searching is case-sensitive. If sub is not in s, -1 is returned.

proc rfind(s: string; sub: char; start: int = - 1): int {.noSideEffect, gcsafe, raises: [],
    tags: [].}

Searches for sub in s in reverse starting at position start.

Searching is case-sensitive. If sub is not in s, -1 is returned.

proc rfind(s: string; chars: set[char]; start: int = - 1): int {.noSideEffect, raises: [],
    tags: [].}

Searches for chars in s in reverse starting at position start.

Searching is case-sensitive. If sub is not in s, -1 is returned.

proc center(s: string; width: int; fillChar: char = ' '): string {.noSideEffect,
    gcsafe, extern: "nsuCenterString", raises: [], tags: [].}

Return the contents of s centered in a string width long using fillChar as padding.

The original string is returned if width is less than or equal to s.len.

proc count(s: string; sub: string; overlapping: bool = false): int {.noSideEffect,
    gcsafe, extern: "nsuCountString", raises: [], tags: [].}
Count the occurrences of a substring sub in the string s. Overlapping occurrences of sub only count when overlapping is set to true.
proc count(s: string; sub: char): int {.noSideEffect, gcsafe, extern: "nsuCountChar",
                                  raises: [], tags: [].}
Count the occurrences of the character sub in the string s.
proc count(s: string; subs: set[char]): int {.noSideEffect, gcsafe,
                                        extern: "nsuCountCharSet", raises: [],
                                        tags: [].}
Count the occurrences of the group of character subs in the string s.
proc quoteIfContainsWhite(s: string): string {.deprecated, raises: [], tags: [].}

Returns '"' & s & '"' if s contains a space and does not start with a quote, else returns s.

DEPRECATED as it was confused for shell quoting function. For this application use osproc.quoteShell.

proc contains(s: string; c: char): bool {.noSideEffect, raises: [], tags: [].}
Same as find(s, c) >= 0.
proc contains(s, sub: string): bool {.noSideEffect, raises: [], tags: [].}
Same as find(s, sub) >= 0.
proc contains(s: string; chars: set[char]): bool {.noSideEffect, raises: [], tags: [].}
Same as find(s, chars) >= 0.
proc replace(s, sub: string; by = ""): string {.noSideEffect, gcsafe,
                                        extern: "nsuReplaceStr", raises: [],
                                        tags: [].}
Replaces sub in s by the string by.
proc replace(s: string; sub, by: char): string {.noSideEffect, gcsafe,
    extern: "nsuReplaceChar", raises: [], tags: [].}

Replaces sub in s by the character by.

Optimized version of replace for characters.

proc replaceWord(s, sub: string; by = ""): string {.noSideEffect, gcsafe,
    extern: "nsuReplaceWord", raises: [], tags: [].}

Replaces sub in s by the string by.

Each occurrence of sub has to be surrounded by word boundaries (comparable to \\w in regular expressions), otherwise it is not replaced.

proc multiReplace(s: string; replacements: varargs[(string, string)]): string {.
    noSideEffect, raises: [], tags: [].}

Same as replace, but specialized for doing multiple replacements in a single pass through the input string.

Calling replace multiple times after each other is inefficient and result in too many allocations follwed by immediate deallocations as portions of the string gets replaced. multiReplace performs all replacements in a single pass.

If the resulting string is not longer than the original input string, only a single memory allocation is required.

The order of the replacements does matter. Earlier replacements are preferred over later replacements in the argument list.

proc delete(s: var string; first, last: int) {.noSideEffect, gcsafe, extern: "nsuDelete",
                                        raises: [], tags: [].}

Deletes in s the characters at position first .. last.

This modifies s itself, it does not return a copy.

proc parseOctInt(s: string): int {.noSideEffect, gcsafe, extern: "nsuParseOctInt",
                               raises: [ValueError], tags: [].}

Parses an octal integer value contained in s.

If s is not a valid integer, ValueError is raised. s can have one of the following optional prefixes: 0o, 0O. Underscores within s are ignored.

proc toOct(x: BiggestInt; len: Positive): string {.noSideEffect, gcsafe,
    extern: "nsuToOct", raises: [], tags: [].}

Converts x into its octal representation.

The resulting string is always len characters long. No leading 0o prefix is generated.

proc toBin(x: BiggestInt; len: Positive): string {.noSideEffect, gcsafe,
    extern: "nsuToBin", raises: [], tags: [].}

Converts x into its binary representation.

The resulting string is always len characters long. No leading 0b prefix is generated.

proc insertSep(s: string; sep = '_'; digits = 3): string {.noSideEffect, gcsafe,
    extern: "nsuInsertSep", raises: [], tags: [].}

Inserts the separator sep after digits digits from right to left.

Even though the algorithm works with any string s, it is only useful if s contains a number. Example: insertSep("1000000") == "1_000_000"

proc escape(s: string; prefix = "\""; suffix = "\""): string {.noSideEffect, gcsafe,
    extern: "nsuEscape", raises: [], tags: [].}

Escapes a string s.

This does these operations (at the same time):

  • replaces any \ by \\
  • replaces any ' by \'
  • replaces any " by \"
  • replaces any other character in the set {'\0'..'\31', '\127'..'\255'} by \xHH where HH is its hexadecimal value.

The procedure has been designed so that its output is usable for many different common syntaxes. The resulting string is prefixed with prefix and suffixed with suffix. Both may be empty strings. Note: This is not correct for producing Ansi C code!

proc unescape(s: string; prefix = "\""; suffix = "\""): string {.noSideEffect, gcsafe,
    extern: "nsuUnescape", raises: [ValueError], tags: [].}

Unescapes a string s.

This complements escape as it performs the opposite operations.

If s does not begin with prefix and end with suffix a ValueError exception will be raised.

proc validIdentifier(s: string): bool {.noSideEffect, gcsafe,
                                    extern: "nsuValidIdentifier", raises: [],
                                    tags: [].}

Returns true if s is a valid identifier.

A valid identifier starts with a character of the set IdentStartChars and is followed by any number of characters of the set IdentChars.

proc editDistance(a, b: string): int {.noSideEffect, gcsafe, extern: "nsuEditDistance",
                                  raises: [], tags: [].}

Returns the edit distance between a and b.

This uses the Levenshtein distance algorithm with only a linear memory overhead. This implementation is highly optimized!

proc formatBiggestFloat(f: BiggestFloat; format: FloatFormatMode = ffDefault;
                       precision: range[0 .. 32] = 16; decimalSep = '.'): string {.
    noSideEffect, gcsafe, extern: "nsu$1", raises: [], tags: [].}

Converts a floating point value f to a string.

If format == ffDecimal then precision is the number of digits to be printed after the decimal point. If format == ffScientific then precision is the maximum number of significant digits to be printed. precision's default value is the maximum number of meaningful digits after the decimal point for Nim's biggestFloat type.

If precision == 0, it tries to format it nicely.

proc formatFloat(f: float; format: FloatFormatMode = ffDefault;
                precision: range[0 .. 32] = 16; decimalSep = '.'): string {.noSideEffect,
    gcsafe, extern: "nsu$1", raises: [], tags: [].}

Converts a floating point value f to a string.

If format == ffDecimal then precision is the number of digits to be printed after the decimal point. If format == ffScientific then precision is the maximum number of significant digits to be printed. precision's default value is the maximum number of meaningful digits after the decimal point for Nim's float type.

If precision == 0, it tries to format it nicely.

proc trimZeros(x: var string) {.noSideEffect, raises: [], tags: [].}
Trim trailing zeros from a formatted floating point value (x). Modifies the passed value.
proc formatSize(bytes: int64; decimalSep = '.'; prefix = bpIEC; includeSpace = false): string {.
    noSideEffect, raises: [], tags: [].}

Rounds and formats bytes.

By default, uses the IEC/ISO standard binary prefixes, so 1024 will be formatted as 1KiB. Set prefix to bpColloquial to use the colloquial names from the SI standard (e.g. k for 1000 being reused as 1024).

includeSpace can be set to true to include the (SI preferred) space between the number and the unit (e.g. 1 KiB).

Examples:

formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB"
formatSize((2.234*1024*1024).int) == "2.234MiB"
formatSize(4096, includeSpace=true) == "4 KiB"
formatSize(4096, prefix=bpColloquial, includeSpace=true) == "4 kB"
formatSize(4096) == "4KiB"
formatSize(5_378_934, prefix=bpColloquial, decimalSep=',') == "5,13MB"
proc formatEng(f: BiggestFloat; precision: range[0 .. 32] = 10; trim: bool = true;
              siPrefix: bool = false; unit: string = nil; decimalSep = '.'): string {.
    noSideEffect, raises: [], tags: [].}

Converts a floating point value f to a string using engineering notation.

Numbers in of the range -1000.0<f<1000.0 will be formatted without an exponent. Numbers outside of this range will be formatted as a significand in the range -1000.0<f<1000.0 and an exponent that will always be an integer multiple of 3, corresponding with the SI prefix scale k, M, G, T etc for numbers with an absolute value greater than 1 and m, μ, n, p etc for numbers with an absolute value less than 1.

The default configuration (trim=true and precision=10) shows the shortest form that precisely (up to a maximum of 10 decimal places) displays the value. For example, 4.100000 will be displayed as 4.1 (which is mathematically identical) whereas 4.1000003 will be displayed as 4.1000003.

If trim is set to true, trailing zeros will be removed; if false, the number of digits specified by precision will always be shown.

precision can be used to set the number of digits to be shown after the decimal point or (if trim is true) the maximum number of digits to be shown.

formatEng(0, 2, trim=false) == "0.00"
formatEng(0, 2) == "0"
formatEng(0.053, 0) == "53e-3"
formatEng(52731234, 2) == "52.73e6"
formatEng(-52731234, 2) == "-52.73e6"

If siPrefix is set to true, the number will be displayed with the SI prefix corresponding to the exponent. For example 4100 will be displayed as "4.1 k" instead of "4.1e3". Note that u is used for micro- in place of the greek letter mu (μ) as per ISO 2955. Numbers with an absolute value outside of the range 1e-18<f<1000e18 (1a<f<1000E) will be displayed with an exponent rather than an SI prefix, regardless of whether siPrefix is true.

If unit is not nil, the provided unit will be appended to the string (with a space as required by the SI standard). This behaviour is slightly different to appending the unit to the result as the location of the space is altered depending on whether there is an exponent.

formatEng(4100, siPrefix=true, unit="V") == "4.1 kV"
formatEng(4.1, siPrefix=true, unit="V") == "4.1 V"
formatEng(4.1, siPrefix=true) == "4.1" # Note lack of space
formatEng(4100, siPrefix=true) == "4.1 k"
formatEng(4.1, siPrefix=true, unit="") == "4.1 " # Space with unit=""
formatEng(4100, siPrefix=true, unit="") == "4.1 k"
formatEng(4100) == "4.1e3"
formatEng(4100, unit="V") == "4.1e3 V"
formatEng(4100, unit="") == "4.1e3 " # Space with unit=""

decimalSep is used as the decimal separator

proc addf(s: var string; formatstr: string; a: varargs[string, `$`]) {.noSideEffect,
    gcsafe, extern: "nsuAddf", raises: [ValueError], tags: [].}
The same as add(s, formatstr % a), but more efficient.
proc `%`(formatstr: string; a: openArray[string]): string {.noSideEffect, gcsafe,
    extern: "nsuFormatOpenArray", raises: [ValueError], tags: [].}

Interpolates a format string with the values from a.

The substitution operator performs string substitutions in formatstr and returns a modified formatstr. This is often called string interpolation.

This is best explained by an example:

"$1 eats $2." % ["The cat", "fish"]

Results in:

"The cat eats fish."

The substitution variables (the thing after the $) are enumerated from 1 to a.len. To produce a verbatim $, use $$. The notation $# can be used to refer to the next substitution variable:

"$# eats $#." % ["The cat", "fish"]

Substitution variables can also be words (that is [A-Za-z_]+[A-Za-z0-9_]*) in which case the arguments in a with even indices are keys and with odd indices are the corresponding values. An example:

"$animal eats $food." % ["animal", "The cat", "food", "fish"]

Results in:

"The cat eats fish."

The variables are compared with cmpIgnoreStyle. ValueError is raised if an ill-formed format string has been passed to the % operator.

proc `%`(formatstr, a: string): string {.noSideEffect, gcsafe,
                                    extern: "nsuFormatSingleElem",
                                    raises: [ValueError], tags: [].}
This is the same as formatstr % [a].
proc format(formatstr: string; a: varargs[string, `$`]): string {.noSideEffect,
    gcsafe, extern: "nsuFormatVarargs", raises: [ValueError], tags: [].}
This is the same as formatstr % a except that it supports auto stringification.
proc removeSuffix(s: var string; chars: set[char] = Newlines) {.gcsafe,
    extern: "nsuRemoveSuffixCharSet", raises: [], tags: [].}
Removes the first matching character from the string (in-place) given a set of characters. If the set of characters is only equal to Newlines then it will remove both the newline and return feed. .. code-block:: nim
var
userInput = "Hello World!rn" otherInput = "Hello!?!"

userInput.removeSuffix userInput == "Hello World!" userInput.removeSuffix({'!', '?'}) userInput == "Hello World" otherInput.removeSuffix({'!', '?'}) otherInput == "Hello!?"

proc removeSuffix(s: var string; c: char) {.gcsafe, extern: "nsuRemoveSuffixChar",
                                      raises: [], tags: [].}
Removes a single character (in-place) from a string. .. code-block:: nim
var
table = "users"

table.removeSuffix('s') table == "user"

proc removeSuffix(s: var string; suffix: string) {.gcsafe,
    extern: "nsuRemoveSuffixString", raises: [], tags: [].}
Remove the first matching suffix (in-place) from a string. .. code-block:: nim
var
answers = "yeses"

answers.removeSuffix("es") answers == "yes"

Iterators

iterator split(s: string; seps: set[char] = Whitespace; maxsplit: int = - 1): string {.
    raises: [], tags: [].}

Splits the string s into substrings using a group of separators.

Substrings are separated by a substring containing only seps.

for word in split("this\lis an\texample"):
  writeLine(stdout, word)

...generates this output:

"this"
"is"
"an"
"example"

And the following code:

for word in split("this:is;an$example", {';', ':', '$'}):
  writeLine(stdout, word)

...produces the same output as the first example. The code:

let date = "2012-11-20T22:08:08.398990"
let separators = {' ', '-', ':', 'T'}
for number in split(date, separators):
  writeLine(stdout, number)

...results in:

"2012"
"11"
"20"
"22"
"08"
"08.398990"
iterator splitWhitespace(s: string): string {.raises: [], tags: [].}
Splits at whitespace.
iterator split(s: string; sep: char; maxsplit: int = - 1): string {.raises: [], tags: [].}

Splits the string s into substrings using a single separator.

Substrings are separated by the character sep. The code:

for word in split(";;this;is;an;;example;;;", ';'):
  writeLine(stdout, word)

Results in:

""
""
"this"
"is"
"an"
""
"example"
""
""
""
iterator split(s: string; sep: string; maxsplit: int = - 1): string {.raises: [], tags: [].}

Splits the string s into substrings using a string separator.

Substrings are separated by the string sep. The code:

for word in split("thisDATAisDATAcorrupted", "DATA"):
  writeLine(stdout, word)

Results in:

"this"
"is"
"corrupted"
iterator rsplit(s: string; seps: set[char] = Whitespace; maxsplit: int = - 1): string {.
    raises: [], tags: [].}
Splits the string s into substrings from the right using a string separator. Works exactly the same as split iterator except in reverse order.
for piece in "foo bar".rsplit(WhiteSpace):
  echo piece

Results in:

"bar"
"foo"

Substrings are separated from the right by the set of chars seps

iterator rsplit(s: string; sep: char; maxsplit: int = - 1): string {.raises: [], tags: [].}
Splits the string s into substrings from the right using a string separator. Works exactly the same as split iterator except in reverse order.
for piece in "foo:bar".rsplit(':'):
  echo piece

Results in:

"bar"
"foo"

Substrings are separated from the right by the char sep

iterator rsplit(s: string; sep: string; maxsplit: int = - 1; keepSeparators: bool = false): string {.
    raises: [], tags: [].}
Splits the string s into substrings from the right using a string separator. Works exactly the same as split iterator except in reverse order.
for piece in "foothebar".rsplit("the"):
  echo piece

Results in:

"bar"
"foo"

Substrings are separated from the right by the string sep

iterator splitLines(s: string): string {.raises: [], tags: [].}

Splits the string s into its containing lines.

Every character literal newline combination (CR, LF, CR-LF) is supported. The result strings contain no trailing \n.

Example:

for line in splitLines("\nthis\nis\nan\n\nexample\n"):
  writeLine(stdout, line)

Results in:

""
"this"
"is"
"an"
""
"example"
""
iterator tokenize(s: string; seps: set[char] = Whitespace): tuple[token: string,
    isSep: bool] {.raises: [], tags: [].}

Tokenizes the string s into substrings.

Substrings are separated by a substring containing only seps. Examples:

for word in tokenize("  this is an  example  "):
  writeLine(stdout, word)

Results in:

("  ", true)
("this", false)
(" ", true)
("is", false)
(" ", true)
("an", false)
("  ", true)
("example", false)
("  ", true)

Templates

template spaces(n: Natural): string
Returns a String with n space characters. You can use this proc to left align strings. Example:
let
  width = 15
  text1 = "Hello user!"
  text2 = "This is a very long string"
echo text1 & spaces(max(0, width - text1.len)) & "|"
echo text2 & spaces(max(0, width - text2.len)) & "|"

© 2006–2017 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/strutils.html