In Files

Parent

Files

String

Constants

BRA2KET

Public Class Methods

interpolate(&str) click to toggle source

Interpolate. Provides a means of extenally using Ruby string interpolation mechinism.

try = "hello"
str = "\#{try}!!!"
String.interpolate{ str }    #=> "hello!!!"

NOTE: The block neccessary in order to get then binding of the caller.

CREDIT: Trans

# File lib/facets/core/facets/string/interpolate.rb, line 14
def self.interpolate(&str)
  eval "%{#{str.call}}", str.binding
end
random_binary(n_bytes) click to toggle source

Generate a random binary string of n_bytes size.

CREDIT: Guido De Rosa

# File lib/facets/core/facets/string/random_binary.rb, line 6
def self.random_binary(n_bytes)
  ( Array.new(n_bytes){ rand(0x100) } ).pack('c*') 
end

Public Instance Methods

-(pattern) click to toggle source

Removes occurances of a string or regexp.

("HELLO HELLO" - "LL")    #=> "HEO HEO"

CREDIT: Benjamin David Oakes

# File lib/facets/core/facets/string/op_sub.rb, line 9
def -(pattern)
  self.gsub(pattern, '')
end
/(path) click to toggle source

Treats self and path as representations of pathnames, joining thme together as a single path.

('home' / 'trans')  #=> 'home/trans'
# File lib/facets/core/facets/string/op_div.rb, line 9
def /(path)
  File.join(self, path.to_s)
end
^(aString) click to toggle source

Binary XOR of two strings.

a = "\000\000\001\001" ^ "\000\001\000\001"
b = "\003\003\003" ^ "\000\001\002"

a  #=> "\000\001\001\000"
b  #=> "\003\002\001"
# File lib/facets/core/facets/string/xor.rb, line 11
def ^(aString)
  a = self.unpack('C'*(self.length))
  b = aString.unpack('C'*(aString.length))
  if (b.length < a.length)
    (a.length - b.length).times { b << 0 }
  end
  xor = ""
  0.upto(a.length-1) { |pos|
    x = a[pos] ^ b[pos]
    xor << x.chr()
  }
  return(xor)
end
align(direction, n, sep="\n", c=' ') click to toggle source

Alignment method dispatches to align_right, align_left or align_center, accorging to the first direction parameter.

s = <<-EOS
This is a test
  and
  so on
EOS

s.align(:right, 14)

produces ...

This is a test
           and
         so on

Returns a String aligned right, left or center.

# File lib/facets/core/facets/string/align.rb, line 21
def align(direction, n, sep="\n", c=' ')
  case direction
  when :right
    align_right(n, sep="\n", c=' ')
  when :left
    align_left(n, sep="\n", c=' ')
  when :center
    align_center(n, sep="\n", c=' ')
  else
    raise ArgumentError
  end
end
align_center(n, sep="\n", c=' ') click to toggle source

Centers each line of a string.

The default alignment separation is a new line ("n"). This can be changed as can be the padding string which defaults to a single space (' ').

s = <<-EOS
  This is a test
  and
  so on
EOS

s.align_center(14)

produces ...

This is a test
     and
    so on

CREDIT: Trans

# File lib/facets/core/facets/string/align.rb, line 116
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=' ') click to toggle source

Align a string to the left.

The default alignment separation is a new line ("n"). This can be changed as can be the padding string which defaults to a single space (' ').

s = <<-EOS
This is a test
  and
  so on
EOS

s.align_left(20, "\n", '.')

produces ...

This is a test......
and.................
so on...............

CREDIT: Trans

# File lib/facets/core/facets/string/align.rb, line 86
def align_left(n, sep="\n", c=' ')
  return ljust(n.to_i,c.to_s) if sep==nil
  q = split(sep.to_s).map do |line|
    line.strip.ljust(n.to_i,c.to_s)
  end
  q.join(sep.to_s)
end
align_right(n, sep="\n", c=' ') click to toggle source

Align a string to the right.

The default alignment separation is a new line ("n"). This can be changed as can be the padding string which defaults to a single space (' ').

s = <<-EOS
This is a test
  and
  so on
EOS

s.align_right(14)

produces ...

This is a test
           and
         so on

CREDIT: Trans

# File lib/facets/core/facets/string/align.rb, line 56
def align_right(n, sep="\n", c=' ')
  return rjust(n.to_i,c.to_s) if sep==nil
  q = split(sep.to_s).map do |line|
    line.rjust(n.to_i,c.to_s)
  end
  q.join(sep.to_s)
end
blank?() click to toggle source

Is this string just whitespace?

"abc".blank?  #=> false
"   ".blank?  #=> true
# File lib/facets/core/facets/kernel/blank.rb, line 74
def blank?
  /\S/ !~ self
