Boris Blaadh <nejnejnej / gmail.com> writes: > Brian Adkins wrote: >> Boris Blaadh <nejnejnej / gmail.com> writes: >> >>> wordlist = string.split(' ') >>> # get rid of the last space >>> shorttext.chop! >>> >>> puts "#{shorttext}..." >> >> It is nicer to break at word boundaries in some contexts. But if it's >> a single word (such as a long email address), then you'd still want to >> show something more than "...". Maybe you can add a check for that. >> >> e.g. for string = 'john.smith / hisdomain.com', lead = 15 > > Hehe, ok: > > if shorttext.empty? > puts wordlist[0] > else > puts "#{shorttext}..." > 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 -- Brian Adkins http://www.lojic.com/ http://lojic.com/blog/