Packages
doex
0.8.1
0.14.1
0.12.2
0.12.1
0.11.2
0.11.1
0.11.0
0.10.2
0.10.1
0.9.0
0.8.3
0.8.2
0.8.1
0.8.0
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
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.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.1
0.3.0
0.2.2
0.2.1
0.2.0
0.1.1
A Digital Ocean API v2 client for Elixir (yes, another one)
Current section
Files
Jump to
Current section
Files
lib/doex/io/table.ex
defmodule Doex.Io.Table do
@moduledoc """
Takes a list of rows (themselves a list of columns) and returns
iodata containing an aligned ASCII table with `padding` spaces
between each column.
Thanks to
https://gist.github.com/ivan/dc26e349de6f1693c1c77355ec85b643
http://stackoverflow.com/questions/30749400/output-tabular-data-with-io-ansi
## Examples
iex> Doex.Io.Table.format([[1, 2, 3], [4000, 6000, 9000]])
[[[["1", " "], ["2", " "], "3"], 10],
[[["4000", " "], ["6000", " "], "9000"], 10]]
"""
def format(rows, opts \\ []) do
padding = Keyword.get(opts, :padding, 1)
rows = stringify(rows)
widths = rows |> transpose |> column_widths
rows
|> pad_cells(widths, padding)
|> Enum.map(&[&1, ?\n])
end
defp pad_cells(rows, widths, padding) do
Enum.map(rows, fn row ->
map_special(
Enum.zip(row, widths),
fn {val, width} ->
pad_amount = width - (val |> byte_size) + padding
[val, "" |> String.pad_leading(pad_amount)]
end,
fn {val, _width} -> val end
)
end)
end
defp stringify(rows) do
Enum.map(rows, fn row ->
Enum.map(row, &to_string/1)
end)
end
defp column_widths(columns) do
Enum.map(columns, fn column ->
column |> Enum.map(&String.length/1) |> Enum.max()
end)
end
defp transpose(rows) do
rows
|> List.zip()
|> Enum.map(&Tuple.to_list(&1))
end
# Map elements in `enumerable` with `fun1` except for the last element
# which is mapped with `fun2`.
defp map_special(enumerable, fun1, fun2) do
do_map_special(enumerable, [], fun1, fun2) |> :lists.reverse()
end
defp do_map_special([], _acc, _fun1, _fun2) do
[]
end
defp do_map_special([t], acc, _fun1, fun2) do
[fun2.(t) | acc]
end
defp do_map_special([h | t], acc, fun1, fun2) do
do_map_special(t, [fun1.(h) | acc], fun1, fun2)
end
end