end
bracket(bra, ket=nil) click to toggle source

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

"wrap me".bracket('{')        #=> "{wrap me}"
"wrap me".bracket('--','!')   #=> "--wrap me!"

CREDIT: Trans

# File lib/facets/core/facets/string/bracket.rb, line 14
def bracket(bra, ket=nil)
  #ket = String.bra2ket[$&] if ! ket && /^[\[({<]$/ =~ bra
  ket = BRA2KET[bra] unless ket
  "#{bra}#{self}#{ket ? ket : bra}"
end
bracket!(bra, ket=nil) click to toggle source

Inplace version of bracket.

CREDIT: Trans

# File lib/facets/core/facets/string/bracket.rb, line 24
def bracket!(bra, ket=nil)
  self.replace(bracket(bra, ket))
end
bytes(&blk) click to toggle source

Upacks string into bytes.

Note, this is not 100% compatible with 1.8.7+ which returns an enumerator instead of an array.

# File lib/facets/core/facets/string/bytes.rb, line 10
def bytes(&blk)
  if block_given?
    self.unpack('C*').each(&blk)
  else
    self.unpack('C*')
  end
end
camelcase(first_letter=nil) click to toggle source
# File lib/facets/core/facets/string/camelcase.rb, line 21
def camelcase(first_letter=nil)
  case first_letter
  when :lower, true
    lower_camelcase
  when :inter, false
    inter_camelcase
  else
    upper_camelcase
    #str = dup
    #str.gsub!(/\/(.?)/){ "::#{$1.upcase}" }  # NOT SO SURE ABOUT THIS
    #str.gsub!(/(?:_+|-+)([a-z])/){ $1.upcase }
    #str.gsub!(/(\A|\s)([a-z])/){ $1 + $2.upcase }
    #str
  end
end
capitalized?() click to toggle source

Return true if the string is capitalized, otherwise false.

"This".capitalized?  #=> true
"THIS".capitalized?  #=> false
"this".capitalized?  #=> false

Note Ruby's strange concept of capitalized. See capitalcase for the more command conception.

CREDIT: Phil Tomson

# File lib/facets/core/facets/string/capitalized.rb, line 14
def capitalized?
  capitalize == self
end
characters() click to toggle source

Returns an array of characters.

"abc".characters.to_a  #=> ["a","b","c"]

TODO: Probably should make this an enumerator. With scan?

