Skip to content

Commit

Permalink
optimized wrapWords; fixes #14579 (#14606) [backport:1.2]
Browse files Browse the repository at this point in the history
  • Loading branch information
Araq authored Jun 8, 2020
1 parent e3f80e4 commit c308c2e
Showing 1 changed file with 48 additions and 25 deletions.
73 changes: 48 additions & 25 deletions lib/std/wordwrap.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:

Expand Down Expand Up @@ -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

0 comments on commit c308c2e

Please sign in to comment.