Scribe
Pretty-print tables of Elixir structs and maps. Inspired by hirb.
Installation
- Add
scribe
to your list of dependencies inmix.exs
:
def deps do
[
{:scribe, "~> 0.10"}
]
end
Usage
Print a list of maps or structs as a table. Header columns are taken from the keys of the first element.
iex(1)> data = [%{key: "value", another_key: 123},
...(1)> [%{key: "test", another_key: :key}]
iex(2)> Scribe.print(data)
+----------------+-------------+
| :another_key | :key |
+----------------+-------------+
| 123 | "value" |
| :key | "test" |
+----------------+-------------+
Useful for printing large collections, such as results of database queries
# %User{id: nil, email: nil}
iex(1)> User |> limit(5) |> Repo.all |> Scribe.print
+-------------+----------------------------+------+
| :__struct__ | :email | :id |
+-------------+----------------------------+------+
| User | "[email protected]" | 5171 |
| User | "[email protected]" | 4528 |
| User | "[email protected]" | 1480 |
| User | "[email protected]" | 2084 |
| User | "[email protected]" | 6599 |
+-------------+----------------------------+------+
Use Scribe Automatically
Scribe can override Inspect
to automatically return maps in table format.
Add the following to your config/dev.exs
:
config :scribe,
compile_auto_inspect: true,
auto_inspect: true
Temporarily disable in the shell if needed:
iex(1)> Scribe.auto_inspect(false)
:ok
Note: Auto-inspect will not work in production Distillery releases. Leave it out of your prod.exs
Pagination
Scribe uses pane to paginate large tables.
Use with Scribe.console/2
.
# %User{id: nil, email: nil, first_name: nil, last_name: nil}
iex(1)> User |> limit(5) |> Repo.all |> Scribe.console
+-------------+------------------------+-------------+-------+------------+
| :__struct__ | :email | :first_name | :id | :last_name |
+-------------+------------------------+-------------+-------+------------+
| User | "celestine_satterfield | "Gene" | 9061 | "Krajcik" |
| User | "[email protected]" | "Maeve" | 9865 | "Gerlach" |
| User | "[email protected]" | "Theodora" | 2262 | "Wunsch" |
| User | "[email protected] | "Oswaldo" | 4977 | "Simonis" |
| User | "caesar_hirthe@reynold | "Arjun" | 3907 | "Prohaska" |
+-------------+------------------------+-------------+-------+------------+
[1 of 1] (j)next (k)prev (q)quit
Printing Custom Tables
Scribe.print/2
takes a list of of columns on the :data
options key to
customize output. You can use either the atom key or customize the header
with {"Custom Title", :key}
.
# %User{id: nil, email: nil, first_name: nil, last_name: nil}
User
|> limit(5)
|> Repo.all
|> Scribe.print(data: [{"ID", :id}, :first_name, :last_name])
+------+--------------+-------------+
| "ID" | :first_name | :last_name |
+------+--------------+-------------+
| 9061 | "Gene" | "Krajcik" |
| 9865 | "Maeve" | "Gerlach" |
| 2262 | "Theodora" | "Wunsch" |
| 4977 | "Oswaldo" | "Simonis" |
| 3907 | "Arjun" | "Prohaska" |
+------+--------------+-------------+
Function Columns
You can specify functions that take the given row's struct or map as its only argument.
# %User{id: nil, email: nil, first_name: nil, last_name: nil}
results =
User
|> limit(5)
|> Repo.all
|> Scribe.print(data: [{"ID", :id}, {"Full Name", fn(x) -> "#{x.last_name}, #{x.first_name}" end}])
+--------------------------+----------------------------------------------+
| "ID" | "Full Name" |
+--------------------------+----------------------------------------------+
| 9061 | "Krajcik, Gene" |
| 9865 | "Gerlach, Maeve" |
| 2262 | "Wunsch, Theodora" |
| 4977 | "Simonis, Oswaldo" |
| 3907 | "Prohaska, Arjun" |
+--------------------------+----------------------------------------------+
:ok
Styling Options
Width
Pass a width
option to define table width.
iex> Scribe.print(data, width: 80)
+-------------------+-----------------------------------------------------+
| :id | :key |
+-------------------+-----------------------------------------------------+
| 910 | "B1786AC67B4DEB19" |
| 313 | "30CB8A2DE4750070" |
| 25 | "D0859205FC7E7298" |
| 647 | "8F0060AD0BD6AB04" |
| 253 | "65509A684D619182" |
+-------------------+-----------------------------------------------------+
Disable Colors
iex> Scribe.print(data, colorize: false)
Styles
Scribe supports four styling formats natively, with support for custom adapters.
Default
iex> Scribe.print(data, style: Scribe.Style.Default)
+-------+-----------------------------------+------------------------+
| :id | :inserted_at | :key |
+-------+-----------------------------------+------------------------+
| 457 | "2017-03-27 14:42:34.095202Z" | "CEB0E055ECDF6028" |
| 326 | "2017-03-27 14:42:34.097519Z" | "CF67027F7235B88D" |
| 756 | "2017-03-27 14:42:34.097553Z" | "DE016DFF477BEDDB" |
| 484 | "2017-03-27 14:42:34.097572Z" | "9194A82EF4BB0123" |
| 780 | "2017-03-27 14:42:34.097591Z" | "BF92748B4AAAF14A" |
+-------+-----------------------------------+------------------------+
Psql
iex> Scribe.print(data, style: Scribe.Style.Psql)
:id | :inserted_at | :key
-------+-----------------------------------+------------------------
700 | "2017-03-27 14:41:33.411442Z" | "A2FA80D0F6DF9388"
890 | "2017-03-27 14:41:33.412955Z" | "F95094328A91D950"
684 | "2017-03-27 14:41:33.412991Z" | "1EAC6B28045ED644"
531 | "2017-03-27 14:41:33.413015Z" | "DC2377B696355642"
648 | "2017-03-27 14:41:33.413037Z" | "EA9311B4683A52B3"
Github Markdown
iex> Scribe.print(data, style: Scribe.Style.GithubMarkdown)
| :id | :inserted_at | :key |
|-------|-----------------------------------|------------------------|
| 457 | "2017-03-27 14:42:34.095202Z" | "CEB0E055ECDF6028" |
| 326 | "2017-03-27 14:42:34.097519Z" | "CF67027F7235B88D" |
| 756 | "2017-03-27 14:42:34.097553Z" | "DE016DFF477BEDDB" |
| 484 | "2017-03-27 14:42:34.097572Z" | "9194A82EF4BB0123" |
| 780 | "2017-03-27 14:42:34.097591Z" | "BF92748B4AAAF14A" |
Pseudo
iex> Scribe.print(data, style: Scribe.Style.Pseudo)
βββββββββ¬ββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββ
β :id β :inserted_at β :key β
βββββββββΌββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββ€
β 457 β "2017-03-27 14:42:34.095202Z" β "CEB0E055ECDF6028" β
β 326 β "2017-03-27 14:42:34.097519Z" β "CF67027F7235B88D" β
β 756 β "2017-03-27 14:42:34.097553Z" β "DE016DFF477BEDDB" β
β 484 β "2017-03-27 14:42:34.097572Z" β "9194A82EF4BB0123" β
β 780 β "2017-03-27 14:42:34.097591Z" β "BF92748B4AAAF14A" β
βββββββββ΄ββββββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββ
NoBorder
iex> Scribe.print(data, style: Scribe.Style.NoBorder)
:id :inserted_at :key
457 "2017-03-27 14:42:34.095202Z" "CEB0E055ECDF6028"
326 "2017-03-27 14:42:34.097519Z" "CF67027F7235B88D"
756 "2017-03-27 14:42:34.097553Z" "DE016DFF477BEDDB"
484 "2017-03-27 14:42:34.097572Z" "9194A82EF4BB0123"
780 "2017-03-27 14:42:34.097591Z" "BF92748B4AAAF14A"
Set a default one in your Mix config if you like:
config :scribe, style: Scribe.Style.Psql