# File lib/facets/core/facets/string/characters.rb, line 8
def characters
  split(//)
end
cleanlines(&block) click to toggle source

Returns an Enumerator for iterating over each line of the string, stripped of whitespace on either side.

"this\nthat\nother\n".cleanlines.to_a  #=> ['this', 'that', 'other']
# File lib/facets/core/facets/string/cleanlines.rb, line 11
def cleanlines(&block)
  if block
    scan(/^.*?$/) do |line|
      block.call(line.strip)
    end
  else
    str = self
    Enumerator.new do |output|
      str.scan(/^.*?$/) do |line|
        output.yield(line.strip)
      end
    end
  end
end
cleave(threshold=nil, len=nil) click to toggle source

Cleave a string. Break a string in two parts at the nearest whitespace.

CREDIT: Trans

# File lib/facets/core/facets/string/cleave.rb, line 8
def cleave(threshold=nil, len=nil)
  l = (len || size / 2)
  t = threshold || size

  h1 = self[0...l]
  h2 = self[l..-1]

  i1 = h1.rindex(/\s/) || 0
  d1 = (i1 - l).abs

  d2 = h2.index(/\s/) || l
  i2 = d2 + l

  d1 = (i1-l).abs
  d2 = (i2-l).abs

  if [d1, d2].min > t
    i = t
  elsif d1 < d2
    i = i1
  else
    i = i2
  end

  #dup.insert(l, "\n").gsub(/^\s+|\s+$/, '')
  return self[0..i].to_s.strip, self[i+1..-1].to_s.strip
end
cmp(other) click to toggle source

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

CREDIT: Peter Vanbroekhoven

TODO: Move String#cmp to string/ directory.

# File lib/facets/core/facets/comparable/cmp.rb, line 34
def cmp(other)
  return -1 if length < other.length
  return 1 if length > other.length
  self <=> other  # alphabetic compare
end
compress_lines(spaced = true) click to toggle source

Matches any whitespace (including newline) and replaces with a single space

string = <<-QUERY.compress_lines
  SELECT name
  FROM users
QUERY

string  #=> "SELECT name FROM users"
# File lib/facets/core/facets/string/compress_lines.rb, line 12
def compress_lines(spaced = true)
  split($/).map{ |line| line.strip }.join(spaced ? ' ' : '')
end
divide( re ) click to toggle source

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.divide( /\<.*?\>/ )
#=> ["<p>This", "<b>is", "</b>a test.", "</p>"]

CREDIT: Trans

# File lib/facets/core/facets/string/divide.rb, line 12
def divide( re )
  re2 = /#{re}.*?(?=#{re}|\Z)/
  scan(re2) #{re}(?=#{re})/)
end
downcase?() click to toggle source

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

"THIS".downcase?  #=> false
"This".downcase?  #=> false
"this".downcase?  #=> true

CREDIT: Phil Tomson

# File lib/facets/core/facets/string/capitalized.rb, line 26
def downcase?
  downcase == self
end
each_char() click to toggle source

Yields a single-character string for each character in the string. When $KCODE = 'UTF8', multi-byte characters are yielded appropriately.

a = ''
"HELLO".each_char{ |c| a << "#{c.downcase}" }
a  #=> 'hello'
# File lib/facets/core/facets/string/each_char.rb, line 14
def each_char # :yield:
  scanner, char = StringScanner.new(self), /./u
  loop{ yield(scanner.scan(char) || break) }
end
each_word(&block) click to toggle source

Iterate through each word of a string.

a = []

"list of words".each_word { |word| a << word }

a  #=> ['list', 'of', 'words']
# File lib/facets/core/facets/string/each_word.rb, line 13
def each_word(&block)
  words.each(&block)
end
edit_distance(str2) click to toggle source

Levenshtein distance algorithm implementation for Ruby, with UTF-8 support.

The Levenshtein distance is a measure of how similar two strings s and t are, calculated as the number of deletions/insertions/substitutions needed to transform s into t. The greater the distance, the more the strings differ.

The Levenshtein distance is also sometimes referred to as the easier-to-pronounce-and-spell 'edit distance'.

Calculate the Levenshtein distance between two strings self and str2. self and str2 should be ASCII, UTF-8, or a one-byte-per character encoding such as ISO-8859-*.

The strings will be treated as UTF-8 if $KCODE is set appropriately (i.e. 'u'). Otherwise, the comparison will be performed byte-by-byte. There is no specific support for Shift-JIS or EUC strings.

When using Unicode text, be aware that this algorithm does not perform normalisation. If there is a possibility of different normalised forms being used, normalisation should be performed beforehand.

CREDIT: Paul Battley

# File lib/facets/core/facets/string/edit_distance.rb, line 25
def edit_distance(str2)
  str1 = self
  if $KCODE =~ /^U/
    unpack_rule = 'U*'
  else
    unpack_rule = 'C*'
  end

  s = str1.unpack(unpack_rule)
  t = str2.unpack(unpack_rule)

  n = s.length
  m = t.length

  return m if (0 == n)
  return n if (0 == m)

  d = (0..m).to_a
  x = nil

  (0...n).each do |i|
    e = i+1
    (0...m).each do |j|
      cost = (s[i] == t[j]) ? 0 : 1
      x = [
        d[j+1] + 1, # insertion
        e + 1,      # deletion
        d[j] + cost # substitution
      ].min
      d[j] = e
      e = x
    end
    d[m] = x
  end

  return x
end
end_with?(suffix) click to toggle source

Does a string end with the given suffix?

"hello".end_with?("lo")    #=> true
"hello".end_with?("to")    #=> false

Note: This definition is better than standard Ruby's becuase it handles regular expressions.

CREDIT: Juris Galang

# File lib/facets/core/facets/string/start_with.rb, line 49
def end_with?(suffix)
  suffix = Regexp.escape(suffix.to_s) unless Regexp===suffix
  /#{suffix}$/.match(self) ? true : false
end
Also aliased as: ends_with?
ends_with?(suffix) click to toggle source
Alias for: end_with?
exclude?(str) click to toggle source

The inverse of include?.

# File lib/facets/core/facets/string/exclude.rb, line 5
def exclude?(str)
  !include?(str)
end
expand_tab(n=8) click to toggle source

Singular form of expand_tabs.

Alias for: expand_tabs
expand_tabs(n=8) click to toggle source

Expands tabs to n spaces. Non-destructive. If n is 0, then tabs are simply removed. Raises an exception if n is negative.

"\t\tHey".expand_tabs(2)  #=> "    Hey"

Thanks to GGaramuno for a more efficient algorithm. Very nice.

CREDIT: Gavin Sinclair, Noah Gibbs, GGaramuno

TODO: Don't much care for the name String#expand_tabs. What about a more concise name like detab?

# File lib/facets/core/facets/string/expand_tab.rb, line 16
def expand_tabs(n=8)
  n = n.to_int
  raise ArgumentError, "n must be >= 0" if n < 0
  return gsub(/\t/, "") if n == 0
  return gsub(/\t/, " ") if n == 1
  str = self.dup
  while
    str.gsub!(/^([^\t\n]*)(\t+)/) { |f|
      val = ( n * $2.size - ($1.size % n) )
      $1 << (' ' * val)
    }
  end
  str
end
Also aliased as: expand_tab
file() click to toggle source

Use fluent notation for making file directives.

For instance, if we had a file 'foo.txt',

'foo.txt'.file.mtime
# File lib/facets/core/facets/string/file.rb, line 11
def file
  Functor.new(&method(:file_send).to_proc)
end
fold(ignore_indented=false) click to toggle source

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. "

One arguable flaw with this, that might need a fix: if the given string ends in a newline, it is replaced with a single space.

CREDIT: Trans

# File lib/facets/core/facets/string/fold.rb, line 19
def fold(ignore_indented=false)
  ns = ''
  i = 0
  br = self.scan(/(\n\s*\n|\Z)/) 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
indent(n, c=' ') click to toggle source

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

CREDIT: Gavin Sinclair, Trans, Tyler Rick

# File lib/facets/core/facets/string/indent.rb, line 8
def indent(n, c=' ')
  if n >= 0
    gsub(/^/, c * n)
  else
    gsub(/^#{Regexp.escape(c)}{0,#{-n}}/, "")
  end
end
indent!(n, c=' ') click to toggle source

Equivalent to String#indent, but modifies the receiver in place.

# File lib/facets/core/facets/string/indent.rb, line 18
def indent!(n, c=' ')
  replace(indent(n,c))
end
index_all(s, reuse=false) click to toggle source

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]

"bbb".index_all('bb', false)  #=> [0]
"bbb".index_all('bb', true)   #=> [0,1]

TODO: Culd probably be defined for Indexable in general too.

# File lib/facets/core/facets/string/index_all.rb, line 14
def index_all(s, reuse=false)
  s = Regexp.new(Regexp.escape(s)) unless Regexp===s
  ia = []; i = 0
  while (i = index(s,i))
    ia << i
    i += (reuse ? 1 : $~[0].size)
  end
  ia
end
inter_camelcase() click to toggle source
# File lib/facets/core/facets/string/camelcase.rb, line 38
def inter_camelcase
  str = dup
  str.gsub!(/\/(.?)/){ "::#{$1.upcase}" }  # NOT SO SURE ABOUT THIS
  str.gsub!(/(?:_+|-+)([a-z])/){ $1.upcase }
  #str.gsub!(/(\A|\s)([a-z])/){ $1 + $2.upcase }
  str
end
lchomp(match) click to toggle source

Left chomp.

"help".lchomp("h")  #=> "elp"
"help".lchomp("k")  #=> "help"

CREDIT: Trans

# File lib/facets/core/facets/string/lchomp.rb, line 10
def lchomp(match)
  if index(match) == 0
    self[match.size..-1]
  else
    self.dup
  end
end
lchomp!(match) click to toggle source

In-place left chomp.

"help".lchomp("h")  #=> "elp"
"help".lchomp("k")  #=> "help"

CREDIT: Trans

# File lib/facets/core/facets/string/lchomp.rb, line 25
def lchomp!(match)
  if index(match) == 0
    self[0...match.size] = ''
    self
  end
end
line_wrap(width, tabs=4) click to toggle source

Line wrap at width.

s = "1234567890".line_wrap(5)

s  #=> "12345\n67890\n"

CREDIT: Trans

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

Returns an array of characters.

"abc\n123".lines.to_a  #=> ["abc\n","123"]
# File lib/facets/core/facets/string/lines.rb, line 9
def lines(&blk)
  if block_given?
    each_line(&blk) #scan(/$.*?\n/).each(&blk)
  else
    Enumerator.new(self, :lines) #.split(/\n/)
  end
end
lower_camelcase() click to toggle source
# File lib/facets/core/facets/string/camelcase.rb, line 53
def lower_camelcase
  #str = dup
  #str = dup
  #str.gsub!(/\/(.?)/){ "::#{$1.upcase}" }  # NOT SO SURE ABOUT THIS
  #str.gsub!(/(?:_+|-+)([a-z])/){ $1.upcase }
  inter_camelcase.gsub(/(\A|\s)([A-Z])/){ $1 + $2.downcase }
end
lowercase() click to toggle source

Downcase first letter.

# File lib/facets/core/facets/string/uppercase.rb, line 17
def lowercase
  str = to_s
  str[0,1].downcase + str[1..-1]
end
margin(n=0) click to toggle source

Provides a margin controlled string.

x = %Q{
      | This
      |   is
      |     margin controlled!
      }.margin

NOTE: This may still need a bit of tweaking.

TODO: describe its limits and caveats and edge cases

CREDIT: Trans

# File lib/facets/core/facets/string/margin.rb, line 17
def margin(n=0)
  #d = /\A.*\n\s*(.)/.match( self )[1]
  #d = /\A\s*(.)/.match( self)[1] unless d
  d = ((/\A.*\n\s*(.)/.match(self)) ||
      (/\A\s*(.)/.match(self)))[1]
  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() click to toggle source

Translate a (class or module) name to a suitable method name.

"My::CoolClass".methodize  #=> "my__cool_class"
# File lib/facets/core/facets/string/methodize.rb, line 18
def methodize
  gsub(/([A-Z]+)([A-Z])/,'\1_\2').
  gsub(/([a-z])([A-Z])/,'\1_\2').
  gsub('/' ,'__').
  gsub('::','__').
  downcase
end
modulize() click to toggle source

Converts a string to module name representation.

This is essentially camelcase. It also converts '/' to '::' which is useful for converting paths to namespaces.

Examples

"method_name".modulize    #=> "MethodName"
"method/name".modulize    #=> "Method::Name"
# File lib/facets/core/facets/string/modulize.rb, line 23
def modulize
  gsub('__','/').
  gsub(/\/(.?)/){ "::#{$1.upcase}" }.
  gsub(/(?:_+|-+)([a-z])/){ $1.upcase }.
  gsub(/(\A|\s)([a-z])/){ $1 + $2.upcase }
end
mscan(re) click to toggle source

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

CREDIT: Trans

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

'Natural order' comparison of 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.1".natcmp("Hello.10")  #=> -1

TODO: Invert case flag?

CREDIT: Alan Davies, Martin Pool

# File lib/facets/core/facets/string/natcmp.rb, line 45
  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) click to toggle source

