class String

Constants

BASE_DIGITS

Cached constants for base conversion.

COLOR_REGEXP

A Regexp to recognize ANSI escape sequences

LOWERCASE_WORDS

For `titlecase`

STOP_WORDS

For `words_without_stopwords`

Public Instance Methods

amount(n) click to toggle source

Convert this string into a string describing this many of the string. (Note: Doesn't know anything about proper grammar.)

Example:

"cookie".amount(0)    #=> "0 cookies"
"shirt".amount(17)    #=> "17 shirts"
"dollar".amount(-10)  #=> "-10 dollars"
"love".amount(1)      #=> "1 love"
# File lib/epitools/core_ext/string.rb, line 473
def amount(n)
  case n
  when 0
    "0 #{self}s"
  when 1, -1
    "#{n} #{self}"
  else
    "#{n} #{self}s"
  end
end
base64()
Alias for: to_base64
blank?() click to toggle source

'true' if the string's length is 0 (after whitespace has been stripped from the ends)

# File lib/epitools/core_ext/truthiness.rb, line 126
def blank?
  strip.size == 0
end
chomp_lines()
Alias for: each_chomped
chomped_lines()
Alias for: each_chomped
clean_lines()
Alias for: nice_lines
contains_ansi?()
Alias for: contains_color?
contains_color?() click to toggle source

This string contains ANSI (VT100) control codes

# File lib/epitools/core_ext/string.rb, line 83
def contains_color?
  self[COLOR_REGEXP]
end
Also aliased as: contains_colors?, contains_ansi?
contains_colors?()
Alias for: contains_color?
decode64()
Alias for: from_base64
deflate(level=nil) click to toggle source

deflate the string

# File lib/epitools/core_ext/string.rb, line 415
def deflate(level=nil)
  Zlib::Deflate.deflate(self, level)
end
dewhitespace() click to toggle source

Remove redundant whitespace AND newlines.

# File lib/epitools/core_ext/string.rb, line 48
def dewhitespace
  gsub(/\s+/,' ').strip
end
each_chomped() { |chomp| ... } click to toggle source

Like each_line, but removes trailing n

# File lib/epitools/core_ext/string.rb, line 111
def each_chomped
  each_line { |line| yield line.chomp }
end
Also aliased as: chomped_lines, chomp_lines
each_slice(slice_width) { |self| ... } click to toggle source

Iterate over slices of the string of size `slice_width`.

# File lib/epitools/core_ext/string.rb, line 255
def each_slice(slice_width, &block)
  max = size
  p = 0
  while p < max
    yield self[p...p+slice_width]
    p += slice_width
  end
end
encode64()
Alias for: to_base64
endswith(substring)
Alias for: endswith?
endswith?(substring) click to toggle source

`true` if this string ends with the substring

# File lib/epitools/core_ext/string.rb, line 436
def endswith?(substring)
  self[-substring.size..-1] == substring
end
Also aliased as: endswith
eval_block(code, block) click to toggle source
# File lib/epitools/core_ext/string.rb, line 673
def eval_block(code, block)
  eval code, block && block.binding
end
float?() click to toggle source

Could this string be cast to an float?

# File lib/epitools/core_ext/truthiness.rb, line 112
def float?
  !!strip.match(/^-?\d+\.\d+$/)
end
from_base(base=10) click to toggle source

Convert a string encoded in some base <= 64 into an integer. (See Integer#to_base for more info.)

# File lib/epitools/core_ext/string.rb, line 329
def from_base(base=10)
  n = 0
  chars.reverse_each.with_index do |c, power|
    value = BASE_DIGITS[c]
    n += (base**power) * value
  end
  n
end
from_base62() click to toggle source
# File lib/epitools/core_ext/string.rb, line 338
def from_base62
  from_base(62)
end
from_base64() click to toggle source

Decode a mime64/base64 encoded string

# File lib/epitools/core_ext/string.rb, line 353
def from_base64
  unpack("m").first
end
Also aliased as: decode64
from_bencode() click to toggle source

Convert Python serialized bencoded (pickled) objects to Ruby Objects

# File lib/epitools/core_ext/string.rb, line 370
def from_bencode
  BEncode.load(self)
end
from_hms() click to toggle source

Converts time duration strings (mm:ss, mm:ss.dd, hh:mm:ss, or dd:hh:mm:ss) to seconds. (The reverse of Integer#to_hms)

# File lib/epitools/core_ext/string.rb, line 488
def from_hms
  nums = split(':')

  nums[-1] = nums[-1].to_f if nums[-1] =~ /\d+\.\d+/ # convert fractional seconds to a float
  nums.map! { |n| n.is_a?(String) ? n.to_i : n } # convert the rest to integers

  nums_and_units = nums.reverse.zip %w[seconds minutes hours days]
  nums_and_units.map { |num, units| num.send(units) }.sum
end
from_json() click to toggle source

Parse this string as JSON

# File lib/epitools/core_ext/string.rb, line 444
def from_json
  JSON.parse(self)
end
from_marshal()
Alias for: unmarshal
from_yaml() click to toggle source

Parse this string as YAML

# File lib/epitools/core_ext/string.rb, line 451
def from_yaml
  YAML.load(self)
end
gunzip() click to toggle source

gunzip the string

# File lib/epitools/core_ext/string.rb, line 407
def gunzip
  data = StringIO.new(self)
  Zlib::GzipReader.new(data).read
end
gzip(level=nil) click to toggle source

gzip the string

# File lib/epitools/core_ext/string.rb, line 398
def gzip(level=nil)
  zipped = StringIO.new
  Zlib::GzipWriter.wrap(zipped, level) { |io| io.write(self) }
  zipped.string
end
hexdump() click to toggle source

Print a hexdump of the string to STDOUT (coloured, if the terminal supports it)

# File lib/epitools/core_ext/string.rb, line 501
def hexdump
  Hex.dump(self)
end
indent(prefix=" ") { |prefix| ... } click to toggle source

Indent all the lines, if “prefix” is a string, prepend that string to each lien. If it's an integer, prepend that many spaces.

# File lib/epitools/core_ext/string.rb, line 152
def indent(prefix="  ")
  prefix = (" " * prefix) if prefix.is_an? Integer

  if block_given?
    lines.each { |line| yield prefix + line }
  else
    lines.map { |line| prefix + line }.join('')
  end
end
indent_html(indent=2)
Alias for: nice_html
inflate() click to toggle source

inflate the string

# File lib/epitools/core_ext/string.rb, line 422
def inflate
  Zlib::Inflate.inflate(self)
end
integer?() click to toggle source

Could this string be cast to an integer?

# File lib/epitools/core_ext/truthiness.rb, line 105
def integer?
  !!strip.match(/^-?\d+$/)
end
md5() click to toggle source

MD5 the string

# File lib/epitools/core_ext/string.rb, line 377
def md5
  Digest::MD5.hexdigest self
end
nice_html(indent=2) click to toggle source

Use Nokogiri to parse this string as HTML, and return an indented version

# File lib/epitools/core_ext/string.rb, line 165
def nice_html(indent=2)
  Nokogiri::HTML.fragment(self).to_xhtml(indent: indent)
end
Also aliased as: nicehtml, indent_html
nice_lines() click to toggle source

Like each_line, but skips empty lines and removes n's.

# File lib/epitools/core_ext/string.rb, line 100
def nice_lines
  # note: $/ is the platform's newline separator
  split($/).select{|l| not l.blank? }
end
Also aliased as: nicelines, clean_lines
nicehtml(indent=2)
Alias for: nice_html
nicelines()
Alias for: nice_lines
number?() click to toggle source

Could this string be cast to an number?

# File lib/epitools/core_ext/truthiness.rb, line 119
def number?
  !!strip.match(/^-?\d\.?\d*$/)
end
present?() click to toggle source

Is there anything in the string? (ignoring whitespace/newlines)

# File lib/epitools/core_ext/truthiness.rb, line 133
def present?
  not blank?
end
rot13() click to toggle source

The Infamous Caesar-Cipher. Unbreakable to this day.

# File lib/epitools/core_ext/string.rb, line 268
def rot13
  tr('n-za-mN-ZA-M', 'a-zA-Z')
end
sentences() click to toggle source
# File lib/epitools/core_ext/string.rb, line 239
def sentences
  split_after(/[\.\!\?]+/).lazy.map {|s| s.strip.gsub(/\s+/, " ") }
end
sha1() click to toggle source

SHA1 the string

# File lib/epitools/core_ext/string.rb, line 384
def sha1
  Digest::SHA1.hexdigest self
end
sha256() click to toggle source

SHA256 the string

# File lib/epitools/core_ext/string.rb, line 391
def sha256
  Digest::SHA256.hexdigest self
end
shellescape() click to toggle source

Escape shell characters (globs, quotes, parens, etc.)

# File lib/epitools/core_ext/string.rb, line 27
def shellescape
  Shellwords.escape(self)
end
smash() click to toggle source

Smash together all the characters in a string (removing whitespace)

# File lib/epitools/core_ext/string.rb, line 41
def smash
  downcase.scan(/\w+/).join
end
split_after(boundary) click to toggle source
# File lib/epitools/core_ext/string.rb, line 140
def split_after(boundary)
  split_at(boundary, include_boundary: true)
end
split_at(boundary, options={}) click to toggle source
# File lib/epitools/core_ext/string.rb, line 118
def split_at(boundary, options={})
  include_boundary = options[:include_boundary] || false

  boundary = Regexp.new(Regexp.escape(boundary)) if boundary.is_a?(String)
  s        = StringScanner.new(self)

  Enumerator.new do |yielder|
    loop do
      if match = s.scan_until(boundary)
        if include_boundary
          yielder << match
        else
          yielder << match[0..-(s.matched_size+1)]
        end
      else
        yielder << s.rest if s.rest?
        break
      end
    end
  end
end
split_before(boundary) click to toggle source
# File lib/epitools/core_ext/string.rb, line 144
def split_before(boundary)
  raise "Why would you want this? Sorry, unimplemented. Send patches."
end
startswith(substring)
Alias for: startswith?
startswith?(substring) click to toggle source

`true` if this string starts with the substring

# File lib/epitools/core_ext/string.rb, line 428
def startswith?(substring)
  self[0...substring.size] == substring
end
Also aliased as: startswith
strip_ansi()
Alias for: strip_color
strip_color() click to toggle source

Remove ANSI color codes.

# File lib/epitools/core_ext/string.rb, line 92
def strip_color
  gsub(COLOR_REGEXP, '')
end
Also aliased as: strip_ansi
tighten() click to toggle source

Remove redundant whitespaces (not including newlines).

# File lib/epitools/core_ext/string.rb, line 34
def tighten
  gsub(/[\t ]+/,' ').strip
end
titlecase() click to toggle source

Return a new string converted to “Title Case” (first letter of each word capitalized)

# File lib/epitools/core_ext/string.rb, line 55
def titlecase
  first = true
  words = downcase.split(/(?<!\w')\b/)

  words.map.with_index do |word,i|
    if LOWERCASE_WORDS.include?(word) and i > 0 # leave LOWERCASE_WORDS lowercase, unless it's the first word.
      word
    else
      word.gsub(/^\w/) { |c| c.upcase } # capitalize first letter
    end
  end.join('')
end
titlecase!() click to toggle source

Convert string to “Title Case” (first letter of each word capitalized)

# File lib/epitools/core_ext/string.rb, line 71
def titlecase!
  replace(titlecase)
end
to_P()
Alias for: to_Path
to_Path() click to toggle source

Convert the string to a Path object (for representing files/directories).

# File lib/epitools/minimal.rb, line 269
def to_Path
  Path[self]
end
Also aliased as: to_P
to_URI()
Alias for: to_uri
to_base62() click to toggle source

Convert a string (encoded in base16 “hex” – for example, an MD5 or SHA1 hash) into “base62” format. (See Integer#to_base62 for more info.)

# File lib/epitools/core_ext/string.rb, line 346
def to_base62
  to_i(16).to_base62
end
to_base64() click to toggle source

Encode into a mime64/base64 string

# File lib/epitools/core_ext/string.rb, line 361
def to_base64
  [self].pack("m")
end
Also aliased as: base64, encode64
to_i_from_bytes(big_endian=false) click to toggle source

Raw bytes to an integer (as big as necessary)

# File lib/epitools/core_ext/string.rb, line 315
def to_i_from_bytes(big_endian=false)
  bs = big_endian ? bytes.reverse_each : bytes.each
  bs.with_index.inject(0) { |sum,(b,i)| (b << (8*i)) + sum }
end
to_params() click to toggle source

Convert a query string to a hash of params

# File lib/epitools/core_ext/string.rb, line 297
def to_params
  params = {}

  split(/[&;]/).each do |pairs|
    key, value = pairs.split('=',2).collect { |v| CGI.unescape(v) }

    if key and value
      params[key] ||= []
      params[key] << value
    end
  end

  params.map_values { |v| v.size > 1 ? v : v.first }
end
to_proc(&block) click to toggle source

String#to_proc

See: weblog.raganwald.com/2007/10/stringtoproc.html

Ported from the String Lambdas in Oliver Steele's Functional Javascript osteele.com/sources/javascript/functional/

This work is licensed under the MIT License:

© 2007 Reginald Braithwaite Portions Copyright © 2006 Oliver Steele

## Basic Usage

'x+1’.to_proc;

 3

'x+2*y'.to_proc[2, 3];

 8

or (more usefully) later:

square = 'x*x'.to_proc; square(3);

 9

square(4);

 16

## Explicit parameters

If the string contains a ->, this separates the parameters from the body.

'x y -> x+2*y'.to_proc[2, 3];

 8

'y x -> x+2*y'.to_proc[2, 3];

 7

Otherwise, if the string contains a _, it’s a unary function and _ is name of the parameter:

'_+1’.to_proc;

 3

'_*_’.to_proc;

 9

## Implicit parameters

If the string doesn’t specify explicit parameters, they are implicit.

If the string starts with an operator or relation besides -, or ends with an operator or relation, then its implicit arguments are placed at the beginning and/or end:

'*2’.to_proc;

 4

'/2’.to_proc;

 2

'2/‘.to_proc;

 0.5

'/'.to_proc[2, 4];

 0.5

’.’ counts as a right operator:

'.abs’.to_proc;

 1

Otherwise, the variables in the string, in order of occurrence, are its parameters.

'x+1’.to_proc;

 3

'x*x’.to_proc;

 9

'x + 2*y'.to_proc[1, 2];

 5

'y + 2*x'.to_proc[1, 2];

 5

## Chaining

Chain -> to create curried functions.

'x y -> x+y'.to_proc[2, 3];

 5

'x -> y -> x+y’.to_proc[3];

 5

plus_two = 'x -> y -> x+y’.to_proc; plus_two

 5

Using String#to_proc in Idiomatic Ruby

Ruby on Rails popularized Symbol#to_proc, so much so that it will be part of Ruby 1.9.

If you like:

%w[dsf fgdg fg].map(&:capitalize)

 ["Dsf", "Fgdg", "Fg"]

then %w[dsf fgdg fg].map(&'.capitalize') isn’t much of an improvement.

But what about doubling every value in a list:

(1..5).map &'*2'

 [2, 4, 6, 8, 10]

Or folding a list:

(1..5).inject &'+'

 15

Or having fun with factorial:

factorial = “(1.._).inject &'*'”.to_proc factorial

 120

LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

# File lib/epitools/core_ext/string.rb, line 638
def to_proc &block
  params = []
  expr = self
  sections = expr.split(/\s*->\s*/m)
  if sections.length > 1 then
      eval_block(sections.reverse!.inject { |e, p| "(Proc.new { |#{p.split(/\s/).join(', ')}| #{e} })" }, block)
  elsif expr.match(/\b_\b/)
      eval_block("Proc.new { |_| #{expr} }", block)
  else
      leftSection = expr.match(/^\s*(?:[+*\/%&|\^\.=<>\[]|!=)/m)
      rightSection = expr.match(/[+\-*\/%&|\^\.=<>!]\s*$/m)
      if leftSection || rightSection then
          if (leftSection) then
              params.push('$left')
              expr = '$left' + expr
          end
          if (rightSection) then
              params.push('$right')
              expr = expr + '$right'
          end
      else
          self.gsub(
              /(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_$\d]*:|self|arguments|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/, ''
          ).scan(
            /([a-z_$][a-z_$\d]*)/i
          ) do |v|
            params.push(v) unless params.include?(v)
          end
      end
      eval_block("Proc.new { |#{params.join(', ')}| #{expr} }", block)
  end
end
to_unix() click to toggle source

Convert rn to n

# File lib/epitools/core_ext/string.rb, line 20
def to_unix
  gsub("\r\n", "\n")
end
to_uri() click to toggle source

URI.parse the string and return an URI object

# File lib/epitools/core_ext/string.rb, line 289
def to_uri
  URI.parse self
end
Also aliased as: to_URI
truthy?() click to toggle source

Does this string contain something that means roughly “true”?

# File lib/epitools/core_ext/truthiness.rb, line 140
def truthy?
  case strip.downcase
  when "1", "true", "yes", "on", "enabled", "affirmative"
    true
  else
    false
  end
end
unmarshal() click to toggle source

Unmarshal the string (transform it into Ruby datatypes).

# File lib/epitools/core_ext/string.rb, line 458
def unmarshal
  Marshal.restore self
end
Also aliased as: from_marshal
urldecode() click to toggle source

Convert an URI's %XXes into regular characters.

# File lib/epitools/core_ext/string.rb, line 282
def urldecode
  URI.unescape(self)
end
urlencode() click to toggle source

Convert non-URI characters into %XXes.

# File lib/epitools/core_ext/string.rb, line 275
def urlencode
  URI.escape(self)
end
without_stopwords()
word_wrap(width=nil)
Alias for: wrap
words() click to toggle source
# File lib/epitools/core_ext/string.rb, line 243
def words
  scan /[[:alnum:]]+/
end
words_without_stopwords() click to toggle source
# File lib/epitools/core_ext/string.rb, line 247
def words_without_stopwords
  downcase.words - STOP_WORDS
end
Also aliased as: without_stopwords
wrap(width=nil) { |s| ... } click to toggle source

Word-wrap the string so each line is at most `width` wide. Returns a string, or, if a block is given, yields each word-wrapped line to the block.

If `width` is nil, find the current width of the terminal and use that. If `width` is negative, subtract `width` from the terminal's current width.

# File lib/epitools/core_ext/string.rb, line 179
def wrap(width=nil)
  if width.nil? or width < 0
    term_width, _ = Term.size

    if width and width < 0
      width = (term_width - 1) + width
    else
      width = term_width - 1
    end
  end

  return self if size <= width

  strings   = []
  start_pos = 0
  end_pos   = width

  loop do
    split_pos = rindex(/\s/, end_pos) || end_pos

    strings << self[start_pos...split_pos]

    start_pos = index(/\S/, split_pos)
    break if start_pos == nil
    end_pos   = start_pos + width

    if end_pos > size
      strings << self[start_pos..-1]
      break
    end
  end

  if block_given?
    strings.each { |s| yield s }
  else
    strings.join("\n")
  end
end
Also aliased as: word_wrap
wrap_and_indent(prefix, width=nil) click to toggle source

Wrap all lines at window size, and indent

# File lib/epitools/core_ext/string.rb, line 224
def wrap_and_indent(prefix, width=nil)
  prefix = " "*prefix if prefix.is_a? Numeric

  prefix_size = prefix.strip_color.size

  if width
    width = width - prefix_size
  else
    width = -prefix_size
  end

  wrap(width).each_line.map { |line| prefix + line }.join
end
Also aliased as: wrapdent
wrapdent(prefix, width=nil)
Alias for: wrap_and_indent