class Athena::Console::Helper::Table
inherits Reference
#
The Table helper can be used to display tabular data rendered to any ACON::Output::Interface
.
+---------------+--------------------------+------------------+
| ISBN | Title | Author |
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
| 80-902734-1-6 | And Then There Were None | Agatha Christie |
+---------------+--------------------------+------------------+
Usage#
Most commonly, a table will consist of a header row followed by one or more data rows:
@[ACONA::AsCommand("table")]
class TableCommand < ACON::Command
protected def execute(input : ACON::Input::Interface, output : ACON::Output::Interface) : ACON::Command::Status
ACON::Helper::Table.new(output)
.headers("ISBN", "Title", "Author")
.rows([
["99921-58-10-7", "Divine Comedy", "Dante Alighieri"],
["9971-5-0210-0", "A Tale of Two Cities", "Charles Dickens"],
["960-425-059-0", "The Lord of the Rings", "J. R. R. Tolkien"],
["80-902734-1-6", "And Then There Were None", "Agatha Christie"],
])
.render
ACON::Command::Status::SUCCESS
end
end
Separating Rows#
Row separators can be added anywhere in the output by passing an ACON::Helper::Table::Separator
as a row.
table
.rows([
["99921-58-10-7", "Divine Comedy", "Dante Alighieri"],
["9971-5-0210-0", "A Tale of Two Cities", "Charles Dickens"],
ACON::Helper::Table::Separator.new,
["960-425-059-0", "The Lord of the Rings", "J. R. R. Tolkien"],
["80-902734-1-6", "And Then There Were None", "Agatha Christie"],
])
+---------------+--------------------------+------------------+
| ISBN | Title | Author |
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
+---------------+--------------------------+------------------+
| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
| 80-902734-1-6 | And Then There Were None | Agatha Christie |
+---------------+--------------------------+------------------+
Header/Footer Titles#
Header and/or footer titles can optionally be added via the #header_title
and/or #footer_title
methods.
table
.header_title("Books")
.footer_title("Page 1/2")
+---------------+----------- Books --------+------------------+
| ISBN | Title | Author |
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
+---------------+--------------------------+------------------+
| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
| 80-902734-1-6 | And Then There Were None | Agatha Christie |
+---------------+--------- Page 1/2 -------+------------------+
Column Sizing#
By default, the width of each column is calculated automatically based on their contents.
The #column_widths
method can be used to set the column widths explicitly.
table
.column_widths(10, 0, 30)
.render
In this example, the first column's width will be 10
, the last column's width will be 30
, and the second column's width will be calculated automatically since it is zero.
If you only want to set the width of a specific column, the #column_width
method can be used.
table
.column_width(0, 10)
.column_width(2, 30)
.render
The resulting table would be:
+---------------+------------------ Books -+--------------------------------+
| ISBN | Title | Author |
+---------------+--------------------------+--------------------------------+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
+---------------+--------------------------+--------------------------------+
| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
| 80-902734-1-6 | And Then There Were None | Agatha Christie |
+---------------+--------------------------+--------------------------------+
Notice that the width of the first column is greater than 10 characters wide. This is because column widths are always considered as the minimum width. If the content doesn't fit, it will be automatically increased to the longest content length.
Max Width#
If you would rather wrap the contents in multiple rows, the #column_max_width
method can be used.
table
.column_max_width(0, 5)
.column_max_width(1, 10)
.render
This would cause the table to now be:
+-------+------------+-- Books -----------------------+
| ISBN | Title | Author |
+-------+------------+--------------------------------+
| 99921 | Divine Com | Dante Alighieri |
| -58-1 | edy | |
| 0-7 | | |
| (the rest of the rows...) |
+-------+------------+--------------------------------+
Orientation#
By default, the table contents are displayed as a normal table with the data being in rows, the first being the header row(s).
The table can also be rendered vertically or horizontally via the #vertical
and #horizontal
methods respectively.
For example, the same contents rendered vertically would be:
+----------------------------------+
| ISBN: 99921-58-10-7 |
| Title: Divine Comedy |
| Author: Dante Alighieri |
|----------------------------------|
| ISBN: 9971-5-0210-0 |
| Title: A Tale of Two Cities |
| Author: Charles Dickens |
|----------------------------------|
| ISBN: 960-425-059-0 |
| Title: The Lord of the Rings |
| Author: J. R. R. Tolkien |
|----------------------------------|
| ISBN: 80-902734-1-6 |
| Title: And Then There Were None |
| Author: Agatha Christie |
+----------------------------------+
While horizontally, it would be:
+--------+-----------------+----------------------+-----------------------+--------------------------+
| ISBN | 99921-58-10-7 | 9971-5-0210-0 | 960-425-059-0 | 80-902734-1-6 |
| Title | Divine Comedy | A Tale of Two Cities | The Lord of the Rings | And Then There Were None |
| Author | Dante Alighieri | Charles Dickens | J. R. R. Tolkien | Agatha Christie |
+--------+-----------------+----------------------+-----------------------+--------------------------+
Styles#
Up until now, all the tables have been rendered using the default
style.
The table helper comes with a few additional built in styles, including:
- borderless
- compact
- box
- double-box
The desired can be set via the #style
method.
table
.style("default") # Same as not calling the method
.render
borderless#
=============== ========================== ==================
ISBN Title Author
=============== ========================== ==================
99921-58-10-7 Divine Comedy Dante Alighieri
9971-5-0210-0 A Tale of Two Cities Charles Dickens
=============== ========================== ==================
960-425-059-0 The Lord of the Rings J. R. R. Tolkien
80-902734-1-6 And Then There Were None Agatha Christie
=============== ========================== ==================
compact#
ISBN Title Author
99921-58-10-7 Divine Comedy Dante Alighieri
9971-5-0210-0 A Tale of Two Cities Charles Dickens
960-425-059-0 The Lord of the Rings J. R. R. Tolkien
80-902734-1-6 And Then There Were None Agatha Christie
box#
┌───────────────┬──────────────────────────┬──────────────────┐
│ ISBN │ Title │ Author │
├───────────────┼──────────────────────────┼──────────────────┤
│ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri │
│ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens │
├───────────────┼──────────────────────────┼──────────────────┤
│ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien │
│ 80-902734-1-6 │ And Then There Were None │ Agatha Christie │
└───────────────┴──────────────────────────┴──────────────────┘
double-box#
╔═══════════════╤══════════════════════════╤══════════════════╗
║ ISBN │ Title │ Author ║
╠═══════════════╪══════════════════════════╪══════════════════╣
║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║
║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║
╟───────────────┼──────────────────────────┼──────────────────╢
║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║
║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║
╚═══════════════╧══════════════════════════╧══════════════════╝
Custom Styles#
If you would rather something more personal, custom styles can also be defined by providing #style
with an ACON::Helper::Table::Style
instance.
table_style = ACON::Helper::Table::Style.new
.horizontal_border_chars("<fg=magenta>|</>")
.vertical_border_chars("<info>-</>")
.default_crossing_char(' ')
table
.style(table_style)
.render
Notice you can use the same style tags as you can with ACON::Formatter::OutputStyleInterface
s.
This is used by default to give some color to headers when allowed.
Tip
Custom styles can also be registered globally:
ACON::Helper::Table.set_style_definition "colorful", table_style
# ...
table.style("colorful")
See ACON::Helper::Table::Style
for more information.
Table Cells#
The ACON::Helper::Table::Cell
type can be used to style a specific cell.
Such as customizing the fore/background color, the alignment of the text, or the overall format of the cell.
See the related type for more information/examples.
Spanning Multiple Columns and Rows#
The ACON::Helper::Table::Cell
type can also be used to add colspan and/or rowspan to a cell;
which would make it span more than one column/row.
ACON::Helper::Table.new(output)
.headers("ISBN", "Title", "Author")
.rows([
["99921-58-10-7", "Divine Comedy", "Dante Alighieri"],
ACON::Helper::Table::Separator.new,
[ACON::Helper::Table::Cell.new("This value spans 3 columns.", colspan: 3)],
])
.render
This would result in:
+---------------+---------------+-----------------+
| ISBN | Title | Author |
+---------------+---------------+-----------------+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
+---------------+---------------+-----------------+
| This value spans 3 columns. |
+---------------+---------------+-----------------+
Tip
This table cells with colspan and center
alignment can be used to create header cells that span the entire table width:
table
.headers([
[ACON::Helper::Table::Cell.new(
"Main table title",
colspan: 3,
style: ACON::Helper::Table::CellStyle.new(
align: :center
)
)],
%w(ISBN Title Author),
])
+--------+--------+--------+
| Main table title |
+--------+--------+--------+
| ISBN | Title | Author |
+--------+--------+--------+
In a similar way, rowspan can be used to have a column span multiple rows. This is especially helpful for columns with line breaks.
ACON::Helper::Table.new(output)
.headers("ISBN", "Title", "Author")
.rows([
[
"978-0521567817",
"De Monarchia",
ACON::Helper::Table::Cell.new("Dante Alighieri\nspans multiple rows", rowspan: 2),
],
["978-0804169127", "Divine Comedy"],
])
.render
This would result in:
+----------------+---------------+---------------------+
| ISBN | Title | Author |
+----------------+---------------+---------------------+
| 978-0521567817 | De Monarchia | Dante Alighieri |
| 978-0804169127 | Divine Comedy | spans multiple rows |
+----------------+---------------+---------------------+
colspan and rowspan may also be used together to create any layout you can think of.
Modifying Rendered Tables#
The #render
method requires providing the entire table's content in order to fully render the table.
In some cases, that may not be possible if the data is generated dynamically.
In such cases, the #append_row
method can be used which functions similarly to #add_row
, but will append the rows to an already rendered table.
Info
This feature is only available when the table is rendered in an ACON::Output::Section
.
@[ACONA::AsCommand("table")]
class TableCommand < ACON::Command
protected def execute(input : ACON::Input::Interface, output : ACON::Output::Interface) : ACON::Command::Status
section = output.section
table = ACON::Helper::Table.new(section)
.add_row("Foo")
table.render
table.append_row "Bar"
ACON::Command::Status::SUCCESS
end
end
This ultimately results in:
+-----+
| Foo |
| Bar |
+-----+
Constructors#
Class methods#
.set_style_definition(name : String, style : ACON::Helper::Table::Style) : Nil
#
Registers the provided style with the provided name.
See custom styles.
.style_definition(name : String) : ACON::Helper::Table::Style
#
Returns the ACON::Helper::Table::Style
style with the provided name,
raising an ACON::Exceptions::InvalidArgument
if no style with that name is defined.
Methods#
#add_row(row : RowType) : self
#
Adds a single new row to this table.
# Existing rows are not removed.
table
.add_row(%w(One Two Three))
.add_row(%w(Foo Bar Baz))
.render
#add_row(*columns : CellType) : self
#
Adds the provided columns as a single row to this table.
# Existing rows are not removed.
table
.add_row("One", "Two", "Three")
.add_row("Foo", "Bar", "Baz")
.render
#add_rows(rows : Enumerable(RowType)) : self
#
Similar to #rows(rows : Enumerable(RowType))
, but appends the provided rows to this table.
# Existing rows are not removed.
table
.add_rows([
%w(One Two Three),
%w(Foo Bar Baz),
])
.render
#append_row(*columns : CellType) : self
#
Appends the provided columns as a single row to an already rendered table.
#column_max_width(index : Int32, width : Int32) : self
#
Sets the maximum width for the column at the provided index.
See column sizing.
#column_style(index : Int32, style : ACON::Helper::Table::Style | String) : self
#
Sets the style of the column at the provided index.
style may either be an explicit ACON::Helper::Table::Style
,
or the name of the style to use if it is built-in, or was registered via .set_style_definition
.
#column_style(index : Int32) : ACON::Helper::Table::Style
#
Returns the ACON::Helper::Table::Style
the column at the provided index is using, falling back on #style
.
#column_width(index : Int32, width : Int32) : self
#
Sets the minimum width for the column at the provided index.
See column sizing.
#column_widths(widths : Enumerable(Int32)) : self
#
Sets the minimum column widths to the provided widths.
See column sizing.
#column_widths(*widths : Int32) : self
#
Sets the minimum column widths to the provided widths.
See column sizing.
#render
#
Renders this table to the ACON::Output::Interface
it was instantiated with.
ameba:disable Metrics/CyclomaticComplexity
#row(index : Int32, row : RowType) : self
#
Manually sets the provided row to the provided index.
# Existing rows are not removed.
table
.add_row(%w(One Two Three))
.row(0, %w(Foo Bar Baz)) # Overrides row 0 to this row
.render
#rows(rows : RowType) : self
#
Overrides the rows of this table to those provided in rows.
table
.rows(%w(Foo Bar Baz))
.render
#rows(rows : Enumerable(RowType)) : self
#
Overrides the rows of this table to those provided in rows.
table
.rows([
%w(One Two Three),
%w(Foo Bar Baz),
])
.render
#style(style : String | ACON::Helper::Table::Style) : self
#
Sets the style of this table.
style may either be an explicit ACON::Helper::Table::Style
,
or the name of the style to use if it is built-in, or was registered via .set_style_definition
.
See styles and custom styles.
#style : ACON::Helper::Table::Style
#
Returns the ACON::Helper::Table::Style
used by this table.