Methods
Constants
SINGULAR_RULES = [ [/(matr)ices$/i, '\1ix'], [/(vert)ices$/i, '\1ex'], [/^(ox)en/i, '\1'], [/(alias)es$/i, '\1'], [/([octop|vir])i$/i, '\1us'], [/(cris|ax|test)es$/i, '\1is'], [/(shoe)s$/i, '\1'], [/(o)es$/i, '\1'], [/(bus)es$/i, '\1'], [/([m|l])ice$/i, '\1ouse'], [/(x|ch|ss|sh)es$/i, '\1'], [/(m)ovies$/i, '\1\2ovie'], [/(s)eries$/i, '\1\2eries'], [/([^aeiouy]|qu)ies$/i, '\1y'], [/([lr])ves$/i, '\1f'], [/(tive)s$/i, '\1'], [/(hive)s$/i, '\1'], [/([^f])ves$/i, '\1fe'], [/(^analy)ses$/i, '\1sis'], [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis'], [/([ti])a$/i, '\1um'], [/(p)eople$/i, '\1\2erson'], [/(m)en$/i, '\1an'], [/(s)tatus$/i, '\1\2tatus'], [/(c)hildren$/i, '\1\2hild'], [/(n)ews$/i, '\1\2ews'], [/s$/i, '']
PLURAL_RULES = [ [/^(ox)$/i, '\1\2en'], # ox [/([m|l])ouse$/i, '\1ice'], # mouse, louse [/(matr|vert)ix|ex$/i, '\1ices'], # matrix, vertex, index [/(x|ch|ss|sh)$/i, '\1es'], # search, switch, fix, box, process, address [/([^aeiouy]|qu)ies$/i, '\1y'], [/([^aeiouy]|qu)y$/i, '\1ies'], # query, ability, agency [/(hive)$/i, '\1s'], # archive, hive [/(?:([^f])fe|([lr])f)$/i, '\1\2ves'], # half, safe, wife [/sis$/i, 'ses'], # basis, diagnosis [/([ti])um$/i, '\1a'], # datum, medium [/(p)erson$/i, '\1eople'], # person, salesperson [/(m)an$/i, '\1en'], # man, woman, spokesman [/(c)hild$/i, '\1hildren'], # child [/(buffal|tomat|potat)o$/i, '\1\2oes'], # buffalo, tomato [/(bu)s$/i, '\1\2ses'], # bus [/(alias)/i, '\1es'], # alias [/(octop|vir)us$/i, '\1i'], # octopus, virus - virus has no defined plural, but viri is better than viruses/viruss [/(ax|cri|test)is$/i, '\1es'], # axis, crisis [/s$/i, 's'], # no change (compatibility) [/$/, 's']
Public Class methods
bra2ket()
# File lib/facets/core/string/bracket.rb, line 4
  def self.bra2ket
    @bra2ket ||= { '['=>']', '('=>')', '{'=>'}', '<'=>'>' }
  end
format(*args)
# File lib/facets/core/string/self/format.rb, line 2
def String.format(*args)
  Kernel.format(*args)
end
interpolate(&str)
# File lib/facets/core/string/self/interpolate.rb, line 4
  def self.interpolate(&str)
    eval "%{#{str.call}}", str.binding
  end
patterns( pattern )

Returns a Regexp pattern based on the given pattern string or symbolic name.

Recognized names are:

  • :char
  • :word
  • :line

They are also recognizied in plural form.

# File lib/facets/core/string/self/patterns.rb, line 14
  def self.patterns( pattern )
    case pattern
    when :char, :chars, :character, :characters
      pattern = //
    when :word, :words
      pattern = /\s+|\Z/
    when :line, :lines
      pattern = /\Z/
    when String
      pattern = Regexp.new(Regexp.escape(pattern))
    end
    pattern
  end
rand_letter()

Module method to generate a random letter.

  String::Random.rand_letter  #=> "q"
  String::Random.rand_letter  #=> "r"
  String::Random.rand_letter  #=> "a"
# File lib/facets/core/string/self/rand_letter.rb, line 9
  def self.rand_letter
    (rand(26) + (rand(2) == 0 ? 65 : 97) ).chr
  end
random(max_length = 8, char_re = /[\w\d]/)

Returns a randomly generated string. One possible use is password initialization. Takes a max legnth of characters (default 8) and an optional valid char Regexp (default /\w\d/).

# File lib/facets/core/string/self/random.rb, line 14
def String.random(max_length = 8, char_re = /[\w\d]/)
  # gmosx: this is a nice example of input parameter checking.
  # this is NOT a real time called method so we can add this
  # check. Congrats to the author.
  raise ArgumentError.new('char_re must be a regular expression!') unless char_re.is_a?(Regexp)

  string = ""

  while string.length < max_length
      ch = rand(255).chr
      string << ch if ch =~ char_re
  end

  return string
end
soundex_code(character)

Support function for String#soundex. Returns code for a single character.

# File lib/facets/core/string/soundex.rb, line 40
  def String.soundex_code(character)
    character.tr! "AEIOUYWHBPFVCSKGJQXZDTLMNR", "00000000111122222222334556"
  end
sprintf(*args)
# File lib/facets/core/string/self/format.rb, line 6
def String.sprintf(*args)
  Kernel.format(*args)
end
Public Instance methods
align_center( n, sep="\n", c=' ' )

Centers each line of a string.

  s = <<-EOS
  This is a test
  and
  so on
  EOS
  puts s.align_center(14)

produces

  This is a test
       and
      so on

Align a string to the center. The defualt alignment seperation is a new line ("/n") This can be changed as can be the padding string which defaults to a single space (’ ’).

# File lib/facets/core/string/align_center.rb, line 47
  def align_center( n, sep="\n", c=' ' )
    return center(n.to_i,c.to_s) if sep==nil
    q = split(sep.to_s).collect { |line|
      line.center(n.to_i,c.to_s)
    }
    q.join(sep.to_s)
  end
align_left( n, sep="\n", c=' ' )

Align a string to the left. The defualt alignment seperation is a new line ("/n") This can be changes as can be the padding string which defaults to a single space (’ ’).

# File lib/facets/core/string/align_center.rb, line 20
  def align_left( n, sep="\n", c=' ' )
    return ljust(n.to_i,c.to_s) if sep==nil
    q = split(sep.to_s).collect { |line|
      line.ljust(n.to_i,c.to_s)
    }
    q.join(sep.to_s)
  end
align_right( n, sep="\n", c=' ' )

Align a string to the right. The defualt alignment seperation is a new line ("/n") This can be changes as can be the padding string which defaults to a single space (’ ’).

# File lib/facets/core/string/align_center.rb, line 8
  def align_right( n, sep="\n", c=' ' )
    return rjust(n.to_i,c.to_s) if sep==nil
    q = split(sep.to_s).collect { |line|
      line.rjust(n.to_i,c.to_s)
    }
    q.join(sep.to_s)
  end
at_rand( separator=// )

Return a random separation of the string. Default separation is by charaacter.

  "Ruby rules".at_rand(' ')  #=> ["Ruby"]
# File lib/facets/core/string/at_rand.rb, line 13
  def at_rand( separator=// )
    separator = self.class.patterns( separator )
    self.split(separator,-1).at_rand
  end
at_rand!( separator=// )

Return a random separation while removing it from the string. Default separation is by character.

  s = "Ruby rules"
  s = at_rand!(' ')  #=> "Ruby"
  s                  #=> "rules"
# File lib/facets/core/string/at_rand.rb, line 25
  def at_rand!( separator=// )
    separator = self.class.patterns( separator )
    a = self.shatter( separator )
    w = []; a.each_with_index { |s,i| i % 2 == 0 ? w << s : w.last << s }
    i = rand( w.size )
    r = w.delete_at( i )
    self.replace( w.join('') )
    return r
  end
basename()

Removes prepend module namespace.

  "Test::Unit".basename  #=> "Unit"
# File lib/facets/core/string/basename.rb, line 8
  def basename
    self.to_s.gsub(/^.*::/, '')
  end
blank?()

Is this string just whitespace?

  "abc".blank?  #=> false
  "   ".blank?  #=> true
This method is also aliased as whitespace? whitespace?
# File lib/facets/core/string/blank.rb, line 9
  def blank?
    self !~ /\S/
  end
bracket(bra, ket=nil)

Return a new string embraced by given brakets. If only one bracket char is given it will be placed on either side.

  "wrap me".bracket('{')        #=> "{wrap me}"
  "wrap me".bracket('--','!')   #=> "--wrap me!"
# File lib/facets/core/string/bracket.rb, line 15
  def bracket(bra, ket=nil)
    #ket = String.bra2ket[$&] if ! ket && /^[\[({<]$/ =~ bra
    ket = String.bra2ket[bra] unless ket
    "#{bra}#{self}#{ket ? ket : bra}"
  end
bracket!(bra, ket=nil)

Inplace version of braket.

# File lib/facets/core/string/bracket.rb, line 22
  def bracket!(bra, ket=nil)
    self.replace( self.bracket(bra, ket) )
  end
brief(string, count = 128, force_cutoff = false, ellipsis="...")

Returns short abstract of long strings (first ‘count’ characters, chopped at the nearest word, appended by ’…’) force_cutoff: break forcibly at ‘count’ chars. Does not accept count < 2.

# File lib/facets/core/string/brief.rb, line 10
  def brief(string, count = 128, force_cutoff = false, ellipsis="...")
    return nil unless string
    return nil if count < 2

    if string.size > count
      cut_at = force_cutoff ? count : (string.index(' ', count-1) || count)
      xstring = string.slice(0, cut_at)
      return xstring.chomp(" ") + ellipsis
    else
      return string
    end
  end
bytes()

Upacks string ginto bytes.

# File lib/facets/core/string/bytes.rb, line 6
  def bytes
    self.unpack('C*')
  end
camelcase( first=false, on='_\s' )

Converts a string to camelcase. By default capitalization occurs on whitespace and underscores. By setting the first parameter to true the first character can also be captizlized. The second parameter can be assigned a valid Regualr Expression characeter set to determine which characters to match for capitalizing subsequent parts of the string.

  "this_is a test".camelcase             #=> "thisIsATest"
  "this_is a test".camelcase(true)       #=> "ThisIsATest"
  "this_is a test".camelcase(true, ' ')  #=> "This_isATest"
# File lib/facets/core/string/camelcase.rb, line 16
  def camelcase( first=false, on='_\s' )
    if first
      gsub(/(^|[#{on}]+)([A-Za-z])/){ $2.upcase }
    else
      gsub(/([#{on}]+)([A-Za-z])/){ $2.upcase }
    end
  end
camelize()

Variation of coverting a string to camelcase. This is unlike camelcase in that it is geared toward code reflection use.

  "this/is_a_test".camelize  #=> This::IsATest
# File lib/facets/core/string/camelize.rb, line 9
  def camelize
    #to_s.gsub(/(^|_)(.)/){$2.upcase}
    to_s.gsub(/\/(.?)/){ "::" + $1.upcase }.gsub(/(^|_)(.)/){ $2.upcase }
  end
capitalized?()

Return true if the string is capitalized, otherwise false.

  "THIS".capitalized?  #=> true
  "This".capitalized?  #=> true
  "this".capitalized?  #=> false
# File lib/facets/core/string/capitalized.rb, line 13
  def capitalized?
    self =~ /^[A-Z]/
  end
chars()

Returns an array of characters.

  "abc".chars  #=> ["a","b","c"]
# File lib/facets/core/string/chars.rb, line 8
  def chars
    self.split(//)
  end
cmp(other)

Compare method that takes length into account. Unlike #<=>, this is compatible with succ.

  "abc".cmp("abc")   #=>  0
  "abcd".cmp("abc")  #=>  1
  "abc".cmp("abcd")  #=> -1
  "xyz".cmp("abc")   #=>  1
# File lib/facets/core/string/cmp.rb, line 12
  def cmp(other)
    return -1 if length < other.length
    return 1 if length > other.length
    self <=> other  # alphabetic compare
  end
dequote()
# File lib/facets/core/string/dequote.rb, line 3
  def dequote
    s = self.dup

    case self[0,1]
    when "'", '"', '`'
      s[0] = ''
    end

    case self[-1,1]
    when "'", '"', '`'
      s[-1] = ''
    end

    s
  end
downcase?()

Return true if the string is lowercase (downcase), otherwise false.

  "THIS".downcase?  #=> false
  "This".downcase?  #=> false
  "this".downcase?  #=> true
This method is also aliased as lowercase?
# File lib/facets/core/string/downcase.rb, line 12
  def downcase?
    downcase == self
  end
dresner()

Scramble the inner characters of words leaving the text still readable (research at Cambridge University, code by KurtDresner).

For example, the above text may result in:

  Srblamce the iennr cchrteaars of wodrs lvenaig the txet stlil rbeaadle
  (rreceash at Cbamigdre Uverintisy, cdoe by KrneruestDr?)
# File lib/facets/core/string/dresner.rb, line 12
  def dresner
    self.gsub(/\B\w+\B/){$&.split(//).sort_by{rand}} 
  end
dresner!()

Inplace version of dresner method.

# File lib/facets/core/string/dresner.rb, line 18
  def dresner!
    self.replace(dresner)
  end
each_char( {|| ...}

Iterates through each character.

# File lib/facets/core/string/each_char.rb, line 5
  def each_char  # :yield:
    split(//).each { |c|
      yield( c )
    }
  end
each_word( &yld )

Iterate through each word of a string.

  "a string".each_word { |word, range| ... }
# File lib/facets/core/string/each_word.rb, line 8
  def each_word( &yld )
    rest_of_string = self
    wordfind = /([-'\w]+)/
    arity = yld.arity
    offset = 0
    while wmatch = wordfind.match(rest_of_string)
      word = wmatch[0]
      range = offset+wmatch.begin(0) ... offset+wmatch.end(0)
      rest_of_string = wmatch.post_match
      if arity == 1
        yld.call(word)
      else
        yld.call(word, range)
      end
      offset = self.length - rest_of_string.length
    end
  end
ends_with?(str)
# File lib/facets/core/string/starts_with.rb, line 11
  def ends_with?(str)
    self.rindex( str ) == self.length - str.length
  end
entropy()
# File lib/facets/core/enumerable/entropy.rb, line 27
  def entropy
    self.split(//).entropy
  end
first(separator_pattern=//)

Returns the first separation of a string. Default seperation is by character.

  "Hello World".first       #=> "H"
  "Hello World".first(' ')  #=> "Hello"
# File lib/facets/core/string/first.rb, line 14
  def first(separator_pattern=//)
    pattern = self.class.patterns(separator_pattern)
    split(separator_pattern).at(0)
  end
first!(separator_pattern=//)

Removes the first separation from a string. Defualt separation is by characters.

  a = "Hello World"
  a.first!       #=> "H"
  a              #=> "ello World"

  a = "Hello World"
  a.first!(' ')  #=> "Hello"
  a              #=> "World"
# File lib/facets/core/string/first.rb, line 36
  def first!(separator_pattern=//)
    pattern = self.class.patterns(separator_pattern)
    a = shatter(pattern)
    r = a.first
    a.shift
    a.shift
    replace( a.join('') )
    return r
  end
first=( x )

Prepends to a string.

  "Hello World".first = "Hello,"  #=> "Hello, Hello World"
# File lib/facets/core/string/first.rb, line 52
  def first=( x )
    insert(0, x.to_s)
  end
first_char(n=1)

Returns first n characters.

  "Hello World".first_char(3)  #=> "Hel"
# File lib/facets/core/string/first_char.rb, line 8
  def first_char(n=1)
    slice(0, n.to_i)
  end
fold(ignore_indented=false)

Returns a new string with all new lines removed from adjacent lines of text.

  s = "This is\na test.\n\nIt clumps\nlines of text."
  s.fold

produces

  "This is a test.\n\nIt clumps lines of text. "
# File lib/facets/core/string/fold.rb, line 19
  def fold(ignore_indented=false)
    ns = ''
    i = 0
    br = self.scan(/(\n\s*\n|\Z)/m) do |m|
      b = $~.begin(1)
      e = $~.end(1)
      nl = $&
      tx = slice(i...b)
      if ignore_indented and slice(i...b) =~ /^[ ]+/
        ns << tx
      else
        ns << tx.gsub(/[ ]*\n+/,' ')
      end
      ns << nl
      i = e
    end
    ns
  end
format( *args )
# File lib/facets/core/string/format.rb, line 4
  def format( *args )
    self.%(args)
  end
frequency(*args)
# File lib/facets/core/string/frequency.rb, line 7
  def frequency(*args)
    to_arr(*args).frequency
  end
fuzzy_match( str_in )

Alias for similarity

humanize()

Replaces underscores with spaces and capitalizes word.

# File lib/facets/core/string/humanize.rb, line 6
  def humanize
    self.gsub(/_/, " ").capitalize
  end
indent(n)

Indent left or right by n spaces. (This used to be called tab and aliased as indent.)

# File lib/facets/core/string/indent.rb, line 25
  def indent(n)
    if n >= 0
      gsub(/^/, ' ' * n)
    else
      gsub(/^ {0,#{-n}}/, "")
    end
  end
index_all(s, reuse=false)

Like index but returns an array of all index locations. The reuse flag allows the trailing portion of a match to be reused for subsquent matches.

  "abcabcabc".index_all('a')  #=> [0,3,6]
# File lib/facets/core/string/index_all.rb, line 10
  def index_all(s, reuse=false)
    ia = []; i = 0
    while (i = self.index(s,i))
      ia << i
      i += (reuse ? 1 : $~.length)
    end
    ia
  end
last(separator_pattern=//)

Returns the last separation of a string. Default separation is by character.

  "Hello World".last(' ')  #=> "World"
# File lib/facets/core/string/last.rb, line 13
  def last(separator_pattern=//)
    pattern = self.class.patterns(separator_pattern)
    self.split(separator_pattern).at(-1)
  end
last!(separator_pattern=//)

Removes the last separation from a string. Default seperation is by characeter.

  a = "Hello World"
  a.last!       #=> "d"
  a             #=> "Hello Worl"

  a = "Hello World"
  a.last!(' ')  #=> "World"
  a             #=> "Hello"
# File lib/facets/core/string/last.rb, line 43
  def last!(separator_pattern=//)
    pattern = self.class.patterns(separator_pattern)
    a = shatter(pattern)
    r = a.last
    a.pop
    a.pop
    replace( a.join('') )
    return r
  end
last=(str)

Appends to a string.

  "Hello World".last = ", Bye."  #=>  "Hello World, Bye."
# File lib/facets/core/string/last.rb, line 22
  def last=(str)
    self << str
  end
last_char(n=1)

Returns last n characters.

  "Hello World".last_char(3)  #=> "rld"
# File lib/facets/core/string/last_char.rb, line 8
  def last_char(n=1)
    n = n.to_i
    return self if n > size
    slice(-n, n) #self[-n..-1]
  end
line_wrap(width)

Line wrap at width.

  puts "1234567890".line_wrap(5)

produces

  12345
  67890
# File lib/facets/core/string/line_wrap.rb, line 13
  def line_wrap(width)
    s = gsub(/\t/,' '*4) # tabs default to 4 spaces.
    s = s.gsub(/\n/,' ')
    r = s.scan( /.{1,#{width}}/ )
    r.join("\n") << "\n"
  end
lines()

Returns an array of characters.

  "abc\n123".lines  #=> ["abc","123"]
# File lib/facets/core/string/lines.rb, line 8
  def lines
    self.split(/\n/)
  end
lowercase?()

Alias for downcase?

margin(n=0)

Provides a margin controlled string.

  x = %Q{
        | This
        |   is
        |     margin controlled!
        }.margin
# File lib/facets/core/string/margin.rb, line 15
  def margin(n=0)
    d = /\A.*\n\s*(.)/.match( self )[1]
    d = /\A\s*(.)/.match( self)[1] unless d
    return '' unless d
    if n == 0
      gsub(/\n\s*\Z/,'').gsub(/^\s*[#{d}]/, '')
    else
      gsub(/\n\s*\Z/,'').gsub(/^\s*[#{d}]/, ' ' * n)
    end
  end
methodize()

Converts a string into a valid ruby method name This method is geared toward code reflection.

  "MyModule::MyClass".methodize  #=> "my_module__my_class"

See also String#modulize, String#pathize

TODO

  • Make sure that all scenarios return a valid ruby class name
  • Make sure it is revertible
# File lib/facets/core/string/methodize.rb, line 18
  def methodize
    to_s.gsub(/([A-Z])/, '_\1').downcase.gsub(/^_/,'').gsub(/(::|\/)_?/, '__')
  end
modulize()

Converts a string into a valid ruby class or module name This method is geared toward code reflection.

  "my_module__my_path".modulize  #=> "MyModule::MyPath"

See also String#methodize, String#pathize

TODO

  • Make sure that all scenarios return a valid ruby class name
  • Make sure it is revertible
# File lib/facets/core/string/modulize.rb, line 16
  def modulize
    to_s.gsub(/(__|\/)(.?)/){ "::" + $2.upcase }.gsub(/(^|_)(.)/){ $2.upcase }
  end
mscan(re) {|| ...}

Like scan but returns MatchData ($~) rather then matched string ($&).

# File lib/facets/core/string/mscan.rb, line 7
  def mscan(re) #:yield:
    if block_given?
      scan(re) { yield($~) }
    else
      m = []
      scan(re) { m << $~ }
      m
    end
  end
natcmp(str2, caseInsensitive=false)

‘Natural order’ comparison of two strings, e.g.

  "my_prog_v1.1.0" < "my_prog_v1.2.0" < "my_prog_v1.10.0"

which does not follow alphabetically. A secondary parameter, if set to true, makes the comparison case insensitive.

  "Hello.10".natcmp("Hello.1")  #=> -1
# File lib/facets/core/string/natcmp.rb, line 42
  def natcmp(str2, caseInsensitive=false)
    str1 = self.dup
    str2 = str2.dup
    compareExpression = /^(\D*)(\d*)(.*)$/

    if caseInsensitive
      str1.downcase!
      str2.downcase!
    end

    # remove all whitespace
    str1.gsub!(/\s*/, '')
    str2.gsub!(/\s*/, '')

    while (str1.length > 0) or (str2.length > 0) do
      # Extract non-digits, digits and rest of string
      str1 =~ compareExpression
      chars1, num1, str1 = $1.dup, $2.dup, $3.dup
      str2 =~ compareExpression
      chars2, num2, str2 = $1.dup, $2.dup, $3.dup
      # Compare the non-digits
      case (chars1 <=> chars2)
        when 0 # Non-digits are the same, compare the digits...
          # If either number begins with a zero, then compare alphabetically,
          # otherwise compare numerically
          if (num1[0] != 48) and (num2[0] != 48)
            num1, num2 = num1.to_i, num2.to_i
          end
          case (num1 <=> num2)
            when -1 then return -1
            when 1 then return 1
          end
        when -1 then return -1
        when 1 then return 1
      end # case
    end # while

    # strings are naturally equal.
    return 0
  end

end
nchar( n, replacement=nil )

Retrns n characters of the string. If n is positive the characters are from the beginning of the string. If n is negative from the end of the string.

Alternatively a replacement string can be given, which will replace the n characters.

# File lib/facets/core/string/nchar.rb, line 11
  def nchar( n, replacement=nil )
    if replacement
      s = self.dup
      n > 0 ? (s[0...n] = replacement) : (s[n..-1] = replacement)
      return s
    else
      n > 0 ? self[0...n] : self[n..-1]
    end
  end
ordinal()
# File lib/facets/core/string/ordinal.rb, line 4
  def ordinal
    self.to_i.ordinal
  end
pathize()

Converts a string into a unix path. This method is geared toward code reflection.

See : String#modulize, String#methodize

  "MyModule::MyClass".pathize   #=> my_module/my_class
  "my_module__my_class".pathize #=> my_module/my_class

TODO :

  • Make sure that all scenarios return a valid unix path
  • Make sure it is revertible
# File lib/facets/core/string/pathize.rb, line 17
  def pathize
    to_s.gsub(/([A-Z])/, '_\1').downcase.gsub(/^_/,'').gsub(/(::|__)_?/, '/')
  end
plural()

Convert an English word from singular to plurel.

  "boy".plural     #=> boys
  "tomato".plural  #=> tomatoes
This method is also aliased as pluralize
# File lib/facets/core/string/singular.rb, line 76
  def plural
    result = self.to_s.dup
    String::PLURAL_RULES.each do |(rule, replacement)|
      break if result.gsub!(rule, replacement)
    end
    return result
  end
pluralize()

Alias for plural

pop()

Polymorphic with Array of characters.

# File lib/facets/core/string/pop.rb, line 5
  def pop
    return '' if size == 0
    r = self[-1,1]
    self[-1] = ''
    r #self
  end
pot( str=' ' )

Like push but works from the other end of the string.

# File lib/facets/core/string/pot.rb, line 6
  def pot( str=' ' )
    insert(0, str)
  end
probability(*args)
# File lib/facets/core/string/probability.rb, line 7
  def probability(*args)
    to_arr(*args).probability
  end
pull()

Same as shift.

# File lib/facets/core/string/pull.rb, line 3
  def pull
    return '' if size == 0
    self[0] = ''
    self
  end
push(str=' ')

Polymorphic with Array of characters.

# File lib/facets/core/string/push.rb, line 5
  def push(str=' ')
    concat(str)
  end
quote(type=:s)

Return a new string embraced by given quotes. If no quotes are specified, then assumes single quotes.

  "quote me".quote     #=> "'quote me'"
  "quote me".quote(2)  #=> "\"quote me\""
# File lib/facets/core/string/quote.rb, line 11
  def quote(type=:s)
    case type.to_s.downcase
    when 's', 'single'
      bracket("'")
    when 'd', 'double'
      bracket('"')
    when 'b', 'back'
      bracket('`')
    else
      bracket("'")
    end
  end
rand_byte()

Return a random byte of self.

  "Ruby rules".rand_byte  #=> 121
# File lib/facets/core/string/rand_byte.rb, line 8
  def rand_byte
    self[rand( size )]
  end
rand_byte!()

Destructive rand_byte. Delete a random byte of self and return it.

  s = "Ruby rules"
  s.rand_byte!      #=> 121
  s                 #=> "Rub rules"
# File lib/facets/core/string/rand_byte.rb, line 18
  def rand_byte!
    i = rand( size )
    rv = self[i,1]
    self[i,1] = ''
    rv
  end
rand_index()

Return a random string index.

  "Ruby rules".rand_index  #=> 3
# File lib/facets/core/string/rand_index.rb, line 6
  def rand_index
    rand( size )
  end
range(s, offset=0)

Like index but returns a Range.

  "This is a test!".range('test')  #=> 10..13
# File lib/facets/core/string/range.rb, line 8
  def range(s, offset=0)
    if self.index(s, offset)
      return ($~.begin(0))..($~.end(0)-1)
    end
    nil
  end
range_all(s, reuse=false)

Like index_all but returns an array of Ranges.

  "abc123abc123".range_all('abc')  #=> [0..2, 6..8]
# File lib/facets/core/string/range_all.rb, line 12
  def range_all(s, reuse=false)
    r = []; i = 0
    while i < self.length
      rng = range(s, i)
      if rng
        r << rng
        i += reuse ? 1 : rng.end + 1
      else
        break
      end
    end
    r.uniq
  end
range_of_line()

Returns an array of ranges mapping the characters per line.

  "this\nis\na\ntest".range_of_line
  #=> [0..4, 5..7, 8..9, 10..13]
# File lib/facets/core/string/range_of_line.rb, line 10
  def range_of_line
    offset=0; charmap = []
    self.each do |line|
      charmap << (offset..(offset + line.length - 1))
      offset += line.length
    end
    charmap
  end
regesc()

Escape string for Regexp use.

# File lib/facets/core/string/regesc.rb, line 5
  def regesc
    Regexp.escape( self )
  end
shatter( re )

Breaks a string up into an array based on a regular expression. Similar to scan, but includes the matches.

  s = "<p>This<b>is</b>a test.</p>"
  s.shatter( /\<.*?\>/ )

produces

  ["<p>", "This", "<b>", "is", "</b>", "a test.", "</p>"]
# File lib/facets/core/string/shatter.rb, line 14
  def shatter( re )
    r = self.gsub( re ){ |s| "\1" + s + "\1" }
    while r[0,1] == "\1" ; r[0] = '' ; end
    while r[-1,1] == "\1" ; r[-1] = '' ; end
    r.split("\1")
  end
shell_escape()

Escape special characters used in most unix shells to use it, eg. with system().

# File lib/facets/core/string/shell_escape.rb, line 7
  def shell_escape
    self.gsub(/([\\\t\| &`<>)('"])/) { |s| '\\' << s }
  end
shift()
# File lib/facets/core/string/shift.rb, line 2
  def shift
    return '' if size == 0
    self[0] = ''
    self
  end
shuffle(separator=//)

Return the string with seperated sections arranged in a random order. The default seperation is by character.

  "Ruby rules".shuffle  #=> "e lybRsuur"
# File lib/facets/core/string/shuffle.rb, line 10
  def shuffle(separator=//)
    split(separator).shuffle.join('')
  end
shuffle!(separator=//)

In place version of shuffle.

# File lib/facets/core/string/shuffle.rb, line 16
  def shuffle!(separator=//)
    self.replace( shuffle(separator) )
  end
similarity( str_in )

A fuzzy matching mechanism. Returns a score from 0-1, based on the number of shared edges. To be effective, the strings must be of length 2 or greater.

  "Alexsander".fuzzy_match( "Aleksander" )  #=> 0.9

The way it works:

  • Converts each string into a "graph like" object, with edges
      "alexsander" -> [ alexsander, alexsand, alexsan ... lexsand ... san ... an, etc ]
      "aleksander" -> [ aleksander, aleksand ... etc. ]
    
  • Perform match, then remove any subsets from this matched set (i.e. a hit on "san" is a subset of a hit on "sander")
      Above example, once reduced -> [ ale, sander ]
    
  • See’s how many of the matches remain, and calculates a score based on how many matches, their length, and compare to the length of the larger of the two words.
This method is also aliased as fuzzy_match
# File lib/facets/core/string/similarity.rb, line 25
  def similarity( str_in )
    return 0 if str_in == nil
    return 1 if self == str_in

    # Make a graph of each word (okay, so its not a true graph, but is similar)
    graph_A = Array.new
    graph_B = Array.new

    # "graph" self
    last = self.length
    (0..last).each do |ff|
      loc  = self.length
      break if ff == last - 1
      wordB = (1..(last-1)).to_a.reverse!
      if (wordB != nil)
        wordB.each do |ss|
          break if ss == ff
          graph_A.push( "#{self[ff..ss]}" )
        end
      end
    end

    # "graph" input string
    last = str_in.length
    (0..last).each{ |ff|
      loc  = str_in.length
      break if ff == last - 1
      wordB = (1..(last-1)).to_a.reverse!
      wordB.each do |ss|
        break if ss == ff
        graph_B.push( "#{str_in[ff..ss]}" )
      end
    }


    # count how many of these "graph edges" we have that are the same
    matches = graph_A & graph_B
    #matches = Array.new
    #graph_A.each do |aa|
    #  matches.push( aa ) if( graph_B.include?( aa ) )
    #end

    # For eliminating subsets, we want to start with the smallest hits.
    matches.sort!{|x,y| x.length <=> y.length}

    # eliminate any subsets
    mclone = matches.dup
    mclone.each_index do |ii|
      reg = Regexp.compile( mclone[ii] )
      count = 0.0
      matches.each{|xx| count += 1 if xx =~ reg}
      matches.delete(mclone[ii]) if count > 1
    end

    score = 0.0
    matches.each{ |mm| score += mm.length }
    self.length > str_in.length ? largest = self.length : largest = str_in.length
    return score/largest
  end
singular()

Convert an English word from plurel to singular.

  "boys".singular      #=> boy
  "tomatoes".singular  #=> tomato
This method is also aliased as singularize
# File lib/facets/core/string/singular.rb, line 63
  def singular
    result = self.to_s.dup
    String::SINGULAR_RULES.each do |(rule, replacement)|
      break if result.gsub!(rule, replacement)
    end
    return result
  end
singularize()

Alias for singular

soundex()

Implementation of the soundex algorithm as described by Knuth in volume 3 of The Art of Computer Programming. Returns nil if the value couldn’t be calculated b/c of empty-string or invalid character.

  "Ruby".soundex  #=> "R100"
# File lib/facets/core/string/soundex.rb, line 14
  def soundex
    return nil if self.empty?

    str = self.upcase
    last_code = String.soundex_code(str[0,1])
    soundex_code = str[0,1]

    for index in 1...(str.size) do
      return soundex_code if soundex_code.size == 4

      code = String.soundex_code(str[index,1])

      if code == "0" then
        last_code = nil
      elsif code == nil then
        return nil
      elsif code != last_code then
        soundex_code += code
        last_code = code
      end
    end

    return soundex_code + "000"[0,4-soundex_code.size]
  end
starts_with?(str)
# File lib/facets/core/string/starts_with.rb, line 7
  def starts_with?(str)
    self.index( str ) == 0
  end
succ(n=1)

Allows succ to take n step increments.

  "abc".succ      #=> "abd"
  "abc".succ(4)   #=> "abg"
  "abc".succ(24)  #=> "aca"
# File lib/facets/core/string/succ.rb, line 9
  def succ(n=1)
    s = self
    n.times { s = s.succ_once }
    s
  end
tab(n)

Aligns each line n spaces. (This used to be taballto.)

# File lib/facets/core/string/indent.rb, line 7
  def tab(n)
    gsub(/^ */, ' ' * n)
  end
tabto(n)

Preserves relative tabbing. The first non-empty line ends up with n spaces before nonspace.

# File lib/facets/core/string/indent.rb, line 14
  def tabto(n)
    if self =~ /^( *)\S/
      indent(n - $1.length)
    else
      self
    end
  end
to_a(div=//,limit=0)

Essentially makes to_a an alias for split, with the excpetion that if no divider is given then the array is split on charaters, and NOT on the global input record divider ($/).

WARNING There is a slight chance of incompatability with other libraries which depend on spliting with $/ (although doing so is a very bad idea!).

# File lib/facets/core/string/to_a.rb, line 14
  def to_a(div=//,limit=0)
    split(div,limit)
  end
to_b()

Interpret common affirmative string meanings as true, otherwise false. Balnk sapce and case are ignored. The following strings that will return true:

  <tt>true</tt>,<tt>yes</tt>,<tt>on</tt>,<tt>t</tt>,<tt>1</tt>,<tt>y</tt>,<tt>==</tt>

Examples:

  "true".to_b   #=> true
  "yes".to_b    #=> true
  "no".to_b     #=> false
  "123".to_b    #=> false
# File lib/facets/core/string/to_b.rb, line 17
  def to_b
    case self.downcase.strip
    when 'true', 'yes', 'on', 't', '1', 'y', '=='
      return true
    when 'nil', 'null'
      return nil
    else
      return false
    end
  end
to_const()

Get a constant by a given string name.

  "Class".to_const   #=> Class

Note this method is not as verstile as it should be, since it can not access contants relative to the current execution context. But without a binding_of_caller that does not seem possible.

# File lib/facets/core/string/to_const.rb, line 12
  def to_const
    split('::').inject(Object){ |namespace,name| namespace.const_get(name) }
  end
to_date()
# File lib/facets/core/string/to_date.rb, line 4
  def to_date
    require 'date'
    require 'parsedate'
    ::Date::civil(*ParseDate.parsedate(self)[0..2])
  end
to_proc(context=nil)

Evaluates a String as a Proc.

  xyp = "|x,y| x + y".to_proc
  xyp.class      #=> Proc
  xyp.call(1,2)  #=> 3
# File lib/facets/core/string/to_proc.rb, line 14
  def to_proc(context=nil)
    if context
      if context.kind_of?(Binding) or context.kind_of?(Proc)
        Kernel.eval "proc { #{self} }", context
      else context
        context.instance_eval "proc { #{self} }"
      end
    else
      Kernel.eval "proc { #{self} }"
    end
  end
to_re(esc=true)

Turns a string into a regular expression. By default it will escape all characters. Use false argument to turn off escaping.

  "[".to_re  #=> /\[/
# File lib/facets/core/string/to_re.rb, line 10
  def to_re(esc=true)
    Regexp.new((esc ? Regexp.escape(self) : self))
  end
to_rx()

Turns a string into a regular expression. Unlike to_re this will not escape characters.

  "a?".to_rx  #=> /a?/
# File lib/facets/core/string/to_re.rb, line 19
  def to_rx
    Regexp.new(self)
  end
to_time()
# File lib/facets/core/string/to_time.rb, line 4
  def to_time
    require 'time'
    Time.parse(self)
  end
unbracket(bra=nil, ket=nil)

Return a new string embraced by given brakets. If only one bracket char is given it will be placed on either side.

  "{unwrap me}".debracket('{')        #=> "unwrap me"
  "--unwrap me!".debracket('--','!')  #=> "unwrap me!"
# File lib/facets/core/string/unbracket.rb, line 16
  def unbracket(bra=nil, ket=nil)
    if bra
      ket = Sring.bra2ket[bra] unless ket
      ket = ket ? ket : bra
      s = self.dup
      s.gsub!(%r[^#{Regexp.escape(bra)}], '')
      s.gsub!(%r[#{Regexp.escape(ket)}$], '')
      return s
    else
      if m = String.bra2ket[ self[0,1] ]
        return self.slice(1...-1) if self[-1,1]  == m
      end
    end
    return self.dup  # if nothing else
  end
unbracket!(bra=nil, ket=nil)

Inplace version of debraket.

# File lib/facets/core/string/unbracket.rb, line 33
  def unbracket!(bra=nil, ket=nil)
    self.replace( unbracket(bra, ket) )
  end
underscore(

Underscore string based on camelcase characteristics.

# File lib/facets/core/string/underscore.rb, line 5
  def underscore #(camel_cased_word)
    self.gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase
  end
unix_crypt()

Common Unix cryptography method.

# File lib/facets/core/string/unix_crypt.rb, line 7
  def unix_crypt
    self.crypt(String.rand_letter + String.rand_letter)
  end
unix_crypt!()

Common Unix cryptography in-place method.

# File lib/facets/core/string/unix_crypt.rb, line 12
  def unix_crypt!
    self.replace( unix_crypt )
  end
unpack(format, offset=nil)

Upack with offset. Extends unpack to allow a string to be unpacked starting at an offset position within it.

# File lib/facets/core/string/unpack.rb, line 8
  def unpack(format, offset=nil)
    if offset.nil?
      unpack_from_orgin(format)
    else
      self[offset..-1].unpack_from_orgin(format)
    end
  end
unshift( str=' ' )
# File lib/facets/core/string/unshift.rb, line 4
  def unshift( str=' ' )
    insert(0, str)
  end
upcase?()

Is the string upcase/uppercase?

  "THIS".upcase?  #=> true
  "This".upcase?  #=> false
  "this".upcase?  #=> false
This method is also aliased as uppercase?
# File lib/facets/core/string/upcase.rb, line 13
  def upcase?
    self.upcase == self
  end
uppercase?()

Alias for upcase?

whitespace?()

Alias for blank?

whitespace?()

Alias for blank?

word_filter( &blk )

Filters out words from a string based on block test.

  "a string".word_filter { |word| word =~ /^a/ }  #=> "string"
# File lib/facets/core/string/word_filter.rb, line 8
  def word_filter( &blk )
    s = self.dup
    s.word_filter!( &blk )
  end
word_filter!( {|| ...}

In place version of word_filter.

  "a string".word_filter { |word| ... }
# File lib/facets/core/string/word_filter.rb, line 17
  def word_filter! #:yield:
    rest_of_string = self
    wordfind = /(\w+)/
    offset = 0
    while wmatch = wordfind.match(rest_of_string)
      word = wmatch[0]
      range = offset+wmatch.begin(0) ... offset+wmatch.end(0)
      rest_of_string = wmatch.post_match
      self[range] = yield( word ).to_s
      offset = self.length - rest_of_string.length
    end
    self
  end
word_wrap( col_width=80 )

Word wrap a string not exceeding max width.

  puts "this is a test".word_wrap(4)

produces

  this
  is a
  test
# File lib/facets/core/string/word_wrap.rb, line 18
  def word_wrap( col_width=80 )
    self.dup.word_wrap!( col_width )
  end
word_wrap!( col_width=80 )

As with word_wrap, but modifies the string in place.

# File lib/facets/core/string/word_wrap.rb, line 24
  def word_wrap!( col_width=80 )
    self.gsub!( /(\S{#{col_width}})(?=\S)/, '\1 ' )
    self.gsub!( /(.{1,#{col_width}})(?:\s+|$)/, "\\1\n" )
    self
  end
words()

Returns an array of characters.

  "abc 123".words  #=> ["abc","123"]
# File lib/facets/core/string/words.rb, line 8
  def words
    self.split(/\s+/)
  end