Boris B. [email protected] writes:

a single word (such as a long email address), then you’d still want to

end

That fixes the problem of showing only ‘…’, but now ‘puts

wordlist[0]’ may display more than the limit.

Refining your idea a bit gave the following:

def elide_words total_length

return self unless self.length > total_length

raise ‘total_length must be at least 3’ if total_length < 3

words = self.split(’ ')

result = ‘’

words.each do |word|

len = total_length - (result.empty? ? 3 : 4)

break if result.length + word.length > len

result << ’ ’ unless result.empty?

result << word

end

if result.empty?

return self.elide(total_length)

else

return result + ‘…’

end

end

But we really don’t need to find *all* the space boundaries via

split(), so the following version is about 10 times faster:

def elide_words total_length

return self unless self.length > total_length

raise ‘total_length must be at least 3’ if total_length < 3

len = total_length - 3 # room for ‘…’

```
# Case 1: natural word break
return self[0, len] + '...' if self[len,1] == ' '
# Case 2: search backward for a char preceding a delimiter
delim_found = false
idx = len.downto(0) {|i|
if delim_found
break (i + 1) if self[i,1] != ' '
else
delim_found = true if self[i,1] == ' '
end
}
return self[0, idx] + '...'
```

end