1# 2# 3# Nim's Runtime Library 4# (c) Copyright 2016 Joey Payne 5# 6# See the file "copying.txt", included in this 7# distribution, for details about the copyright. 8# 9 10## This module contains various string utility routines that are uncommonly 11## used in comparison to the ones in `strutils <strutils.html>`_. 12 13import std/strutils 14 15func expandTabs*(s: string, tabSize: int = 8): string = 16 ## Expands tab characters in `s`, replacing them by spaces. 17 ## 18 ## The amount of inserted spaces for each tab character is the difference 19 ## between the current column number and the next tab position. Tab positions 20 ## occur every `tabSize` characters. 21 ## The column number starts at 0 and is increased with every single character 22 ## and inserted space, except for newline, which resets the column number 23 ## back to 0. 24 runnableExamples: 25 doAssert expandTabs("\t", 4) == " " 26 doAssert expandTabs("\tfoo\t", 4) == " foo " 27 doAssert expandTabs("a\tb\n\txy\t", 3) == "a b\n xy " 28 29 result = newStringOfCap(s.len + s.len shr 2) 30 var pos = 0 31 32 template addSpaces(n) = 33 for j in 0 ..< n: 34 result.add(' ') 35 pos += 1 36 37 for i in 0 ..< len(s): 38 let c = s[i] 39 if c == '\t': 40 let 41 denominator = if tabSize > 0: tabSize else: 1 42 numSpaces = tabSize - pos mod denominator 43 44 addSpaces(numSpaces) 45 else: 46 result.add(c) 47 pos += 1 48 if c == '\l': 49 pos = 0 50 51func partition*(s: string, sep: string, 52 right: bool = false): (string, string, string) = 53 ## Splits the string at the first (if `right` is false) 54 ## or last (if `right` is true) occurrence of `sep` into a 3-tuple. 55 ## 56 ## Returns a 3-tuple of strings, `(beforeSep, sep, afterSep)` or 57 ## `(s, "", "")` if `sep` is not found and `right` is false or 58 ## `("", "", s)` if `sep` is not found and `right` is true. 59 ## 60 ## **See also:** 61 ## * `rpartition proc <#rpartition,string,string>`_ 62 runnableExamples: 63 doAssert partition("foo:bar:baz", ":") == ("foo", ":", "bar:baz") 64 doAssert partition("foo:bar:baz", ":", right = true) == ("foo:bar", ":", "baz") 65 doAssert partition("foobar", ":") == ("foobar", "", "") 66 doAssert partition("foobar", ":", right = true) == ("", "", "foobar") 67 68 let position = if right: s.rfind(sep) else: s.find(sep) 69 if position != -1: 70 return (s[0 ..< position], sep, s[position + sep.len ..< s.len]) 71 return if right: ("", "", s) else: (s, "", "") 72 73func rpartition*(s: string, sep: string): (string, string, string) = 74 ## Splits the string at the last occurrence of `sep` into a 3-tuple. 75 ## 76 ## Returns a 3-tuple of strings, `(beforeSep, sep, afterSep)` or 77 ## `("", "", s)` if `sep` is not found. This is the same as 78 ## `partition(s, sep, right = true)`. 79 ## 80 ## **See also:** 81 ## * `partition proc <#partition,string,string,bool>`_ 82 runnableExamples: 83 doAssert rpartition("foo:bar:baz", ":") == ("foo:bar", ":", "baz") 84 doAssert rpartition("foobar", ":") == ("", "", "foobar") 85 86 partition(s, sep, right = true) 87