41

How can I make the puts commands I output from a commandline based ruby program colour? I would appreciated any references to how I call each different colour also.

Lets say we start with this..

puts "The following word is blue.. Im Blue!"
puts "The following word is green.. Im Green!"
puts "The following word is red.. Im Red!"

And I get different text I want in different colours I want, You get the idea.

Im using Ubuntu, would I need to change my approach so that the program outputs correctly in diff os?

Jeremy Mack
  • 4,987
  • 2
  • 25
  • 22
Evolve
  • 8,939
  • 12
  • 51
  • 63
  • 1
    I was thinking of the ruby command line text when I asked my question back in 2010. The question has over 11,000 views and a stack of external links. I wouldn't have thought to look for 'colorized ruby output' when I was forming my question and infact couldn't find that answer at the time when searching. The implied answers may be similar but the questions are posed quite differently. I see both questions distinct, happy to have them linked though. – Evolve Mar 03 '14 at 05:42

10 Answers10

58

I found this article describing a very easy way to write coloured texts to the console. The article describes this little example which seems to do the trick (I took the liberty to improve it slightly):

def colorize(text, color_code)
  "\e[#{color_code}m#{text}\e[0m"
end

def red(text); colorize(text, 31); end
def green(text); colorize(text, 32); end

# Actual example
puts 'Importing categories [ ' + green('DONE') + ' ]'
puts 'Importing tags       [' + red('FAILED') + ']'

Best seems to define some of the colours. You can extent the example when you need also different background colours (see bottom of article).

When using Window XP, the author mentions the requirement of a gem called win32console.

