summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/std/wordwrap.nim73
1 files changed, 48 insertions, 25 deletions
diff --git a/lib/std/wordwrap.nim b/lib/std/wordwrap.nim
index 4b0dc4417..bb6f2dc6f 100644
--- a/lib/std/wordwrap.nim
+++ b/lib/std/wordwrap.nim
@@ -11,10 +11,10 @@
 
 import strutils, unicode
 
-proc olen(s: string): int =
-  var i = 0
+proc olen(s: string; start, lastExclusive: int): int =
+  var i = start
   result = 0
-  while i < s.len:
+  while i < lastExclusive:
     inc result
     let L = graphemeLen(s, i)
     inc i, L
@@ -32,31 +32,46 @@ proc wrapWords*(s: string, maxLineWidth = 80,
   result = newStringOfCap(s.len + s.len shr 6)
   var spaceLeft = maxLineWidth
   var lastSep = ""
-  for word, isSep in tokenize(s, seps):
-    let wlen = olen(word)
+
+  var i = 0
+  while true:
+    var j = i
+    let isSep = j < s.len and s[j] in seps
+    while j < s.len and (s[j] in seps) == isSep: inc(j)
+    if j <= i: break
+    #yield (substr(s, i, j-1), isSep)
     if isSep:
-      lastSep = word
-      spaceLeft = spaceLeft - wlen
-    elif wlen > spaceLeft:
-      if splitLongWords and wlen > maxLineWidth:
-        var i = 0
-        while i < word.len:
-          if spaceLeft <= 0:
-            spaceLeft = maxLineWidth
-            result.add newLine
-          dec spaceLeft
-          let L = graphemeLen(word, i)
-          for j in 0 ..< L: result.add word[i+j]
-          inc i, L
+      lastSep.setLen 0
+      for k in i..<j:
+        if s[k] notin {'\L', '\C'}: lastSep.add s[k]
+      if lastSep.len == 0:
+        lastSep.add ' '
+        dec spaceLeft
       else:
-        spaceLeft = maxLineWidth - wlen
-        result.add(newLine)
-        result.add(word)
+        spaceLeft = spaceLeft - olen(lastSep, 0, lastSep.len)
     else:
-      spaceLeft = spaceLeft - wlen
-      result.add(lastSep)
-      result.add(word)
-      lastSep.setLen(0)
+      let wlen = olen(s, i, j)
+      if wlen > spaceLeft:
+        if splitLongWords and wlen > maxLineWidth:
+          var k = 0
+          while k < j - i:
+            if spaceLeft <= 0:
+              spaceLeft = maxLineWidth
+              result.add newLine
+            dec spaceLeft
+            let L = graphemeLen(s, k+i)
+            for m in 0 ..< L: result.add s[i+k+m]
+            inc k, L
+        else:
+          spaceLeft = maxLineWidth - wlen
+          result.add(newLine)
+          for k in i..<j: result.add(s[k])
+      else:
+        spaceLeft = spaceLeft - wlen
+        result.add(lastSep)
+        for k in i..<j: result.add(s[k])
+        #lastSep.setLen(0)
+    i = j
 
 when isMainModule:
 
@@ -93,3 +108,11 @@ tnaetdriaoenvlcyfglwckßqfgvwkßqgfvlwkßqfgvlwckßqvlwkgfUIαοιαοιαχολ
 ξχλωωχαοεοιαεοαεοιαεοαεοιαοεσναοεκνρκψγκψφϵιηαααοε"""
   doAssert wrapWords(longlongword) == longlongwordRes
 
+  # bug #14579
+  const input60 = """
+This is a long string. It is manually wrapped to 60
+characters. I would not expect it to be changed by
+wordwrap if wordwrap is set to wrap at 80 characters"""
+  const input60Res = """This is a long string. It is manually wrapped to 60 characters. I would not
+expect it to be changed by wordwrap if wordwrap is set to wrap at 80 characters"""
+  doAssert wrapWords(input60) == input60Res