Very cool code but harder to understand for me...I ran it and got the results as expected, with a tiny 'bug'. When I passed it the string "this is a very long sentence without spaces in between", the shortened string was "this is a very long ..." (no problem there).

When I passed it the string "thisisaverylongsentencewithoutspacesinbetween", the output was "thisisaverylongsentencewith..." i.e. without any space between the last character of that string and '...'.

sub trimTo {
my( $str, $n ) = @_;
## Give back what they gave us if the nothing to do
return $str if length $str < $n;
my $lastSpace = 1 + rindex( $str, ' ', $n-3 );
## Subtracting 3 allows for adding the '...'
## rindex finds the last space preceding the position
## or -1 if it fails.
## Adding 1 means that we can test whether it found the space +with
## if( 1+rindex...) { ...
## or supply a default value
## 1 + rindex( ... ) || $default
## It also means that we get a length that we can supply
## directly to substr without having to increment it.
substr( $str, 0, $lastSpace || $n-3 ) . '...';
## The substr( ... ) returns from the start of string
## to the first space before the postition-3 (including that space+)
## or the first $n characters of the string.
## Combining the two avoids a temporary var.
## Tack on the '...'
}