1# 2# 3# Nim's Runtime Library 4# (c) Copyright 2018 Nim contributors 5# 6# See the file "copying.txt", included in this 7# distribution, for details about the copyright. 8# 9 10## This module contains an algorithm to wordwrap a Unicode string. 11 12import strutils, unicode 13 14proc olen(s: string; start, lastExclusive: int): int = 15 var i = start 16 result = 0 17 while i < lastExclusive: 18 inc result 19 let L = graphemeLen(s, i) 20 inc i, L 21 22proc wrapWords*(s: string, maxLineWidth = 80, 23 splitLongWords = true, 24 seps: set[char] = Whitespace, 25 newLine = "\n"): string {.noSideEffect.} = 26 ## Word wraps `s`. 27 runnableExamples: 28 doAssert "12345678901234567890".wrapWords() == "12345678901234567890" 29 doAssert "123456789012345678901234567890".wrapWords(20) == "12345678901234567890\n1234567890" 30 doAssert "Hello Bob. Hello John.".wrapWords(13, false) == "Hello Bob.\nHello John." 31 doAssert "Hello Bob. Hello John.".wrapWords(13, true, {';'}) == "Hello Bob. He\nllo John." 32 result = newStringOfCap(s.len + s.len shr 6) 33 var spaceLeft = maxLineWidth 34 var lastSep = "" 35 36 var i = 0 37 while true: 38 var j = i 39 let isSep = j < s.len and s[j] in seps 40 while j < s.len and (s[j] in seps) == isSep: inc(j) 41 if j <= i: break 42 #yield (substr(s, i, j-1), isSep) 43 if isSep: 44 lastSep.setLen 0 45 for k in i..<j: 46 if s[k] notin {'\L', '\C'}: lastSep.add s[k] 47 if lastSep.len == 0: 48 lastSep.add ' ' 49 dec spaceLeft 50 else: 51 spaceLeft = spaceLeft - olen(lastSep, 0, lastSep.len) 52 else: 53 let wlen = olen(s, i, j) 54 if wlen > spaceLeft: 55 if splitLongWords and wlen > maxLineWidth: 56 var k = 0 57 while k < j - i: 58 if spaceLeft <= 0: 59 spaceLeft = maxLineWidth 60 result.add newLine 61 dec spaceLeft 62 let L = graphemeLen(s, k+i) 63 for m in 0 ..< L: result.add s[i+k+m] 64 inc k, L 65 else: 66 spaceLeft = maxLineWidth - wlen 67 result.add(newLine) 68 for k in i..<j: result.add(s[k]) 69 else: 70 spaceLeft = spaceLeft - wlen 71 result.add(lastSep) 72 for k in i..<j: result.add(s[k]) 73 #lastSep.setLen(0) 74 i = j 75