/var/log/messages

Mar 4, 2019 - 2 minute read - Comments - programming

プログラミング Elixir (25)

13 章はこのエントリで終わりにしたい。残は 13.13 と 13.14、13.15 な模様。

13.13 タスク: コメントのテスト

TableFormatter へのドキュメント記載なナニが例示されています。

defmodule Issues.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 a 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.0

  We calculate the width of each column to fit the longest element
  in that column.
  """
  def print_table_for_columns(rows, headers) do
    with data_by_columns = split_into_columns(rows, headers),
         columns_width   = width_of(data_by_columns),
         format          = format_for(columns_width)
    do
         puts_one_line_in_columns(headers, format)
         IO.puts(separator(columns_width))
         puts_in_columns(data_by_columns, format)
    end
  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

  ## Example

      iex> list = [Enum.into([{"a", "1"}, {"b", "2"}, {"c", "3"}], %{}),
      ...>         Enum.into([{"a", "4"}, {"b", "5"}, {"c", "6"}], %{})]
      iex> Issues.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 """
  Retuen a binary (string) version of our parameter.
  ## Examples

      iex> Issues.TableFormatter.printable("a")
      "a"
      iex> Issues.TableFormatter.printable(99)
      "99"
  """
  def printable(str) when is_binary(str), do: str
  def printable(str), do: to_string(str)

  @doc """
  Given a list containing sublists, where each sublist contains the data for
  a column, return a list containing the maximum width of each column

  ## Example
      iex> data = [ [ "cat", "wombat", "elk" ], [ "mongoose", "ant", "gnu" ] ]
      iex> Issues.TableFormatter.width_of(data)
      [ 6, 8 ]
  """
  def width_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.

  ## Example
      iex> widths = [5,6,99]
      iex> Issues.TableFormatter.format_for(widths)
      "~-5s | ~-6s | ~-99s~n"
  """
  def format_for(column_width) do
    map_join(column_width, " | ", fn width -> "~-#{width}s" end) <> "~n"
  end

  @doc """
  Generate the line that goes below the column headings. It is a strings of
  hyphens, with + signs where the vertical bar between the columns goes.

  ## Example
      iex> widths = [5, 6, 9]
      iex> Issues.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

で、テストを書いています。

defmodule DocTest do
  use ExUnit.Case
  doctest Issues.TableFormatter
end

いくつかナチュラルな間違いがありましたがスルー。

$ mix test test/doc_test.exs 
warning: variable "escript_config" does not exist and is being expanded to "escript_config()", please use parentheses to remove the ambiguity or change the variable name
  mix.exs:7

Compiling 1 file (.ex)
.....

Finished in 0.2 seconds
5 doctests, 0 failures

Randomized with seed 466592

13.14 タスク: プロジェクトドキュメントの生成

こりゃ凄い。というか今日はへろへろ状態なので別途で

  • mix.exs に必要な情報を記載
  • Github へのリポジトリの登録
  • ドキュメントの生成

やります。あと、OrganizingAProject-6 も別途取り組んでみる方向。

プログラミング Elixir (24) プログラミング Elixir (26)

comments powered by Disqus