Returns 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.

str = "this is text"

str.nchar(4)            #=> "this"
str.nchar(-4)           #=> "text"

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

str.nchar(4, 'that')    #=> "that is text"

The original string remains unaffected.

str  #=> "this is text"
# File lib/facets/core/facets/string/nchar.rb, line 21
def nchar(n, replacement=nil)
  if replacement
    s = self.dup
    n > 0 ? (s[0...n] = replacement) : (s[n..-1] = replacement)
    s
  else
    n > 0 ? self[0...n] : self[n..-1]
  end
end
newlines(&block) click to toggle source

Returns an Enumerator for iterating over each line of the string, void of the termining newline character, in contrast to lines which retains it.

"a\nb\nc".newlines.class.assert == Enumerator
"a\nb\nc".newlines.to_a.assert == %w{a b c}

a = []
"a\nb\nc".newlines{|nl| a << nl}
a.assert == %w{a b c}
# File lib/facets/core/facets/string/newlines.rb, line 16
def newlines(&block)
  if block
    scan(/^.*?$/) do |line|
      block.call(line.chomp)
    end
  else
    str = self
    Enumerator.new do |output|
      str.scan(/^.*?$/) do |line|
        output.yield(line.chomp)
      end
    end
  end
end
object_state(data=nil) click to toggle source
# File lib/facets/core/facets/object/object_state.rb, line 54
def object_state(data=nil)
  data ? replace(data) : dup
