TableTennis is a Ruby library for printing stylish tables in your terminal.
require "table_tennis"
options = { title: "Star Wars People", zebra: true, color_scale: :height }
puts TableTennis.new(Starwars.all, options)
Prints this lovely table in your terminal:
# install gem
$ gem install table_tennis
# or add to your Gemfile
gem "table_tennis"
- auto-themes to pick light or dark based on your terminal background
- auto-layout to fit your terminal window
- auto-format floats and dates
- auto-color numeric columns
- auto-link markdown links
- titles, row numbers, zebra stripes...
TableTennis examines the background color of your terminal to pick either the dark or light theme. You can also specify :dark
or :light
manually, or even an :ansi
theme to use your terminal's default colors. This feature is surprisingly complicated.
Construct your table with an array of rows. Rows are hashes, ActiveRecord objects, structs, Data records, or anything that responds to to_h
. It also supports oddballs like arrays (as rows) or even a single hash.
puts TableTennis.new([{a: "hello", b: "world"}, {a: "foo", b: "bar"}])
puts TableTennis.new(Recipe.all.to_a) # activerecord
puts TableTennis.new(array_of_structs) # these use to_h
puts TableTennis.new([[1,2],[3,4]]) # array of arrays
puts TableTennis.new(authors[0]) # single hash
Here is a more complex example to get you started:
options = {
color_scales: :commission,
columns: %i[ name commission bday phone ],
mark: -> { _1[:name] =~ /jane|john/i },
row_numbers: true,
save: "/tmp/people.csv",
search: "february",
title: "Employees",
zebra: true,
}
option | default | details |
---|---|---|
color_scales |
─ | Color code a column of floats, similar to the "conditional formatting" feature in Google Sheets. See docs below. |
columns |
─ | Manually set which columns to include. Leave unset to show all columns. |
headers |
─ | Specify some or all column headers. For example, {user_id: "Customer"} . When unset, headers are inferred. |
mark |
─ | mark is a way to highlight specific columns with a nice color. For example, use mark: ->(row) { row[:planet] == "tatooine" } to highlight those rows. Your lambda can also return a specific bg color or Paint color array. |
row_numbers |
false |
Show row numbers in the table. |
search |
─ | String/regex to highlight in output. |
separators |
true |
Include column and header separators in output. |
title |
─ | Add a title line to the table. |
titleize |
─ | Titleize column headers, so person_id becomes Person . |
zebra |
false |
Turn on zebra stripes. |
option | default | details |
---|---|---|
coerce |
true |
if true, try to coerce strings into numbers where possible so we can format with digits . You may want to disable this if you already have nicely formatted ints/floats and you don't want TableTennis to mess with them. |
color |
─ | Are ANSI colors enabled? Specify true or false , or leave it as nil to autodetect. Autodetect will turn on color unless redirecting to a file. When using autodetect, you can force it on by setting ENV["FORCE_COLOR"] , or off with ENV["NO_COLOR"] . |
delims |
true |
Format ints & floats with comma delimiter, like 123,456. |
digits |
3 |
Format floats to this number of digits. TableTennis will look for either Float cells or string floats. |
layout |
true |
This controls column widths. Leave unset or use true for autolayout. Autolayout will shrink the table to fit inside the terminal. false turns off layout and columns will be full width. Use an int to fix all columns to a certain width, or a hash to just set a few. |
placeholder |
"—" |
Put this into empty cells. |
save |
─ | If you set this to a file path, TableTennis will save your table as a CSV file too. Useful if you want to do something else with the data. |
strftime |
see → | strftime string for formatting Date/Time objects. The default is "%Y-%m-%d" , which looks like 2025-04-21 |
theme |
─ | When unset, will be autodetected based on terminal background color. If autodetect fails the theme defaults to :dark. You can also manually specify :dark , :light or :ansi . If colors are turned off this setting has no effect. |
Color scales are useful for visualizing numeric columns. The :color_scales
option can be a single column, an array of column names, or a hash from column names to colors. The scale defaults to :b
(blue) if you don't use a hash.
puts TableTennis.new(rows, color_scales: :price)
puts TableTennis.new(rows, color_scales: [ :price, :quantity ])
puts TableTennis.new(rows, color_scales: { price: :b, quantity: :r })
The color names are abbreviations, so :gyr
goes from green to yellow to red. Here is the full list of supported color scales - %i[g y r b gw yw rw bw rg gr gyr]
. For clarity this screenshot uses sorted columns, but note that TableTennis never does any sorting:
Use mark to highlight certain rows. Maybe you need to find the droids? Or search to highlight text. I almost always use row numbers and zebra stripes too.
puts TableTennis.new(rows, mark: ->(row) { row[:homeworld] =~ /droids/i })
puts TableTennis.new(rows, search: /hope.*empire/i })
puts TableTennis.new(rows, row_numbers: true, zebra: true)
:mark |
:search |
:row_numbers and :zebra |
---|---|---|
![]() |
![]() |
![]() |
Modern terminals support hyperlinks in the text stream. If your table includes markdown-style links, TableTennis will use OSC 8 to render them. For example:
puts TableTennis.new([{site: "[search](https://google.com)"}])
TableTennis can be configured a few different ways:
TableTennis.defaults = { title: "All Tables Have This Name" }
TableTennis.new(rows, title: "An Amazing Title")
TableTennis.new do |t|
t.title = "Yet Another Way To Set Things Up"
end
Tables usually get puts
to $stdout, but there are other ways to do it:
# Uses `to_s`, so there can be a pause before output shows up. Best for small tables.
puts TableTennis.new(rows)
# Write to `$stdout` one row at a time. Prefer this for tables over 10,000 rows.
TableTennis.new(rows).render
# Render to any I/O stream ($stdout/$stderr, an open file, StringIO...)
TableTennis.new(rows).render(io)
We love CSV tools and use them all the time! Here are a few that we rely on:
- bat - syntax highlights csv files, and many others
- csvlens & tidy viewer - great viewers for CSV files, beautiful and fun
- qsv - filter, sort, combine, join... (a fork of xsv)
- Terminal::Table - wonderful rubygem for pretty printing tables, great for non-hash data like confusion matrices
- visidata - the best for poking around large files, it does everything
- added
coerce:
option to disable string => numeric coercion - added
headers:
option to manually set column headers - fixed some issues related to links, including
save:
- added MagicOptions
- Support for markdown style links in the cells
- Separators can be turned off with
separators: false
. - Headers are in color now. Tweaked a few of the dark colors as well.
- Tricky math to better protect narrow columns with auto-layout.
- termbg and termenv for showing how to safely detect the terminal background color. These libraries are widely used for Rust/Go, but as far as I know nothing similar exists for Ruby.
- The Paint gem for help with ansi colors.
- I copied the header color themes from tabiew. Great project!
- Google Sheets for providing nice color scales