summary refs log tree commit diff stats
path: root/lib/pure/strmisc.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/strmisc.nim')
-rw-r--r--lib/pure/strmisc.nim43
1 files changed, 35 insertions, 8 deletions
diff --git a/lib/pure/strmisc.nim b/lib/pure/strmisc.nim
index 359014d8c..89ef2fcd2 100644
--- a/lib/pure/strmisc.nim
+++ b/lib/pure/strmisc.nim
@@ -14,6 +14,32 @@ import strutils
 
 {.deadCodeElim: on.}
 
+proc expandTabs*(s: string, tabSize: int = 8): string {.noSideEffect,
+  procvar.} =
+  ## Expand tab characters in `s` by `tabSize` spaces
+
+  result = newStringOfCap(s.len + s.len shr 2)
+  var pos = 0
+
+  template addSpaces(n) =
+    for j in 0 ..< n:
+      result.add(' ')
+      pos += 1
+
+  for i in 0 ..< len(s):
+    let c = s[i]
+    if c == '\t':
+      let
+        denominator = if tabSize > 0: tabSize else: 1
+        numSpaces = tabSize - pos mod denominator
+
+      addSpaces(numSpaces)
+    else:
+      result.add(c)
+      pos += 1
+    if c == '\l':
+      pos = 0
+
 proc partition*(s: string, sep: string,
                 right: bool = false): (string, string, string)
                 {.noSideEffect, procvar.} =
@@ -22,16 +48,9 @@ proc partition*(s: string, sep: string,
   ## Returns a 3 string tuple of (beforeSep, `sep`, afterSep) or
   ## (`s`, "", "") if `sep` is not found and `right` is false or
   ## ("", "", `s`) if `sep` is not found and `right` is true
-
   let position = if right: s.rfind(sep) else: s.find(sep)
-
   if position != -1:
-    let
-      beforeSep = s[0 ..< position]
-      afterSep = s[position + sep.len ..< s.len]
-
-    return (beforeSep, sep, afterSep)
-
+    return (s[0 ..< position], sep, s[position + sep.len ..< s.len])
   return if right: ("", "", s) else: (s, "", "")
 
 proc rpartition*(s: string, sep: string): (string, string, string)
@@ -43,6 +62,14 @@ proc rpartition*(s: string, sep: string): (string, string, string)
   return partition(s, sep, right = true)
 
 when isMainModule:
+  doAssert expandTabs("\t", 4) == "    "
+  doAssert expandTabs("\tfoo\t", 4) == "    foo "
+  doAssert expandTabs("\tfoo\tbar", 4) == "    foo bar"
+  doAssert expandTabs("\tfoo\tbar\t", 4) == "    foo bar "
+  doAssert expandTabs("", 4) == ""
+  doAssert expandTabs("", 0) == ""
+  doAssert expandTabs("\t\t\t", 0) == ""
+
   doAssert partition("foo:bar", ":") == ("foo", ":", "bar")
   doAssert partition("foobarbar", "bar") == ("foo", "bar", "bar")
   doAssert partition("foobarbar", "bank") == ("foobarbar", "", "")