end
pathize() click to toggle source

Converts a camelcase name (e.g. class or module name) to a unix path.

"ExamplePathize".pathize           #=> "example_pathize"
"ExamplePathize::Example".pathize  #=> "example_pathize/example"
# File lib/facets/core/facets/string/pathize.rb, line 8
def pathize
  gsub(/([A-Z]+)([A-Z])/,'\1_\2').
  gsub(/([a-z])([A-Z])/,'\1_\2').
  gsub('__','/').
  gsub('::','/').
  downcase
end
quote(type=:double, count=nil) click to toggle source

Return a new string embraced by given type and count of quotes. The arguments can be given in any order.

If no type is given, double quotes are assumed.

"quote me".quote     #=> '"quote me"'

If no type but a count is given then :mixed is assumed.

"quote me".quote(1)  #=> %q{'quote me'}
"quote me".quote(2)  #=> %q{"quote me"}
"quote me".quote(3)  #=> %q{'"quote me"'}

Symbols can be used to describe the type.

"quote me".quote(:single)    #=> %q{'quote me'}
"quote me".quote(:double)    #=> %q{"quote me"}
"quote me".quote(:back)      #=> %q{`quote me`}
"quote me".quote(:bracket)   #=> %q{`quote me'}

Or the character itself.

"quote me".quote("'")     #=> %q{'quote me'}
"quote me".quote('"')     #=> %q{"quote me"}
"quote me".quote("`")     #=> %q{`quote me`}
"quote me".quote("`'")    #=> %q{`quote me'}

