Packages
io_ansi_table
0.1.3
1.0.40
1.0.39
1.0.38
1.0.37
1.0.36
1.0.34
1.0.33
1.0.32
1.0.31
1.0.30
1.0.29
1.0.28
1.0.27
1.0.26
1.0.25
1.0.24
1.0.23
1.0.22
1.0.21
1.0.20
1.0.19
1.0.18
1.0.17
1.0.16
1.0.15
1.0.14
1.0.13
1.0.12
1.0.11
1.0.10
1.0.9
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.4.32
0.4.31
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.29
0.3.28
0.3.27
0.3.26
0.3.25
0.3.24
0.3.23
0.3.22
0.3.21
0.3.20
0.3.19
0.3.18
0.3.17
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Writes data to "stdio" in a table with borders and colors. Can choose a table style to change the look of the table.
Current section
Files
Jump to
Current section
Files
lib/io/ansi/table/formatter.ex
# Based on the book "Programming Elixir" by Dave Thomas.
defmodule IO.ANSI.Table.Formatter do
@moduledoc """
Prints a table applying a table style. Each row is
a list of values identified by successive headers.
"""
alias IO.ANSI.Table.Config
alias IO.ANSI.Table.Formatter.Helper
alias IO.ANSI.Table.Style
@doc """
Takes a list of `key`-`value` `collections`, how many to format,
whether to ring the `bell`, a table `style` and, as `options`, a list
of `headers` (`keys`) and a key `header` to sort the `collections` on.
Prints a table to STDOUT of the `values` in each `collection`.
The columns are identified by successive `headers` in order.
We calculate the width of each column to fit the longest element
in that column, also considering the `header` itself.
## Parameters
- `collections` - list of collections (maps or keywords)
- `count` - number of collections to format (integer)
- `bell` - ring the bell? (boolean)
- `style` - table style (atom)
- `options` - headers and key header (keyword)
## Table styles
#{Style.texts " - `&style`&filler - ¬e\n"}
## Options
- `:headers` - defaults to config value `:headers`
- `:key_header` - defaults to config value `:key_header`
## Examples
alias IO.ANSI.Table.Formatter
people = [
%{name: "Mike", likes: "ski, arts", date_of_birth: "1992-04-15"},
%{name: "Mary", likes: "reading" , date_of_birth: "1985-07-11"},
%{name: "Ray" , likes: "cycling" , date_of_birth: "1977-08-28"}
]
Formatter.print_table(
people, 3, true, :dark,
headers: [:name, :date_of_birth, :likes],
key_header: :date_of_birth
)
## 
iex> alias IO.ANSI.Table.Formatter
iex> alias ExUnit.CaptureIO
iex> people = [
...> %{name: "Mike", likes: "ski, arts", date_of_birth: "1992-04-15"},
...> %{name: "Mary", likes: "reading" , date_of_birth: "1985-07-11"},
...> %{name: "Ray" , likes: "cycling" , date_of_birth: "1977-08-28"}
...> ]
iex> CaptureIO.capture_io fn ->
...> Formatter.print_table(
...> people, 3, false, :dashed,
...> headers: [:name, :date_of_birth, :likes],
...> key_header: :date_of_birth
...> )
...> end
\"""
+------+---------------+-----------+
| Name | Date Of Birth | Likes |
+------+---------------+-----------+
| Ray | 1977-08-28 | cycling |
| Mary | 1985-07-11 | reading |
| Mike | 1992-04-15 | ski, arts |
+------+---------------+-----------+
\"""
"""
@spec print_table([map | Keyword.t], integer, boolean, atom, Keyword.t)
:: :ok
def print_table(collections, count, bell, style, options \\ []) do
headers = Keyword.get(options, :headers, Config.headers)
key_header = Keyword.get(options, :key_header, Config.key_header)
collections =
collections
|> Stream.map(&Map.take &1, headers) # optional
|> Enum.sort(&(&1[key_header] <= &2[key_header]))
|> Enum.take(count)
widths =
[Map.new(headers, &{&1, titlecase &1}) | collections]
|> columns(headers)
|> widths # => max widths of column values or headers
rows = rows(collections, headers)
Helper.print_table(rows, headers, key_header, widths, style, bell)
end
@doc """
Takes a list of `key`-`value` `collections` and a list of `keys`.
Returns a list of columns, each column being a list of string `values`
selected from each `collection` on a given `key` and repeatedly on
successive `keys` in order.
## Examples
iex> alias IO.ANSI.Table.Formatter
iex> list = [
...> %{"a" => "1", "b" => "2", "c" => "3"},
...> %{"a" => "4", "b" => "5", "c" => "6"}
...> ]
iex> Formatter.columns(list, ["c", "a"])
[["3", "6"], ["1", "4"]]
iex> alias IO.ANSI.Table.Formatter
iex> list = [
...> %{:one => "1", '2' => 2.0, 3 => :three},
...> %{:one => '4', '2' => "5", 3 => 000006}
...> ]
iex> Formatter.columns(list, [3, :one, '2'])
[["three", "6"], ["1", "4"], ["2.0", "5"]]
"""
@spec columns([map | Keyword.t], [any]) :: [[String.t]]
def columns(collections, keys) do
for key <- keys do
for collection <- collections, do: to_string collection[key]
end
end
@doc """
Takes a list of `key`-`value` `collections` and a list of `keys`.
Returns a list of rows, each row being a list of string `values`
orderly selected on successive `keys` from a given `collection` and
repeatedly for each `collection` in turn.
## Examples
iex> alias IO.ANSI.Table.Formatter
iex> list = [
...> %{"a" => "1", "b" => "2", "c" => "3"},
...> %{"a" => "4", "b" => "5", "c" => "6"}
...> ]
iex> Formatter.rows(list, ["c", "a"])
[["3", "1"], ["6", "4"]]
iex> alias IO.ANSI.Table.Formatter
iex> list = [
...> %{:one => "1", '2' => 2.0, 3 => :three},
...> %{:one => '4', '2' => "5", 3 => 000006}
...> ]
iex> Formatter.rows(list, [3, :one, '2'])
[["three", "1", "2.0"], ["6", "4", "5"]]
"""
@spec rows([map | Keyword.t], [any]) :: [[String.t]]
def rows(collections, keys) do
for collection <- collections do
for key <- keys, do: to_string collection[key]
end
end
@doc """
Given a list of sublists, where each sublist contains the strings of
a `column`, returns a list containing the maximum width of each `column`.
## Examples
iex> alias IO.ANSI.Table.Formatter
iex> data = [["cat", "wombat", "elk"], ["mongoose", "ant", "gnu"]]
iex> Formatter.widths(data)
[6, 8]
iex> alias IO.ANSI.Table.Formatter
iex> data = [[":cat", "{1, 2}", "007"], ["mongoose", ":ant", "3.1416"]]
iex> Formatter.widths(data)
[6, 8]
"""
@spec widths([[String.t]]) :: [non_neg_integer]
def widths(columns) do
for column <- columns, do: column |> Enum.map(&String.length/1) |> Enum.max
end
@doc """
Capitalizes every word of a `title` (converted to string if applicable).
Any underscore is considered a space and consecutive
whitespace characters are treated as a single occurrence.
Leading and trailing whitespace characters are removed.
## Examples
iex> alias IO.ANSI.Table.Formatter
iex> Formatter.titlecase(" son of a gun ")
"Son Of A Gun"
iex> alias IO.ANSI.Table.Formatter
iex> Formatter.titlecase("_date___of_birth_")
"Date Of Birth"
iex> alias IO.ANSI.Table.Formatter
iex> Formatter.titlecase(:" _aN_ _oDD cASe_ ")
"An Odd Case"
"""
@spec titlecase(any) :: String.t
def titlecase(title) do
title
|> to_string
|> String.split(~r/(_|\s)+/, trim: true)
|> Enum.map(&String.capitalize/1)
|> Enum.join("\s")
end
end