What's the most efficient way to truncate a string to a given character count while preserving words? I implemented the below using tokenize(). But given that this will run on a dozens of elements to render a page, looking to minimize overhead.
proc truncate*(s: string, truncAt: int): string =
## Truncates a given text after a given length if text is longer than length
let suffix = "..."
var count: int
for (word, _) in tokenize(s):
if count >= truncAt - suffix.len():
result.add suffix
break
result.add word
count.inc word.len()
I would do something like this:
from strutils import Whitespace
proc truncate*(s: string, truncAt: int, suffix = "..."): string =
var at = -1
var i = 0
for i, c in s:
if i < truncAt or at < 0:
if c in Whitespace:
if i <= truncAt: at = i
else: break
else: break
if at < 0:
result = s
else:
result = s[0..<at] & suffix
Code might be a little ugly but should get the point across. If you want to avoid tracking duplicate whitespace then you could turn c in Whitespace to c in Whitespace and s[i - 1] notin Whitespace or something similar.
from strutils import Whitespace
proc truncate*(s: var string, truncAt: int) =
if s.len > truncAt:
var i = truncAt
while i > 0 and s[i] notin Whitespace:
dec i
dec i
while i > 0 and s[i] in Whitespace: dec i
setLen s, i+1
s.add "..."
var text = "ab cd def ghe"
truncate text, 10
echo text