CREDIT: Trans

# File lib/facets/core/facets/string/quote.rb, line 32
def quote(type=:double, count=nil)
  if Integer === type
    tmp   = count
    count = type
    type  = tmp || :mixed
  else
    count ||= 1
  end

  type = type.to_s unless Integer===type

  case type
  when "'", 'single', 's', 1
    f = "'" * count
    b = f
  when '"', 'double', 'd', 2
    f = '"' * count
    b = f
  when '`', 'back', 'b', -1
    f = '`' * count
    b = f
  when "`'", 'bracket', 'sb'
    f = "`" * count
    b = "'" * count
  when "'\"", 'mixed', "m", Integer
    c = (count.to_f / 2).to_i
    f = '"' * c
    b = f
    if count % 2 != 0
      f = "'" + f
      b = b + "'"
    end
  else
    raise ArgumentError, "unrecognized quote type -- #{type}"
  end
  "#{f}#{self}#{b}"
end
range(pattern, offset=0) click to toggle source

Like index but returns a Range.

"This is a test!".range('test')  #=> (10..13)

CREDIT: Trans

# File lib/facets/core/facets/string/range.rb, line 9
def range(pattern, offset=0)
  unless Regexp === pattern
    pattern = Regexp.new(Regexp.escape(pattern.to_s))
  end
  string = self[offset..-1]
  if md = pattern.match(string)
    return (md.begin(0)+offset)..(md.end(0)+offset-1)
  end
  nil
end
range_all(pattern, reuse=false) click to toggle source

Like index_all but returns an array of Ranges.

"abc123abc123".range_all('abc')  #=> [0..2, 6..8]

TODO: Add offset ?

CREDIT: Trans

# File lib/facets/core/facets/string/range.rb, line 28
def range_all(pattern, reuse=false)
  r = []; i = 0
  while i < self.length
    rng = range(pattern, i)
    if rng
      r << rng
      i += reuse ? 1 : rng.end + 1
    else
      break
    end
  end
  r.uniq
end
range_of_line() click to toggle source

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]

CREDIT: Trans

# File lib/facets/core/facets/string/range.rb, line 50
def range_of_line
  offset=0; charmap = []
  each_line do |line|
    charmap << (offset..(offset + line.length - 1))
    offset += line.length
  end
  charmap
end
rewrite(rules) click to toggle source

Apply a set of rules in the form of regular expression matches to the string.

  • rules - The array containing rule-pairs (match, write).

Keep in mind that the order of rules is significant.

Returns the rewritten String.

CREDIT: George Moschovitis

# File lib/facets/core/facets/string/rewrite.rb, line 14
def rewrite(rules)
  raise ArgumentError.new('The rules parameter is nil') unless rules
  rewritten_string = dup
  rules.each do |(match,write)|
    rewritten_string.gsub!(match,write)
  end
  return rewritten_string
end
shatter( re ) click to toggle source

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>"]

CREDIT: Trans

# File lib/facets/core/facets/string/shatter.rb, line 15
def shatter( re )
  r = self.gsub( re ){ |s| "\11"" + s + "\11"" }
  while r[0,1] == "\11"" ; r[0] = '' ; end
  while r[-1,1] == "\11"" ; r[-1] = '' ; end
  r.split("\11"")
end
similarity(str_in) click to toggle source

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".similarity("Aleksander")  #=> 0.9

The way it works:

  1. Converts each string into a "graph like" object, with edges ...

    "alexsander" -> [ alexsander, alexsand, alexsan ... lexsand ... san ... an, etc ]
    "aleksander" -> [ aleksander, aleksand ... etc. ]
  2. 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 ]
  1. 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.

Still a bit rough. Any suggestions for improvement are welcome.

CREDIT: Derek Lewis.

# File lib/facets/core/facets/string/similarity.rb, line 28
def similarity(str_in)
  return 0 if str_in == nil
  return 1 if self == str_in

  # -- make a graph of each word (okay, 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{ |aa| matches.push(aa) if( graph_B.include?(aa) ) }
  #++

  # -- 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( Regexp.escape(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
snakecase() click to toggle source

The reverse of camelcase. Makes an underscored of a camelcase string.

Changes '::' to '/' to convert namespaces to paths.

Examples

"SnakeCase".snakecase           #=> "snake_case"
"Snake-Case".snakecase          #=> "snake_case"
"SnakeCase::Errors".snakecase   #=> "snake_case/errors"
# File lib/facets/core/facets/string/snakecase.rb, line 12
def snakecase
  gsub(/::/, '/').  # NOT SO SURE ABOUT THIS
  gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
  gsub(/([a-z\d])([A-Z])/,'\1_\2').
  tr("-", "_").
  downcase
