require 'Win32/Console/ANSI' if RUBY_PLATFORM =~ /win32/ ## # cute. # # >> "this is red".red # # >> "this is red with a blue background (read: ugly)".red_on_blue # # >> "this is red with an underline".red.underline # # >> "this is really bold and really blue".bold.blue # # >> Colored.red "This is red" # but this part is mostly untested module Colored extend self COLORS = { 'black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37 } EXTRAS = { 'clear' => 0, 'bold' => 1, 'underline' => 4, 'reversed' => 7 } COLORS.each do |color, value| define_method(color) do colorize(self, :foreground => color) end define_method("on_#{color}") do colorize(self, :background => color) end COLORS.each do |highlight, value| next if color == highlight define_method("#{color}_on_#{highlight}") do colorize(self, :foreground => color, :background => highlight) end end end EXTRAS.each do |extra, value| next if extra == 'clear' define_method(extra) do colorize(self, :extra => extra) end end define_method(:to_eol) do tmp = sub(/^(\e\[[\[\e0-9;m]+m)/, "\\1\e[2K") if tmp == self return "\e[2K" << self end tmp end def colorize(string, options = {}) colored = [color(options[:foreground]), color("on_#{options[:background]}"), extra(options[:extra])].compact * '' colored << string colored << extra(:clear) end def colors @@colors ||= COLORS.keys.sort end def extra(extra_name) extra_name = extra_name.to_s "\e[#{EXTRAS[extra_name]}m" if EXTRAS[extra_name] end def color(color_name) background = color_name.to_s =~ /on_/ color_name = color_name.to_s.sub('on_', '') return unless color_name && COLORS[color_name] "\e[#{COLORS[color_name] + (background ? 10 : 0)}m" end end unless Object.const_defined? :Colored String.send(:include, Colored)