Packages

It fetches issues from GitHub for selected user and project.

Current section

Files

Jump to
githubissues lib GithubIssues table_formatter.ex
Raw

lib/GithubIssues/table_formatter.ex

defmodule GithubIssues.TableFormatter do
import Enum, only: [each: 2, map: 2, map_join: 3, max: 1]
@doc """
Takes a list of row data, where each row is Map, and a list of
headers. Prints a table to STDOUT of the data from each row
identified by each header. That is, each header identifies a column,
and those columns are extracted and printed from the rows.
We calculate the width of each column to fit the longest element
in that column.
"""
def print_table_for_columns(rows, headers) do
data_by_columns = split_into_columns(rows, headers)
column_widths = widths_of(data_by_columns)
format = format_for(column_widths)
puts_one_line_in_columns(headers, format)
IO.puts separator(column_widths)
puts_in_columns(data_by_columns, format)
end
@doc """
Given a list of rows, where each row contains a keyed list
of columns, return a list containing lists of the data in each column.
The `headers` parameter contains the list of columns to extract.
## Examples
iex> list = [Enum.into([{"a", "1"}, {"b", "2"}, {"c", "3"}], Map.new),
...> Enum.into([{"a", "4"}, {"b", "5"}, {"c", "6"}], Map.new)]
iex> GithubIssues.TableFormatter.split_into_columns(list, ["a", "b", "c"])
[["1", "4"], ["2", "5"], ["3", "6"]]
"""
def split_into_columns(rows, headers) do
for header <- headers do
for row <- rows, do: printable(row[header])
end
end
@doc """
Returns a binary (string) version of our parameter.
## Examples
iex> GithubIssues.TableFormatter.printable("a")
"a"
iex> GithubIssues.TableFormatter.printable(99)
"99"
"""
def printable(str) when is_binary(str), do: str
def printable(str), do: to_string(str)
@doc """
Given a list containg sublists, where each sublist contains the data
for a column, return a list containing the maximum width of each column
## Examples
iex> data = [["cat", "wombat", "dog"], ["elephant", "ant", "rhino"]]
iex> GithubIssues.TableFormatter.widths_of(data)
[6, 8]
"""
def widths_of(columns) do
for column <- columns, do: column |> map(&String.length/1) |> max
end
@doc """
Return a format string that hard codes the widths of a set of columns.
We put `"|"` between each column.
## Examples
iex> widths = [5, 6, 99]
iex> GithubIssues.TableFormatter.format_for(widths)
"~-5s|~-6s|~-99s~n"
"""
def format_for(column_widths) do
map_join(column_widths, "|", fn width -> "~-#{width}s" end) <> "~n"
end
@doc """
Generate the line that goes below the column headings. It is a string of
hyphens, with + signs where the vertical bar between columns goes.
## Examples
iex> widths = [5, 6, 9]
iex> GithubIssues.TableFormatter.separator(widths)
"------+--------+----------"
"""
def separator(column_widths) do
map_join(column_widths, "-+-", fn width -> List.duplicate("-", width) end)
end
@doc """
Given a list containing rows of data, a list containing the header
selectors, and a format string, write the extracted data under control
of the format string.
"""
def puts_in_columns(data_by_columns, format) do
data_by_columns
|> List.zip
|> map(&Tuple.to_list/1)
|> each(&puts_one_line_in_columns(&1, format))
end
def puts_one_line_in_columns(fields, format) do
:io.format(format, fields)
end
end