File: string_extensions.rb

package info (click to toggle)
ruby-highline 1.6.13-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 616 kB
  • sloc: ruby: 4,657; makefile: 2
file content (131 lines) | stat: -rw-r--r-- 4,493 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# Extensions for class String
#
# HighLine::String is a subclass of String with convenience methods added for colorization.
#
# Available convenience methods include:
#   * 'color' method         e.g.  highline_string.color(:bright_blue, :underline)
#   * colors                 e.g.  highline_string.magenta
#   * RGB colors             e.g.  highline_string.rgb_ff6000
#                             or   highline_string.rgb(255,96,0)
#   * background colors      e.g.  highline_string.on_magenta
#   * RGB background colors  e.g.  highline_string.on_rgb_ff6000
#                             or   highline_string.on_rgb(255,96,0)
#   * styles                 e.g.  highline_string.underline
#
# Additionally, convenience methods can be chained, for instance the following are equivalent:
#   highline_string.bright_blue.blink.underline
#   highline_string.color(:bright_blue, :blink, :underline)
#   HighLine.color(highline_string, :bright_blue, :blink, :underline)
#
# For those less squeamish about possible conflicts, the same convenience methods can be 
# added to the builtin String class, as follows:
#
#  require 'highline'
#  Highline.colorize_strings

class HighLine
  def self.String(s)
    HighLine::String.new(s)
  end
  
  module StringExtensions
    def self.included(base)
      HighLine::COLORS.each do |color|
        base.class_eval <<-END
          if public_instance_methods.map { |m| m.to_s }.
                                     include? "#{color.downcase}"
            undef :#{color.downcase}
          end
          def #{color.downcase}
            color(:#{color.downcase})
          end
        END
        base.class_eval <<-END
          if public_instance_methods.map { |m| m.to_s }.
                                     include? "on_#{color.downcase}"
            undef :on_#{color.downcase}
          end
          def on_#{color.downcase}
            on(:#{color.downcase})
          end
        END
        HighLine::STYLES.each do |style|
          base.class_eval <<-END
            if public_instance_methods.map { |m| m.to_s }.
                                       include? "#{style.downcase}"
              undef :#{style.downcase}
            end
            def #{style.downcase}
              color(:#{style.downcase})
            end
          END
        end
      end
      
      base.class_eval do
        if public_instance_methods.map { |m| m.to_s }.include? "color"
          undef :color
        end
        if public_instance_methods.map { |m| m.to_s }.include? "foreground"
          undef :foreground
        end
        def color(*args)
          self.class.new(HighLine.color(self, *args))
        end
        alias_method :foreground, :color
        
        if public_instance_methods.map { |m| m.to_s }.include? "on"
          undef :on
        end
        def on(arg)
          color(('on_' + arg.to_s).to_sym)
        end

        if public_instance_methods.map { |m| m.to_s }.include? "uncolor"
          undef :uncolor
        end
        def uncolor
          self.class.new(HighLine.uncolor(self))
        end
        
        if public_instance_methods.map { |m| m.to_s }.include? "rgb"
          undef :rgb
        end
        def rgb(*colors)
          color_code = colors.map{|color| color.is_a?(Numeric) ? '%02x'%color : color.to_s}.join
          raise "Bad RGB color #{colors.inspect}" unless color_code =~ /^[a-fA-F0-9]{6}/
          color("rgb_#{color_code}".to_sym)
        end
        
        if public_instance_methods.map { |m| m.to_s }.include? "on_rgb"
          undef :on_rgb
        end
        def on_rgb(*colors)
          color_code = colors.map{|color| color.is_a?(Numeric) ? '%02x'%color : color.to_s}.join
          raise "Bad RGB color #{colors.inspect}" unless color_code =~ /^[a-fA-F0-9]{6}/
          color("on_rgb_#{color_code}".to_sym)
        end
        
        if public_instance_methods.map { |m| m.to_s }.include? "method_missing"
          undef :method_missing
        end
        # TODO Chain existing method_missing
        def method_missing(method, *args, &blk)
          if method.to_s =~ /^(on_)?rgb_([0-9a-fA-F]{6})$/
            color(method)
          else
            raise NoMethodError, "undefined method `#{method}' for #<#{self.class}:#{'%#x'%self.object_id}>"
          end
        end
      end
    end
  end
  
  class HighLine::String < ::String
    include StringExtensions
  end
  
  def self.colorize_strings
    ::String.send(:include, StringExtensions)
  end
end