tobble

Tobble is a table library for Gleam, which makes it as easy as possible to render tables from simple output. It does provide some customization options, but they are not very expansive, as Tobble does not aim to be a full layout library. Rather, it aims to make it simple to make beautiful output for your programs.

import gleam/io
import tobble

pub fn main() {
  let assert Ok(table) =
    tobble.builder()
    |> tobble.add_row(["", "Output"])
    |> tobble.add_row(["Stage 1", "Wibble"])
    |> tobble.add_row(["Stage 2", "Wobble"])
    |> tobble.add_row(["Stage 3", "WibbleWobble"])
    |> tobble.build()

  io.println(tobble.render(table))
}
+---------+--------------+
|         | Output       |
+---------+--------------+
| Stage 1 | Wibble       |
| Stage 2 | Wobble       |
| Stage 3 | WibbleWobble |
+---------+--------------+

Types

Builder is a type used to help you build tables. See builder for more details.

pub opaque type Builder
pub type BuilderError {
  InconsistentColumnCountError(expected: Int, got: Int)
  EmptyTableError
  EmptyTitleError
}

Constructors

  • InconsistentColumnCountError(expected: Int, got: Int)

    Returned when not all rows have the same number of columns.

    Why is this an error? It is not possible to render a rectangular table if any row has a different number of columns than another.

  • EmptyTableError

    Returned when attempting to build a table with no rows.

    Why is this an error? It is somewhat unclear how to render this, and is left as an error so callers can handle it however is best for their application.

  • EmptyTitleError

    Returned when attempting to build a table with an empty string as the title.

    Why is this an error? It is somewhat unclear how to render this, and is likely the result of a bug in your app.

pub type HorizontalRules {
  HeaderOnlyHorizontalRules
  EveryRowHasHorizontalRules
  NoHorizontalRules
}

Constructors

  • HeaderOnlyHorizontalRules

    Renders the table with only the header having a horizontal rule beneath it. This is the default setting.

    +---------+--------------+
    |         | Output       |
    +---------+--------------+
    | Stage 1 | Wibble       |
    | Stage 2 | Wobble       |
    | Stage 3 | WibbleWobble |
    +---------+--------------+
    
  • EveryRowHasHorizontalRules

    Renders the table with every row the header having a horizontal rule beneath it.

    +---------+--------------+
    |         | Output       |
    +---------+--------------+
    | Stage 1 | Wibble       |
    +---------+--------------+
    | Stage 2 | Wobble       |
    +---------+--------------+
    | Stage 3 | WibbleWobble |
    +---------+--------------+
    
  • NoHorizontalRules

    Renders the table without any horizontal rules interleaved with the table’s rows.

    +---------+--------------+
    |         | Output       |
    | Stage 1 | Wibble       |
    | Stage 2 | Wobble       |
    | Stage 3 | WibbleWobble |
    +---------+--------------+
    
pub type RenderLineType {
  BoxDrawingCharsLineType
  BoxDrawingCharsWithRoundedCornersLineType
  ASCIILineType
  BlankLineType
}

Constructors

  • BoxDrawingCharsLineType

    Renders the table with box drawing characters for the borders.

    ┌─────────┬──────────────┐
    │         │ Output       │
    ├─────────┼──────────────┤
    │ Stage 1 │ Wibble       │
    │ Stage 2 │ Wobble       │
    │ Stage 3 │ WibbleWobble │
    └─────────┴──────────────┘
  • BoxDrawingCharsWithRoundedCornersLineType

    Renders the table with box drawing characters for the borders, but with rounded corners.

    ╭─────────┬──────────────╮
    │         │ Output       │
    ├─────────┼──────────────┤
    │ Stage 1 │ Wibble       │
    │ Stage 2 │ Wobble       │
    │ Stage 3 │ WibbleWobble │
    ╰─────────┴──────────────╯
  • ASCIILineType

    Render the table with ASCII characters for the borders. This is the default setting.

    +---------+--------------+
    |         | Output       |
    +---------+--------------+
    | Stage 1 | Wibble       |
    | Stage 2 | Wobble       |
    | Stage 3 | WibbleWobble |
    +---------+--------------+
    
  • BlankLineType

    Renders the table with spaces for the borders. Note that this does not strip trailing spaces, the borders that you see in other line types are simply replaced with spaces. It will, however, remove the top and bottom borders for you.

                Output
    
      Stage 1   Wibble
      Stage 2   Wobble
      Stage 3   WibbleWobble
    
pub type RenderOption {
  TableWidthRenderOption(width: Int)
  ColumnWidthRenderOption(width: Int)
  LineTypeRenderOption(line_type: RenderLineType)
  HorizontalRulesRenderOption(horizontal_rules: HorizontalRules)
  TitlePositionRenderOption(position: TitlePosition)
  HideTitleRenderOption
}

Constructors

  • TableWidthRenderOption(width: Int)

    Render the table with a width of, at most, the given width. Note that this is best effort, and there are pathological cases where Tobble will decide to render your tables slightly wider than requested (e.g. requesting a width too small to even fit the table borders). By default, the table width is unconstrained.

  • ColumnWidthRenderOption(width: Int)

    Render the table where each column’s text has the given width. If a width less than 1 is given, this will default to 1. By default, columns are as wide as the longest row within them.

  • LineTypeRenderOption(line_type: RenderLineType)

    Render the table with a different style of border By default, ASCIILineType is used.

  • HorizontalRulesRenderOption(horizontal_rules: HorizontalRules)

    Changes the way the table renders horizontal rules. See HorizontalRules for more details. By default, only the first row has a horizontal rule.

  • TitlePositionRenderOption(position: TitlePosition)

    Render a title for the table at the given position. If the table does not have a title set, this option is ignored. By default, the title will render at the top.

  • HideTitleRenderOption

    Render a table that has a title set, but without its title.

