diff options
Diffstat (limited to 'lib/pure/strutils.nim')
-rwxr-xr-x | lib/pure/strutils.nim | 90 |
1 files changed, 87 insertions, 3 deletions
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index f5adf1abb..f6de035a8 100755 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -449,8 +449,83 @@ proc repeatChar*(count: int, c: Char = ' '): string {.noSideEffect, ## Returns a string of length `count` consisting only of ## the character `c`. result = newString(count) - for i in 0..count-1: - result[i] = c + for i in 0..count-1: result[i] = c + +proc align*(s: string, count: int): string {. + noSideEffect, rtl, extern: "nsuAlignString".} = + ## 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 + ## spaces are added and `s` is returned unchanged. + if s.len < count: + result = newString(count) + var spaces = count - s.len + for i in 0..spaces-1: result[i] = ' ' + for i in spaces..count-1: result[i] = s[i-spaces] + else: + result = s + +iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[ + token: string, isSep: bool] = + ## Tokenizes the string `s` into substrings. + ## + ## Substrings are separated by a substring containing only `seps`. + ## Examples: + ## + ## .. code-block:: nimrod + ## for word in tokenize(" this is an example "): + ## writeln(stdout, word) + ## + ## Results in: + ## + ## .. code-block:: nimrod + ## (" ", true) + ## ("this", false) + ## (" ", true) + ## ("is", false) + ## (" ", true) + ## ("an", false) + ## (" ", true) + ## ("example", false) + ## (" ", true) + var i = 0 + while true: + var j = i + var isSep = s[j] in seps + while j < s.len and (s[j] in seps) == isSep: inc(j) + if j > i: + yield (copy(s, i, j-1), isSep) + else: + break + i = j + +proc wordWrap*(s: string, maxLineWidth = 80, + splitLongWords = true, + seps: set[char] = whitespace, + newLine = "\n"): string {. + noSideEffect, rtl, extern: "nsuWordWrap".} = + ## word wraps `s`. + result = "" + var SpaceLeft = maxLineWidth + for word, isSep in tokenize(s, seps): + if len(word) > SpaceLeft: + if splitLongWords and len(word) > maxLineWidth: + result.add(copy(word, 0, spaceLeft-1)) + var w = spaceLeft+1 + var wordLeft = len(word) - spaceLeft + while wordLeft > 0: + result.add(newLine) + var L = min(maxLineWidth, wordLeft) + SpaceLeft = maxLineWidth - L + result.add(copy(word, w, w+L-1)) + inc(w, L) + dec(wordLeft, L) + else: + SpaceLeft = maxLineWidth - len(Word) + result.add(newLine) + result.add(word) + else: + SpaceLeft = SpaceLeft - len(Word) + result.add(word) proc startsWith*(s, prefix: string): bool {.noSideEffect, rtl, extern: "nsuStartsWith".} = @@ -739,7 +814,7 @@ proc validEmailAddress*(s: string): bool {.noSideEffect, rtl, extern: "nsuValidEmailAddress".} = ## returns true if `s` seems to be a valid e-mail address. ## The checking also uses a domain list. - ## Note: This will be moved into another module soon. + ## Note: This will be moved to another module soon. const chars = Letters + Digits + {'!','#','$','%','&', '\'','*','+','/','=','?','^','_','`','{','}','|','~','-','.'} @@ -862,3 +937,12 @@ proc editDistance*(a, b: string): int {.noSideEffect, #dealloc(row) {.pop.} + +when isMainModule: + assert align("abc", 4) == " abc" + assert align("a", 0) == "a" + assert align("1232", 6) == " 1232" + echo wordWrap(""" this is a long text -- muchlongerthan10chars and here + it goes""", 10, false) + + |