tallboy
tallboy
Generate pretty Unicode, ASCII or 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 │
└────────────┴─────────────┴─────────────┘
# draw border joints correctly even with different span sizes :)
Top Features
- spanning cells across muliple columns and entire rows
- simple, readable and flexible API
- text alignment (left, right, center)
- set width and alignment for entire columns with column definitions
- static type checking for almost all DSL options
- support multi-line cells with the newline character
- full custom styling or choose from multiple border styles including ascii, unicode and markdown
- render directly into IO for better performance
Install it as a shard
- Add the dependency to your shard.yml:
dependencies:
  tallboy:
    github: epoch/tallboy
- Run shards install
Simple tutorial
- create a table with Tallboy.table
table = Tallboy.table do
end
- 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
- add rows. you can add single row with rowor nested arrays withrows. values can be any object that has ato_smethod.
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
- add header. we can manually add header with headerwith 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
  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
- 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
- set column span, widths and aligments. header,rowandfooteralso 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
  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 do
    cell "total", span: 3
    cell "43.8"
  end
end
- render with different border styles.
puts table.render # defaults to unicode
puts table.render(:ascii) # classic look
# markdown does not support column spans and outer edge borders
# turning off top and bottom border with border set to `:none`
table = Tallboy.table(border: :none) do
  header ["name", "hex"]
  row ["mistyrose",       "#ffe4e1"]
  row ["darkolivegreen",  "#556b2f"]
  row ["papayawhip",      "#ffefd5"]
end
puts table.render(:markdown) 
| name           | hex     |
|----------------|---------|
| mistyrose      | #ffe4e1 |
| darkolivegreen | #556b2f |
| papayawhip     | #ffefd5 |
- tallboy supports rendering into custom IO
table.render(IO::Memory.new)
puts(
  Tallboy.table do
    row [1,2,3]
  end
)
How it works
Most components in tallboy can be invoked separately. The design philosophy is inspired by how web browsers renders 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]
]
# TableBuilder is the DSL that returns an object model
table_object_model = Tallboy::TableBuilder.new do 
  rows(data)
end
# ComputedTableBuilder takes the object model and calculate widths for each cell 
computed_table = Tallboy::ComputedTableBuilder.new(table_object_model).build
# RenderTreeBuilder work out borders, spans and organize into nodes to rendering
render_tree = Tallboy::RenderTreeBuilder.new(computed_table).build
# render into output with unicode border style
output_string = 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)
- Daniel Tsui - creator and maintainer