Table is the central type of Tobble. It holds the data you wish to display, without regard for how you render it. These can be built using builder/build.

pub opaque type Table
pub type TitlePosition {
  TopTitlePosition
  BottomTitlePosition
}

Constructors

  • TopTitlePosition

    Place the title above the table

  • BottomTitlePosition

    Place the title below the table

Functions

pub fn add_row(
  to builder: Builder,
  columns columns: List(String),
) -> Builder

Add a row to a table that is being built. Every call to add_row for a given Builder must have the same number of columns, or an InconsistentColumnCountError will be returned when build is called.

pub fn build(
  with builder: Builder,
) -> Result(Table, BuilderError)

Build a Table from the given Builder. If an invalid operation was performed when constructing the Builder, an error will be returned.

pub fn builder() -> Builder

Create a new Builder for table generation. Once you have completed adding your rows to this with add_row, you should call build to generate a Table.

pub fn render(table table: Table) -> String

Render the given table to a String, with the default options. The output can be customized by using render_with_options.

Example

let assert Ok(table) =
    tobble.builder()
    |> tobble.add_row(["", "Output"])
    |> tobble.add_row(["Stage 1", "Wibble"])
    |> tobble.add_row(["Stage 2", "Wobble"])
    |> tobble.add_row(["Stage 3", "WibbleWobble"])
    |> tobble.build()

io.println(tobble.render(table))
+---------+--------------+
|         | Output       |
+---------+--------------+
| Stage 1 | Wibble       |
| Stage 2 | Wobble       |
| Stage 3 | WibbleWobble |
+---------+--------------+
pub fn render_iter(
  table table: Table,
  options options: List(RenderOption),
) -> Yielder(String)

Render the given table to a Yielder. Each element of the Yielder will produce a single line of output, without a trailing newline. Note that options are applied in order, so if duplicate or conflicting options are given, the last one will win.

Example

let assert Ok(table) =
tobble.builder()
|> tobble.add_row(["", "Output"])
|> tobble.add_row(["Stage 1", "Wibble"])
|> tobble.add_row(["Stage 2", "Wobble"])
|> tobble.add_row(["Stage 3", "WibbleWobble"])
|> tobble.build()


table
|> tobble.render_iter(options: [])
|> yielder.each(io.println)
+---------+--------------+
|         | Output       |
+---------+--------------+
| Stage 1 | Wibble       |
| Stage 2 | Wobble       |
| Stage 3 | WibbleWobble |
+---------+--------------+
pub fn render_with_options(
  table table: Table,
  options options: List(RenderOption),
) -> String

Render the given table to a String, with extra options. Note that options are applied in order, so if duplicate or conflicting options are given, the last one will win.

let assert Ok(table) =
  tobble.builder()
  |> tobble.add_row(["", "Output"])
  |> tobble.add_row(["Stage 1", "Wibble"])
  |> tobble.add_row(["Stage 2", "Wobble"])
  |> tobble.add_row(["Stage 3", "WibbleWobble"])
  |> tobble.build()

io.println(
  tobble.render_with_options(table, options: [
    tobble.ColumnWidthRenderOption(6),
  ]),
)
+--------+--------+
|        | Output |
+--------+--------+
| Stage  | Wibble |
| 1      |        |
| Stage  | Wobble |
| 2      |        |
| Stage  | Wibble |
| 3      | Wobble |
+--------+--------+
pub fn set_title(
  to builder: Builder,
  title title: String,
) -> Builder

Set a title for a table that is being built. The title must be a non-empty string or a TitleEmptyError will be returned when build is called.

Example

let assert Ok(table) =
  tobble.builder()
  |> tobble.set_title("Setup")
  |> tobble.add_row(["", "Output"])
  |> tobble.add_row(["Stage 1", "Wibble"])
  |> tobble.add_row(["Stage 2", "Wobble"])
  |> tobble.add_row(["Stage 3", "WibbleWobble"])
  |> tobble.build()

io.println(tobble.render(table))
         Setup
+---------+--------------+
|         | Output       |
+---------+--------------+
| Stage 1 | Wibble       |
| Stage 2 | Wobble       |
| Stage 3 | WibbleWobble |
+---------+--------------+
pub fn title(table: Table) -> Option(String)

Get the title of a table, if there is one.

Example

let assert Ok(table) =
  tobble.builder()
  |> tobble.set_title("Setup")
  |> tobble.add_row(["", "Output"])
  |> tobble.add_row(["Stage 1", "Wibble"])
  |> tobble.add_row(["Stage 2", "Wobble"])
  |> tobble.add_row(["Stage 3", "WibbleWobble"])
  |> tobble.build()

io.debug(tobble.title(table))
Some("Setup")
pub fn to_list(table: Table) -> List(List(String))

Convert an existing table to a list of its rows.

Example

let assert Ok(table) =
  tobble.builder()
  |> tobble.add_row(["", "Output"])
  |> tobble.add_row(["Stage 1", "Wibble"])
  |> tobble.add_row(["Stage 2", "Wobble"])
  |> tobble.add_row(["Stage 3", "WibbleWobble"])
  |> tobble.build()

io.debug(tobble.to_list(table))
[
  ["", "Output"],
  ["Stage 1", "Wibble"],
  ["Stage 2", "Wobble"],
  ["Stage 3", "WibbleWobble"]
]
Search Document