Veger
  • 37,240
  • 11
  • 105
  • 116
  • 1
    To make it even easier to use, you can extend the String class ("Hello".red): `class String; def red; colorize(self, "\033[31m"); end; end`. Check this thread as well: [Colorized Ruby output](http://stackoverflow.com/questions/1489183/colorized-ruby-output) – Adriano P Jul 18 '12 at 16:25
38

I find the Colored gem to be the easiest and cleanest to use.

puts "this is red".red
puts "this is red with a blue background (read: ugly)".red_on_blue
puts "this is red with an underline".red.underline
puts "this is really bold and really blue".bold.blue
logger.debug "hey this is broken!".red_on_yellow 
Mark Carey
  • 1,567
  • 10
  • 9
6

I've created something like this:

begin
   require 'Win32/Console/ANSI' if PLATFORM =~ /win32/
rescue LoadError
   raise 'You must gem install win32console to use color on Windows'
end

class Colors
   COLOR1 = "\e[1;36;40m"
   COLOR2 = "\e[1;35;40m"
   NOCOLOR = "\e[0m"
   RED = "\e[1;31;40m"
   GREEN = "\e[1;32;40m"
   DARKGREEN = "\e[0;32;40m"
   YELLOW = "\e[1;33;40m"
   DARKCYAN = "\e[0;36;40m"
end

class String
   def color(color)
      return color + self + Colors::NOCOLOR
   end
end

Now you can just use another method of String:

"Hello World".color(Colors::DARKGREEN)

To know all the colors just execute this:

begin
  require 'Win32/Console/ANSI' if PLATFORM =~ /win32/
rescue LoadError
  raise 'You must gem install win32console to use color on Windows'
end

[0, 1, 4, 5, 7].each do |attr|
  puts '----------------------------------------------------------------'
  puts "ESC[#{attr};Foreground;Background"
  30.upto(37) do |fg|
    40.upto(47) do |bg|
      print "\033[#{attr};#{fg};#{bg}m #{fg};#{bg}  "
    end
  puts "\033[0m"
  end
end
darek129
  • 61
  • 1
5

use escape sequence \033 instead of \e as it is 100% posix compatible and will work on bsd-ish (e.g. osx) systems as well. the latter is a gnu extension.

glasz
  • 2,526
  • 25
  • 24
4

Thought I'd add another solution as it does things a little differently and includes more colour codes:

First some examples...

Using method chaining:

String.include(AnsiTextStyles)

puts "How are you?".blue.bold + " " + 'I am good!'.red.bold
puts '%s %s' % ["How are you?".blue.bold, 'I am good!'.red.bold]

Using the style method and applying multiple attributes:

puts "How are you?".style(:red)
puts 'I am good!'.style(:blue, :underline)
puts 'Good to hear'.style([:bg_magenta, :blink])

This can be used to store style attributes in some manner to apply later:

text_styles = {
    red_bold:       [:red, :bold],
    blue_underline: [:blue, :underline],
    pretty:         [:bg_magenta, :blink],
  }

text_styles.each do |name, style|
  styled_text = "Text styled multiple ways".style(style)
  puts "%s: %s" % [name, styled_text]
end

I've given a few more examples on this gist I created and expanded the code to include refinements so that modifications to String are scoped.

This is the basic code:

module AnsiTextStyles

  TEXT_ATTRIBUTES = {
      # text properties
      none: 0, # turn off all attributes
      bold: 1, bright: 1, # these do the same thing really
      italic: 3, underline: 4, blink: 5,
      reverse: 7, # swap foreground and background colours
      hide: 8, # foreground color same as background

      # foreground colours
      black: 30, grey: 90, lt_grey: 37, :white => 97,
      red: 31, lt_red: 91, 
      green: 32, lt_green: 92,
      dk_yellow: 33, brown: 33, yellow: 93,
      blue: 34, lt_blue: 94,
      magenta: 35, pink: 95, lt_magenta: 95,
      cyan: 36, lt_cyan: 96,
      default: 39,

      # background colours
      bg_black: 40, bg_grey: 100, bg_lt_grey: 47, bg_white: 107,
      bg_red: 41, bg_lt_red: 101,
      bg_green: 42, bg_lt_green: 102,
      bg_dk_yellow: 43, bg_brown: 43, bg_yellow: 103,
      bg_blue: 44, bg_lt_blue: 104,
      bg_magenta: 45, bg_pink: 105, bg_lt_magenta: 105,
      bg_cyan: 46, bg_lt_cyan: 106,
    }

  def self.text_attributes
    TEXT_ATTRIBUTES.keys
  end

  # applies the text attributes to the current string
  def style(*text_attributes)
    codes = TEXT_ATTRIBUTES.values_at(*text_attributes.flatten).compact
    "\e[%sm%s\e[m" % [codes.join(';'), self.to_s]
  end

end
br3nt
  • 9,017
  • 3
  • 42
  • 63
  • Nice one! Thanks for the addition, I'm sure a few peeps will find this useful, love the clever use of method chaining :) – Evolve Aug 04 '16 at 08:16
2

Use Colorize gem! Check it out:

https://github.com/fazibear/colorize

Installation:

sudo gem install colorize

usage:

require 'colorize'

puts "I am now red.".red
puts "I am now blue.".green
puts "I am a super coder".yellow
mpz
  • 1,906
  • 3
  • 15
  • 23
1

Check out the following libraries:

http://www.gnu.org/software/ncurses/ncurses.html

https://github.com/JEG2/highline

http://coderay.rubychan.de/

Community
  • 1
  • 1
St.Woland
  • 5,357
  • 30
  • 30
1

For a quick and dirty solution you can just embed ASCII colour codes in your strings (\e[XXm sets the colour to be used from now on to XX and \e[0m reset the colour to normal):

puts "The following word is blue.. \e[34mIm Blue!\e[0m"
puts "The following word is green.. \e[32mIm Green!\e[0m"
puts "The following word is red.. \e[31mIm Red!\e[0m"

ASCII codes also support things like underlining, blinking, and highlighting of text.

There also seems to be a helper library available that deals with the actual ASCII codes for you.

Edit: regarding the different platforms: you shouldn't have any trouble using ASCII codes on unix machines, but windows, AFAIK, doesn't support them out of the box. Fortunately there's a win32console gem that seems to fix this.

You can use the following snippet (found on the page Veger linked to) to load the win32console library only on windows:

begin
  require 'Win32/Console/ANSI' if PLATFORM =~ /win32/
rescue LoadError
  raise 'You must gem install win32console to use color on Windows'
end
liwp
  • 6,746
  • 1
  • 27
  • 39
1

Check out the cli-colorize gem: http://github.com/stjohncj/cli-colorize/blob/master/README.rdoc

Chris
  • 11
  • 1
1

My suggestion: The paint gem. It does not enforce string extensions and supports 256-colors (with fall-back mode for non-256-color terminals).

Usage:

puts Paint["I'm blue!", :blue]
puts Paint["I'm dark blue if your terminal supports it!", "#000044"]
J-_-L
  • 9,079
  • 2
  • 40
  • 37