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
|