tallboy

Generate pretty ASCII, Unicode & Markdown tables on the terminal for your command line programs.

tallboy is a DSL for quickly creating text based tables in Crystal.

Quick start

table = Tallboy.table do
  header ["name", "hex"]
  row ["mistyrose",       "#ffe4e1"],
  row ["darkolivegreen",  "#556b2f"],
  row ["papayawhip",      "#ffefd5"]
end

puts table
┌────────────────┬─────────┐
│ name           │ hex     │
├────────────────┼─────────┤
│ mistyrose      │ #ffe4e1 │
│ darkolivegreen │ #556b2f │
│ papayawhip     │ #ffefd5 │
└────────────────┴─────────┘
# full API

table = Tallboy.table do
  # define 3 columns. set first column width to 12 & align right 
  columns do 
    add "size", width: 12, align: :right
    add "http method"
    add "path"
  end

  # add header with multiple lines
  header "good\nfood\nhunting", align: :right

  # add header with column span on one cell
  header do
    cell ""
    cell "routes", span: 2
  end
  
  # add header inferred from column definitions
  # [size, http method, path]
  header

  rows [
    ["207 B", "post", "/dishes"],
    ["1.3 kB", "get", "/dishes"],
    ["910 B", "patch", "/dishes/:id"],
    ["10.2 kB", "delete", "/dishes/:id"],
  ]
end

puts table
┌────────────────────────────────────────┐
│                                   good │
│                                   food │
│                                hunting │
├────────────┬───────────────────────────┤
│            │ routes                    │
├────────────┼─────────────┬─────────────┤
│       size │ http method │ path        │
├────────────┼─────────────┼─────────────┤
│      207 B │ post        │ /dishes     │
│     1.3 kB │ get         │ /dishes     │
│      910 B │ patch       │ /dishes/:id │
│    10.2 kB │ delete      │ /dishes/:id │
└────────────┴─────────────┴─────────────┘

# look at those beautiful table joins!

Top Features

Install it as a shard

  1. Add the dependency to your shard.yml:
dependencies:
  tallboy:
    github: epoch/tallboy
  1. Run shards install

Simple tutorial

  1. create a table with Tallboy.table
table = Tallboy.table do
end
  1. define columns. here we will define a 4 column table with columns.
table = Tallboy.table do
  columns do
    add "id"
    add "name"
    add "description"
    add "price
  end
end
  1. add rows. you can add single row with row or nested arrays with rows. values can be strings, integers or floats.
table = Tallboy.table do
  columns do
    add "id"
    add "name"
    add "description"
    add "price"
  end

  rows [
    [1, "cake", "goes well with pudding", 3.4],
    [2, "pudding", "so good with cake!", 12.5],
    [3, "burger", "from the reburgulator", 22.9],
    [4, "chips", "wait you mean fries?", 5],
  ]
end
  1. add header. we can manually add header with header with arguments or pass no arguments to inferred from column definitions. header is just a row with a border below.
table = Tallboy.table do
  columns do
    add "id"
    add "name"
    add "description"
    add "price"
  end

  auto_header
  rows [
    [1, "cake", "goes well with pudding", 3.4],
    [2, "pudding", "so good with cake!", 12.5],
    [3, "burger", "from the reburgulator", 22.9],
    [4, "chips", "wait you mean fries?", 5],
  ]
end
  1. add footer. we can add footer with footer. footer is a row with border on top. If we pass a string instead of an array it will auto span all 4 columns based on the other rows defined in this table. nice! :)
table = Tallboy.table do
  columns do
    add "id"
    add "name"
    add "description"
    add "price"
  end
  header
  rows [
    [1, "cake", "goes well with pudding", 3.4],
    [2, "pudding", "so good with cake!", 12.5],
    [3, "burger", "from the reburgulator", 22.9],
    [4, "chips", "wait you mean fries?", 5],
  ]
  footer "43.8"
end
  1. set column span, widths and aligments. header, row and footer also take blocks. here we can set column span on a cell within the footer.
table = Tallboy.table do
  columns do
    add "id"
    add "name"
    add "description"
    add "price"
  end
  auto_header
  rows [
    [1, "cake", "goes well with pudding", 3.4],
    [2, "pudding", "so good with cake!", 12.5],
    [3, "burger", "from the reburgulator", 22.9],
    [4, "chips", "wait you mean fries?", 5],
  ]
  footer "43.8" do
    cell "total", span: 3
    cell "43.8"
  end
end
  1. render with different border styles.
puts table.render # defaults to unicode
puts table.render(:ascii) # classic look
puts table.render(:markdown) # markdown does not support column spans and outer edge borders
  1. tallboy supports rendering into custom IO
puts(
  Tallboy.table do
    row [1,2,3]
  end
)
  1. Most components in tallboy can be invoked separately. The design philosophy is inspired by how web browsers render HTML.
┌───────────────────────────────────────────────────────────┐
│                  web browser vs tallboy                   │
├───────────────────────────────────────────────────────────┤
│ HTML ──> Document Object Model ──> render tree ──> pixels │
│ DSL  ──> Table Object Model    ──> render tree ──> text   │
└───────────────────────────────────────────────────────────┘
data = [
  [1,2,3],
  [4,5,6]
]

# table object model
table_object_model = Tallboy::TableBuilder.new { rows(data) }

min_widths = Tallboy::MinWidthCalculator.new(t3).calculate

# object model with resolved widths
computed_table = Tallboy::ComputedTableBuilder.new(t3, min_widths).build

# render tree
render_tree = Tallboy::RenderTreeBuilder.new(computed_table).build

# text
str = Tallboy::Renderer.new(render_tree).render

API

more examples in the examples folder

Contributing

Issues and pull requests are welcome on GitHub at (https://github.com/epoch/tallboy)