Terminal colours made simple
Over the weekend, I pushed out the first release of the tco gem. Its goal is to make working with terminal colours as simple as possible; hence the name tco. The main feature of this tool is the way it works with colours. Instead of an oddly organised sequence of colour codes, tco uses simple RGB. It provides a library for your Ruby gems and apps, and also a standalone command-line tool that you can use anywhere else.
If you’ve ever worked with the extended colour palette in the terminal, you probably know that it’s not really easy to find the colour you want. The palette consists of 256 colours that are evenly sampled through the RGB space. As opposed to the ANSI palette, the colours tend to be the same across different terminals. They are assigned linearly to a set of escape sequences that are used to apply the colours. And that is the problem; searching through the palette is very unintuitive.
On the other hand, selecting a RGB colour using your favourite
colour picker is a nice, buttery piece of cake
with a bit of cream on top. That is everything you need to do; pass the value
to tco
and it will sort out all the boring bits for you. Using the
RGB value, the library will find the perceptually closest option that is
displayable in your terminal and decorate the string with the appropriate
escape sequences, letting you focus on more interesting things in life instead.
How does it work then?
Let me start with explaining the tco
command-line tool first. Among all
the parameters it accepts, there are four essential ones that control directly
how the output will look like. That includes setting the foreground -f
and background -b
colours, and also the bold -B
and underline
-u
flags. The actual input can be passed either as an argument or piped to
stdin. See the following examples:
In most cases, you will probably use several colours and settings over and over
again. To help you with that, tco comes with configurable colour names and
style definitions. You can set them either system-wide in /etc/tco.conf
or just for a single user in the ~/.tco.conf
file (for more information on
its format, see the example on
Github). Once
you’ve configured some, you can access them through the -s
option.
Fairly often, you might want to decorate different parts of a string with
different colours. Instead of having to split the string and print it in parts,
you can use a simple template syntax to indicate how should each of the
parts be decorated. These templates are enclosed in double curly brackets
{{ }}
. The first part of a template is the colour
definition fg:bg:ub
, followed by a space and the string to be decorated.
You can even nest them; see the few examples below:
There are a few more options available for different things; get the full
up-to-date list by passing -h
to the program.
Using the Ruby library
tco
is a gem, so you can use the same functionality in your own Ruby apps and
scripts too. The interface is pretty simple with just a few methods that cover
all the functionality. For convenience, there is a String
extension that
makes these functions accessible directly from all string objects.
require 'tco'
puts "Red font on grey background".fg("#ff0000").bg("#bebebe")
puts "Bold and underlined".bold.underline
puts "{{#000:#ff0000 R}}{{#000:#00ff00 G}}{{#000:#0000ff B}}".decorate
Most applications are likely to use a fixed palette of colours only. Therfore, it is really simple to reconfigure the library to match the needs of your program. You can define your own colour names and styles to which you can refer to later on. These settings will be applied on top of the user and system configurations, but they won’t be saved when you application terminates. The following example shows exactly how to do it:
require "tco"
conf = Tco.config
conf.names["purple"] = "#622e90"
conf.names["dark-blue"] = "#2d3091"
conf.names["blue"] = "#00aaea"
conf.names["green"] = "#02a552"
conf.names["yellow"] = "#fdea22"
conf.names["orange"] = "#f37f5a"
conf.names["red"] = "#eb443b"
Tco.reconfigure conf
rainbow = ["purple", "dark-blue", "blue", "green", "yellow", "orange", "red"]
10.times do
rainbow.each { |colour| print " ".bg colour }
puts
end
If you would like to get really crazy, you can even render a very low
resolution images inside the terminal. You’ll need to print roughly 2 spaces
for each pixel (it’s not perfect, but close enough). The following example
reads a PNG picture of the Tux using the rmagick
gem and displays it in the
terminal.
#!/usr/bin/env ruby
require "tco"
require "rmagick"
Magick::Image.read("tux.png")[0].each_pixel do |pixel, col, row|
c = [pixel.red, pixel.green, pixel.blue].map { |v| 255*(v/65535.0) }
print " ".bg c
puts if col >= 53
end
Summary
And that’s it! It’s quite a simple gem, but it can help you make your console apps more lively and their output much easier to navigate with barely any additional effort. It’s available right now on RubyGems, the sources are hosted on GitHub, licensed under MIT.
If you have any questions, comments, suggestions, or problems, please let me know, I’ll be happy to help you :-).