*
@method truncate(<length>, [split] = true, [from] = 'right', [ellipsis] = '...')
@returns String
@short Truncates a string.
@extra If [split] is %false%, will not split words up, and instead discard the word where the truncation occurred. [from] can also be %"middle"% or %"left"%.
@example

'just sittin on the dock of the bay'.truncate(20)                 -> 'just sittin on the do...'
'just sittin on the dock of the bay'.truncate(20, false)          -> 'just sittin on the...'
'just sittin on the dock of the bay'.truncate(20, true, 'middle') -> 'just sitt...of the bay'
'just sittin on the dock of the bay'.truncate(20, true, 'left')   -> '...the dock of the bay'

*
function(length, split, from, ellipsis) {
      var pos,
        prepend = '',
        append = '',
        str = this.toString(),
        chars = '[' + getTrimmableCharacters() + ']+',
        space = '[^' + getTrimmableCharacters() + ']*',
        reg = regexp(chars + space + '$');
      ellipsis = isUndefined(ellipsis) ? '...' : string(ellipsis);
      if(str.length <= length) {
        return str;
      }
      switch(from) {
        case 'left':
          pos = str.length - length;
          prepend = ellipsis;
          str = str.slice(pos);
          reg = regexp('^' + space + chars);
          break;
        case 'middle':
          pos    = floor(length / 2);
          append = ellipsis + str.slice(str.length - pos).trimLeft();
          str    = str.slice(0, pos);
          break;
        default:
          pos = length;
          append = ellipsis;
          str = str.slice(0, pos);
      }
      if(split === false && this.slice(pos, pos + 1).match(/\S/)) {
        str = str.remove(reg);
      }
      return prepend + str + append;
    }