Class: String

Inherits:
Object show all
Includes:
WithKnowledgeOfColor
Defined in:
lib/quality_extensions/color/rgb.rb,
lib/quality_extensions/range_list.rb,
lib/quality_extensions/string/md5.rb,
lib/quality_extensions/string/prefix.rb,
lib/quality_extensions/string/to_proc.rb,
lib/quality_extensions/console/command.rb,
lib/quality_extensions/string/numeric_eh.rb,
lib/quality_extensions/string/digits_only.rb,
lib/quality_extensions/symbol/constantize.rb,
lib/quality_extensions/string/shell_escape.rb,
lib/quality_extensions/colored/toggleability.rb,
lib/quality_extensions/string/safe_in_comment.rb,
lib/quality_extensions/string/each_char_with_index.rb,
lib/quality_extensions/string/to_underscored_label.rb,
lib/quality_extensions/string/safe_numeric_conversion.rb,
lib/quality_extensions/string/with_knowledge_of_color.rb,
lib/quality_extensions/test/difference_highlighting-minitest.rb,
lib/quality_extensions/test/difference_highlighting-test_unit.rb

Overview

Author

Tyler Rick

Copyright

Copyright © 2007 QualitySmith, Inc.

License

Ruby License

Submit to Facets?

Probably not.

Developer notes:

  • Can we use a more general method instead (like humanize or methodize)? Does this really have a use distinct from all the other inflection methods out there?

++

Constant Summary collapse

Range_list_item_format =

Range_list_item_format = /(d+)(-(d+))?/ # if only - is allowed as delimiter within a range

/(\d+)((-|\.\.|\.\.\.)(\d+))?/
Range_list_format =
/^#{Range_list_item_format}(,#{Range_list_item_format})*$/
@@colorize_enabled =
true

Constants included from WithKnowledgeOfColor

WithKnowledgeOfColor::Color_regexp

Instance Method Summary collapse

Methods included from WithKnowledgeOfColor

#length_without_color, #ljust_with_color, #nonprinting_characters_used_for_color, #rjust_with_color, #strip_color

Instance Method Details

#__std__to_fObject



32
# File 'lib/quality_extensions/string/safe_numeric_conversion.rb', line 32

alias __std__to_f to_f

#__std__to_iObject



31
# File 'lib/quality_extensions/string/safe_numeric_conversion.rb', line 31

alias __std__to_i to_i

#colorize_with_toggleability(string, options = {}) ⇒ Object



18
19
20
21
22
23
24
# File 'lib/quality_extensions/colored/toggleability.rb', line 18

def colorize_with_toggleability(string, options = {})
  if @@colorize_enabled
    colorize_without_toggleability(string, options)
  else
    string
  end
end

#constantizeObject

Tries to find a declared constant with the name specified in self.

'Foo'.constantize => Foo

Unlike ActiveSupport, we don’t do this check (because Kernel.module “can handle module hierarchy”):

vendor/rails/activesupport/lib/active_support/inflector.rb
  unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
    raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
  end


37
38
39
# File 'lib/quality_extensions/symbol/constantize.rb', line 37

def constantize
  Kernel.constant(self)
end

#digits_onlyObject

Strips out everything except digits.



10
11
12
# File 'lib/quality_extensions/string/digits_only.rb', line 10

def digits_only
  self.gsub(/[^0-9]/, "")
end

#each_char_with_indexObject



12
13
14
15
16
17
18
# File 'lib/quality_extensions/string/each_char_with_index.rb', line 12