end
splice(idx, sub=nil) click to toggle source

String#slice is essentially the same as store.

a = "HELLO"
a.splice(1, "X")
a                #=> "HXLLO"

But it acts like slice! when given a single argument.

a = "HELLO"
a.splice(1)    #=> "E"
a              #=> "HLLO"

CREDIT: Trans

# File lib/facets/core/facets/string/splice.rb, line 19
def splice(idx, sub=nil)
  if sub
    store(idx, sub)
  else
    case idx
    when Range
      slice!(idx)
    else
      slice!(idx,1)
    end
  end
end
squish() click to toggle source

Returns the string, first removing all whitespace on both ends of the string, and then changing remaining consecutive whitespace groups into one space each.

%{ Multi-line
   string }.squish                   # => "Multi-line string"

" foo   bar    \n   \t   boo".squish # => "foo bar boo"
# File lib/facets/core/facets/string/squish.rb, line 11
def squish
  dup.squish!
end
squish!() click to toggle source

Performs a destructive squish. See String#squish.

# File lib/facets/core/facets/string/squish.rb, line 16
def squish!
  strip!
  gsub!(/\s+/, ' ')
  self
end
start_with?(prefix) click to toggle source

Does a string start with the given prefix?

"hello".start_with?("he")    #=> true
"hello".start_with?("to")    #=> false

Note: This definition is better than standard Ruby's becuase it handles regular expressions.

CREDIT: Juris Galang

# File lib/facets/core/facets/string/start_with.rb, line 30
def start_with?(prefix)
  prefix = Regexp.escape(prefix.to_s) unless Regexp===prefix
  /^#{prefix}/.match(self) ? true : false
end
Also aliased as: starts_with?
starts_with?(prefix) click to toggle source

end

Alias for: start_with?
tab(n) click to toggle source

Aligns each line n spaces.

CREDIT: Gavin Sinclair

# File lib/facets/core/facets/string/tab.rb, line 9
def tab(n)
  gsub(/^ */, ' ' * n)
end
tabto(n) click to toggle source

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

CREDIT: Gavin Sinclair

# File lib/facets/core/facets/string/tabto.rb, line 10
def tabto(n)
  if self =~ /^( *)\S/
    indent(n - $1.length)
  else
    self
  end
end
titlecase() click to toggle source

Title case.

"this is a string".titlecase
#=> "This Is A String"

CREDIT: Eliazar Parra

# File lib/facets/core/facets/string/titlecase.rb, line 10
def titlecase
  gsub(/\b\w/){ $`[-1,1] == "'" ? $& : $&.upcase }
end
to_b() click to toggle source

Interpret common affirmative string meanings as true, otherwise nil or false. Blank space and case are ignored. The following strings that will return true ...

true
yes
on
t
1
y
==

The following strings will return nil ...

nil
null

All other strings return false.

Here are some exmamples.

"true".to_b   #=> true
"yes".to_b    #=> true
"no".to_b     #=> false
"123".to_b    #=> false
# File lib/facets/core/facets/boolean.rb, line 96
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_re(esc=false) click to toggle source

Turns a string into a regular expression.

"a?".to_re  #=> /a?/

CREDIT: Trans

# File lib/facets/core/facets/string/to_re.rb, line 9
def to_re(esc=false)
  Regexp.new((esc ? Regexp.escape(self) : self))
end
to_rx(esc=true) click to toggle source

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

"[".to_rx  #=> /\[/

CREDIT: Trans

# File lib/facets/core/facets/string/to_re.rb, line 21
def to_rx(esc=true)
  Regexp.new((esc ? Regexp.escape(self) : self))
end
unbracket(bra=nil, ket=nil) click to toggle source

Return a new string with the given brackets removed. If only one bracket char is given it will be removed from either side.

"{unwrap me}".unbracket('{')        #=> "unwrap me"
"--unwrap me!".unbracket('--','!')  #=> "unwrap me"

CREDIT: Trans

# File lib/facets/core/facets/string/bracket.rb, line 37
def unbracket(bra=nil, ket=nil)
  if bra
    ket = BRA2KET[bra] unless ket
    ket = ket ? ket : bra
    s = self.dup
    s.gsub!(%[^#{Regexp.escape(bra)}], '')
    s.gsub!(%[#{Regexp.escape(ket)}$], '')
    return s
  else
    if m = 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) click to toggle source

Inplace version of unbracket.

CREDIT: Trans

# File lib/facets/core/facets/string/bracket.rb, line 57
def unbracket!(bra=nil, ket=nil)
  self.replace( unbracket(bra, ket) )
end
underscore() click to toggle source

The reverse of camelcase. Makes an underscored of a camelcase string.

Changes '::' to '/' to convert namespaces to paths.

Examples

"SnakeCase".underscore           #=> "snake_case"
"Snake-Case".underscore          #=> "snake_case"
"SnakeCase::Errors".underscore   #=> "snake_case/errors"
# File lib/facets/core/facets/string/underscore.rb, line 13
def underscore
  gsub(/::/, '/').
  gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
  gsub(/([a-z\d])([A-Z])/,'\1_\2').
  tr("-", "_").
  downcase
end
unfold() click to toggle source

Unfold paragrpahs.

FIXME: Sometimes adds one too many blank lines. TEST!!!

# File lib/facets/core/facets/string/unfold.rb, line 7
def unfold
  blank = false
  text  = ''
  split(/\n/).each do |line|
    if /\S/ !~ line
      text << "\n\n"
      blank = true
    else
      if /^(\s+|[*])/ =~ line
        text << (line.rstrip + "\n")
      else
        text << (line.rstrip + " ")
      end
      blank = false
    end
  end
  text = text.gsub(/(\n){3,}/,"\n\n")
  text.rstrip
end
unindent(size=nil) click to toggle source

Remove excessive indentation. Useful for multi-line strings embeded in already indented code.

<<-END.unindent
    ohaie
      wurld
END

Outputs ...

ohaie
  wurld

Instead of ...

ohaie
  wurld

CREDIT: Noah Gibbs, mynyml

# File lib/facets/core/facets/string/indent.rb, line 42
def unindent(size=nil)
  if size
    indent(-size)
  else
    char = ' '
    self.scan(/^[\ \t]*\S/) do |m|
      if size.nil? || m.size < size
        size = m.size
        char = m[0...-1]
      end
    end
    size -= 1
    indent(-size, char)
  end
end
unindent!() click to toggle source

Equivalent to String#unindent, but modifies the receiver in place.

CREDIT: mynyml

# File lib/facets/core/facets/string/indent.rb, line 62
def unindent!
  self.replace(self.unindent)
end
unquote() click to toggle source

Remove quotes from string.

"'hi'".unquote    #=> "hi"

CREDIT: Trans

# File lib/facets/core/facets/string/quote.rb, line 76
def unquote
  s = self.dup

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

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

  return s
end
upcase?() click to toggle source

Is the string upcase/uppercase?

"THIS".upcase?  #=> true
"This".upcase?  #=> false
"this".upcase?  #=> false

CREDIT: Phil Tomson

# File lib/facets/core/facets/string/capitalized.rb, line 41
def upcase?
  upcase == self
end
upper_camelcase() click to toggle source
# File lib/facets/core/facets/string/camelcase.rb, line 46
def upper_camelcase
  #str = dup
  #str.gsub!(/\/(.?)/){ "::#{$1.upcase}" }  # NOT SO SURE ABOUT THIS
  #str.gsub!(/(?:_+|-+)([a-z])/){ $1.upcase }
  inter_camelcase.gsub(/(\A|\s)([a-z])/){ $1 + $2.upcase }
end
uppercase() click to toggle source

Upcase first letter.

NOTE: One might argue that this method should behave the same as #upcase and rather this behavior should be in place of #captialize. Probably so, but since Matz has already defined #captialize the way it is, this name seems most fitting to the missing behavior.

# File lib/facets/core/facets/string/uppercase.rb, line 10
def uppercase
  str = to_s
  str[0,1].upcase + str[1..-1]
end
variablize() click to toggle source

Prepend an "@" to the beginning of a string to make a instance variable name. This also replaces non-valid characters with underscores.

# File lib/facets/core/facets/string/variablize.rb, line 7
def variablize
  v = gsub(/\W/, '_')
  "@#{v}"
end
word_wrap( col_width=80 ) click to toggle source

Word wrap a string not exceeding max width.

"this is a test".word_wrap(4)

produces ...

this
is a
test

This is basic implementation of word wrap, but smart enough to suffice for most use cases.

CREDIT: Gavin Kistner, Dayne Broderson

# File lib/facets/core/facets/string/word_wrap.rb, line 18
def word_wrap( col_width=80 )
  self.dup.word_wrap!( col_width )
end
word_wrap!( col_width=80 ) click to toggle source

As with word_wrap, but modifies the string in place.

CREDIT: Gavin Kistner, Dayne Broderson

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

Returns an array of characters.

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

Private Instance Methods

file_send(op, *a, &b) click to toggle source
# File lib/facets/core/facets/string/file.rb, line 17
def file_send(op, *a, &b)
  File.send(op, self, *a, &b)
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.