def each_char_with_index
  i = 0
  split(//).each do |c|
    yield i, c
    i += 1
  end
end

#highlight_absenceObject

This is a (sub)string that doesn’t exist in self, only in the other string. It’s just a placeholder character (a space) that represents a missing character.



55
56
57
# File 'lib/quality_extensions/test/difference_highlighting-minitest.rb', line 55

def highlight_absence
  self.white.on_cyan.bold
end

#highlight_commonalityObject

This is a (sub)string that is common to both expected and actual



32
33
34
35
36
37
38
# File 'lib/quality_extensions/test/difference_highlighting-minitest.rb', line 32

def highlight_commonality
  self.
    make_control_characters_visible.
    make_spaces_visible(:green).
    green.bold
    #send_unless(self == ' ', :bold)     # spaces are not bold; '_'s (and everything else) are
end

#highlight_differenceObject

This is a (sub)string that is different between expected and actual



40
41
42
43
44
45
46
# File 'lib/quality_extensions/test/difference_highlighting-minitest.rb', line 40

def highlight_difference
  self.
    make_control_characters_visible.
    make_spaces_visible(:red).
    red.bold
    #send_unless(self == ' ', :bold)     # spaces are not bold; '_'s (and everything else) are
end

#highlight_uniqueObject

This is a (sub)string that exists only in self, not in the other string



48
49
50
51
52
53
# File 'lib/quality_extensions/test/difference_highlighting-minitest.rb', line 48

def highlight_unique
  self.
    make_control_characters_visible.
    make_spaces_visible(:magenta).
    magenta
end

#integer?Boolean

returns true if the string is a valid integer (which can be converted to an Integer using the Integer() or String#to_i methods); otherwise returns false

Returns:

  • (Boolean)


20
21
22
23
# File 'lib/quality_extensions/string/numeric_eh.rb', line 20

def integer?
  # not the empty string and containing only 1 or more digits
  !self.empty? && !!(self =~ /\A[-+]?\d+\Z/)
end

#make_control_characters_visibleObject



62
63
64
65
66
67
# File 'lib/quality_extensions/test/difference_highlighting-minitest.rb', line 62

def make_control_characters_visible 
  self.gsub(/\n/, '\n'+"\n").   # Show '\n' in addition to actually doing the line break
       gsub(/\r/, '\r').        # Just escape it...
       gsub(/\t/, '\t')
  #:todo: Add other control characters?
end

#make_spaces_visible(color) ⇒ Object



58
59
60
61
# File 'lib/quality_extensions/test/difference_highlighting-minitest.rb', line 58

def make_spaces_visible(color)
  #:todo: Make this optional? Might be useful if you are comparing things with lots of spaces and underscores and you want to be able to tell the difference between them...?
  self.gsub(' ', ' '.send(:"on_#{color}"))
end

#md5Object

Because it’s so much more natural to have this as a method of the string rather than having to call Digest::MD5.hexdigest(string).



12
13
14
# File 'lib/quality_extensions/string/md5.rb', line 12

def md5
  return Digest::MD5.hexdigest(self)
end

#numeric?Boolean

returns true if the string is a valid number (which can be converted to an actual number using the Float() or String#to_f methods); otherwise returns false

Returns:

  • (Boolean)


15
16
17
# File 'lib/quality_extensions/string/numeric_eh.rb', line 15

def numeric?
  !self.empty? && !!Float(self) rescue false
end

#option_demethodizeObject



39
40
41
# File 'lib/quality_extensions/console/command.rb', line 39

def option_demethodize
  self.sub('__','--').gsub('_','-')
end

#option_methodizeObject



42
43
44
# File 'lib/quality_extensions/console/command.rb', line 42

def option_methodize
  self.gsub('-','_')
end

#prefix(prefix) ⇒ Object



11
12
13
# File 'lib/quality_extensions/string/prefix.rb', line 11

def prefix(prefix)
  sub(/^/, prefix)
end

#prefix_lines(prefix) ⇒ Object




29
30
31
# File 'lib/quality_extensions/string/prefix.rb', line 29

def prefix_lines(prefix)
  gsub(/^/, prefix)
end

#safe_in_commentObject



13
14
15
# File 'lib/quality_extensions/string/safe_in_comment.rb', line 13

def safe_in_comment
  gsub('-', '-')
end

#shell_escapeObject



12
13
14
# File 'lib/quality_extensions/string/shell_escape.rb', line 12

def shell_escape
  Escape.shell_command([self])
end

#suffix(suffix) ⇒ Object



19
20
21
# File 'lib/quality_extensions/string/prefix.rb', line 19

def suffix(suffix)
  sub(/$/, suffix)
end

#suffix_lines(suffix) ⇒ Object



37
38
39
# File 'lib/quality_extensions/string/prefix.rb', line 37

def suffix_lines(suffix)
  gsub(/$/, suffix)
end

#to_fObject



45
46
47
48
49
50
# File 'lib/quality_extensions/string/safe_numeric_conversion.rb', line 45

def to_f()
  case self
  when /^[-+]?\d/          then  __std__to_f
  else raise NumericError, "Cannot convert string to Float!"
  end
end

#to_iObject



36
37
38
39
40
41
42
43
# File 'lib/quality_extensions/string/safe_numeric_conversion.rb', line 36

def to_i()
  case self
  when /^[-+]?0\d/         then  __std__oct
  when /^[-+]?0x[a-f\d]/i  then  __std__hex
  when /^[-+]?\d/          then  __std__to_i
  else raise NumericError, "Cannot convert string to Integer!"
  end
end

#to_proc(&block) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/quality_extensions/string/to_proc.rb', line 34

def to_proc &block
  params = []
  expr = self
  sections = expr.split(/\s*->\s*/m)
  if sections.length > 1 then
      eval sections.reverse!.inject { |e, p| "(Proc.new { |#{p.split(/\s/).join(', ')}| #{e} })" }, block && block.binding
  elsif expr.match(/\b_\b/)
      eval "Proc.new { |_| #{expr} }", block && block.binding
  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 "Proc.new { |#{params.join(', ')}| #{expr} }", block && block.binding
  end
end

#to_range_listObject

A “range list” is an array of numbers and ranges, for example [1..3, 5, 7..9], and is a way to represent “discontiguous ranges” (something a single Range object cannot do, unfortunately).

See also: Array#expand_ranges

Name: to_range_list? parse_range_list?

To do:

  • Allow other format styles besides a-b and a..b and a…b : (a,b), [a,b], [a,b)

  • Allow indeterminate ranges like ‘7-’ (7 to infinity)?



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/quality_extensions/range_list.rb', line 94

def to_range_list
  raise RangeList::FormatError unless match(Range_list_format)
  array = split(',')
  array.map! {|e|
    md = e.match(/^#{Range_list_item_format}$/)
    range_type = md[3]
    points = [md[1], md[4]].compact.map(&:to_i)
    case points.size
    when 1
      points[0]
    when 2
      case range_type
      when '...'
        points[0] ... points[1]
      when '-', '..'
        points[0] .. points[1]
      else
        raise "Unexpected range_type #{range_type}"
      end
    end
  }
  array.to_range_list
end

#to_rgbObject



23
24
25
# File 'lib/quality_extensions/color/rgb.rb', line 23

def to_rgb
  self.hex.to_rgb
end

#to_underscored_labelObject

Strips out most non-alphanumeric characters and leaves you with a lowercased, underscored string that can safely be used as a class_name



12
13
14
15
16
17
18
19
# File 'lib/quality_extensions/string/to_underscored_label.rb', line 12

def to_underscored_label
  self.
    downcase.
    gsub(/-+/, "_").gsub(/ +/, "_").  # spaces and -'s-> underscores
    gsub(/[^a-z0-9_]/, "").           # keep only alphanumeric and _ characters
    gsub(/_+$/, "").                   # We don't want any _ characters at the end
    gsub(/^_+/, "")                   # ... or the beginning 
end

#unprefix(prefix) ⇒ Object



15
16
17
# File 'lib/quality_extensions/string/prefix.rb', line 15

def unprefix(prefix)
  sub(/^#{Regexp.escape(prefix)}/, "")
end

#unprefix_lines(prefix) ⇒ Object



33
34
35
# File 'lib/quality_extensions/string/prefix.rb', line 33

def unprefix_lines(prefix)
  gsub(/^#{Regexp.escape(prefix)}/, "")
end

#unsuffix(suffix) ⇒ Object



23
24
25
# File 'lib/quality_extensions/string/prefix.rb', line 23

def unsuffix(suffix)
  sub(/#{Regexp.escape(suffix)}$/, "")
end

#unsuffix_lines(suffix) ⇒ Object



41
42
43
# File 'lib/quality_extensions/string/prefix.rb', line 41

def unsuffix_lines(suffix)
  gsub(/#{Regexp.escape(suffix)}$/, "")
end