Skip to content

Commit

Permalink
Provide styler and header_styler options on initializing table
Browse files Browse the repository at this point in the history
Allows default styler and header styler to be set for all columns
on the table.
  • Loading branch information
matt-harvey committed Feb 1, 2020
1 parent 2e65611 commit 9a5b895
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 26 deletions.
43 changes: 36 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ Tabulo has also been ported to Crystal (with some modifications): see [Tablo](ht
* [Automating column widths](#automating-column-widths)
* [Overflow handling](#overflow-handling)
* [Formatting cell values](#formatting-cell-values)
* [Colours and styling](#colours-and-styling)
* [Colours and other styling](#colours-and-styling)
* [Styling cell content](#styling-cell-content)
* [Styling column headers](#styling-column-headers)
* [Setting default styles](#default-styles)
* [Styling borders](#border-styling)
* [Repeating headers](#repeating-headers)
* [Using a Table Enumerator](#using-a-table-enumerator)
* [Accessing cell values](#accessing-cell-values)
Expand Down Expand Up @@ -476,7 +480,10 @@ Formatters set for individual columns on calling `#add_column` always override t
the table.

<a name="colours-and-styling"></a>
### Colours and styling
### Colours and other styling

<a name="styling-cell-content"></a>
#### Styling cell content

In most terminals, if you want to print text that is coloured, or has certain other styles such as
underlining, you need to use ANSI escape sequences, either directly, or by means of a library such
Expand Down Expand Up @@ -517,22 +524,44 @@ If the content of a cell is wrapped over multiple lines, then the `styler` will
once per line, so that each line of the cell will have the escape sequence applied to it
separately (ensuring the styling doesn't bleed into neighbouring cells).

If the content of a cell has been [truncated](#overflow-handling), then whatever colours or other styling
apply to the cell content will also be applied the truncation indicator character.

<a name="styling-column-headers"></a>
#### Styling column headers

If you want to apply colours or other styling to the content of a column header, as opposed
to cells in the table body, use the `header_styler` option, e.g.:

```ruby
table.add_column(:even?, header_styler: -> (s) { "\033[32m#{s}\033[0m" })
```

To apply colours or other styling to the row divider, column divider, corner and border
characters of the table, use the `border_styler` option when initializing the table, e.g.:
<a name="default-styles"></a>
#### Setting default styles

By default, no styling is applied to the headers or body content of a column unless configured to do
so via the `header_styler` or `styler` option when calling `add_column` to add a particular column.
It is possible to apply styling by default to _all_ columns in a table, however, as the table initializer
also accepts both a `header_styler` and a `styler` option. For example, if you want all the header text in the
table to be green, you could do:

```ruby
table = Tabulo::Table.new(1..5, :itself, :even?, :odd?, border_styler: -> (s) { "\033[32m#{s}\033[0m" })
table = Tabulo::Table.new(1..5, :itself, :even?, :odd?, header_styler: -> (s) { "\033[32m#{s}\033[0m" })
```

If the content of a cell has been [truncated](#overflow-handling), then whatever colours or other styling
apply to the cell content will also be applied the truncation indicator character.
Now, all columns in the table will have automatically have green header text, unless overridden
by another header styler being passed to `#add_column`.

<a name="border-styling"></a>
#### Styling borders

Styling can also be applied to borders and dividing lines, using the `border_styler` option when
initializing the table, e.g.:

```ruby
table = Tabulo::Table.new(1..5, :itself, :even?, :odd?, border_styler: -> (s) { "\033[32m#{s}\033[0m" })
```

<a name="repeating-headers"></a>
### Repeating headers
Expand Down
15 changes: 11 additions & 4 deletions lib/tabulo/table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,21 @@ class Table
# element indicates the amount to apply to the right.
# @param [Integer, nil] column_width The default column width for columns in this
# table, not excluding padding. If <tt>nil</tt>, then {DEFAULT_COLUMN_WIDTH} will be used.
# @param [nil, #to_proc] formatter (:to_s.to_proc) The default value for the `formatter` option
# when columns are added to this table via {#add_column}.
# @param [nil, #to_proc] formatter (:to_s.to_proc) The default formatter for columns in this
# table. See `formatter` option of {#add_column} for details.
# @param [:start, nil, Integer] header_frequency (:start) Controls the display of column headers.
# If passed <tt>:start</tt>, headers will be shown at the top of the table only. If passed <tt>nil</tt>,
# headers will not be shown. If passed an Integer N (> 0), headers will be shown at the top of the table,
# then repeated every N rows.
# @param [nil, #to_proc] header_styler (nil) The default header styler for columns in this
# table. See `header_styler` option of {#add_column} for details.
# @param [nil, Integer] row_divider_frequency (nil) Controls the display of horizontal row dividers within
# the table body. If passed <tt>nil</tt>, dividers will not be shown. If passed an Integer N (> 0),
# dividers will be shown after every N rows. The characters used to form the dividers are
# determined by the `border` option, and are the same as those used to form the bottom edge of the
# header row.
# @param [nil, #to_proc] styler (nil) The default styler for columns in this table. See `styler`
# option of {#add_column} for details.
# @param [nil, String] truncation_indicator Determines the character used to indicate that a
# cell's content has been truncated. If omitted or passed <tt>nil</tt>,
# defaults to {DEFAULT_TRUNCATION_INDICATOR}. If passed something other than <tt>nil</tt> or
Expand Down Expand Up @@ -114,7 +118,9 @@ def initialize(
column_width: nil,
formatter: :to_s.to_proc,
header_frequency: :start,
header_styler: nil,
row_divider_frequency: nil,
styler: nil,
truncation_indicator: nil,
wrap_body_cells_to: nil,
wrap_header_cells_to: nil)
Expand All @@ -139,6 +145,7 @@ def initialize(
@column_width = (column_width || DEFAULT_COLUMN_WIDTH)
@formatter = formatter
@header_frequency = header_frequency
@header_styler = header_styler
@row_divider_frequency = row_divider_frequency
@truncation_indicator = validate_character(truncation_indicator,
DEFAULT_TRUNCATION_INDICATOR, InvalidTruncationIndicatorError, "truncation indicator")
Expand Down Expand Up @@ -253,9 +260,9 @@ def add_column(
extractor: extractor || label.to_proc,
formatter: formatter || @formatter,
header: (header || label).to_s,
header_styler: header_styler,
header_styler: header_styler || @header_styler,
padding_character: PADDING_CHARACTER,
styler: styler,
styler: styler || @styler,
truncation_indicator: @truncation_indicator,
width: width || @column_width,
)
Expand Down
96 changes: 81 additions & 15 deletions spec/table_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
column_width: column_width,
formatter: formatter,
header_frequency: header_frequency,
header_styler: header_styler,
row_divider_frequency: row_divider_frequency,
styler: styler,
truncation_indicator: truncation_indicator,
wrap_body_cells_to: wrap_body_cells_to,
wrap_header_cells_to: wrap_header_cells_to,
Expand All @@ -30,7 +32,9 @@
let(:column_width) { nil }
let(:formatter) { :to_s.to_proc }
let(:header_frequency) { :start }
let(:header_styler) { nil }
let(:row_divider_frequency) { nil }
let(:styler) { nil }
let(:truncation_indicator) { nil }
let(:wrap_body_cells_to) { nil }
let(:wrap_header_cells_to) { nil }
Expand Down Expand Up @@ -131,6 +135,77 @@
end
end

describe "`header_styler` param" do
context "when passed `nil`" do
let(:header_styler) { nil }

it "does not apply any additional styling to the header text" do
expect(table.to_s).to eq \
%Q(+--------------+--------------+
| N | Doubled |
+--------------+--------------+
| 1 | 2 |
| 2 | 4 |
| 3 | 6 |
| 4 | 8 |
| 5 | 10 |
+--------------+--------------+).gsub(/^ +/, "")
end
end

context "when passed a callable" do
let(:header_styler) { -> (str) { "\033[31;1;4m#{str}\033[0m" } }

it "applies additional styling to the header text of every column, without affecting the width "\
"calculations" do
expect(table.to_s).to eq \
%Q(+--------------+--------------+
| \033[31;1;4mN\033[0m | \033[31;1;4mDoubled\033[0m |
+--------------+--------------+
| 1 | 2 |
| 2 | 4 |
| 3 | 6 |
| 4 | 8 |
| 5 | 10 |
+--------------+--------------+).gsub(/^ +/, "")
end

context "when a new column is added with `nil` passed to the `header_styler` option "\
"of #add_column" do
it "applies the same styling to the newly added column" do
table.add_column("Trebled", header_styler: nil) { |n| n * 3 }
expect(table.to_s).to eq \
%Q(+--------------+--------------+--------------+
| \033[31;1;4mN\033[0m | \033[31;1;4mDoubled\033[0m | \033[31;1;4mTrebled\033[0m |
+--------------+--------------+--------------+
| 1 | 2 | 3 |
| 2 | 4 | 6 |
| 3 | 6 | 9 |
| 4 | 8 | 12 |
| 5 | 10 | 15 |
+--------------+--------------+--------------+).gsub(/^ +/, "")
end
end

context "when a new column is added with a different callable passed to the `header_styler` option "\
"of #add_column" do
it "applies the different styling to the newly added column only" do
table.add_column( "Trebled", header_styler: -> (str) { "\033[32;4m#{str}\033[0m" }) { |n| n * 3 }
expect(table.to_s).to eq \
%Q(+--------------+--------------+--------------+
| \033[31;1;4mN\033[0m | \033[31;1;4mDoubled\033[0m | \033[32;4mTrebled\033[0m |
+--------------+--------------+--------------+
| 1 | 2 | 3 |
| 2 | 4 | 6 |
| 3 | 6 | 9 |
| 4 | 8 | 12 |
| 5 | 10 | 15 |
+--------------+--------------+--------------+).gsub(/^ +/, "")
end
end
end
end

describe "`row_divider_frequency` param" do
context "when table is initialized with `row_divider_frequency: nil`" do
let(:row_divider_frequency) { nil }
Expand Down Expand Up @@ -1182,27 +1257,18 @@
describe "`header_styler` param" do
it "styles the header cell content by calling the header_styler on the header text without "\
"affecting width calculations" do
table.add_column(
"Trebled",
formatter: -> (val) { "%.2f" % val },
header_styler: -> (str) { "\033[31;1;4m#{str}\033[0m" }
) do |n|
n * 3
end
table.add_column("Trebled", header_styler: -> (str) { "\033[31;1;4m#{str}\033[0m" }) { |n| n * 3 }

expect(table.to_s).to eq \
%Q(+--------------+--------------+--------------+
| N | Doubled | \033[31;1;4mTrebled\033[0m |
+--------------+--------------+--------------+
| 1 | 2 | 3.00 |
| 2 | 4 | 6.00 |
| 3 | 6 | 9.00 |
| 4 | 8 | 12.00 |
| 5 | 10 | 15.00 |
| 1 | 2 | 3 |
| 2 | 4 | 6 |
| 3 | 6 | 9 |
| 4 | 8 | 12 |
| 5 | 10 | 15 |
+--------------+--------------+--------------+).gsub(/^ +/, "")
top_right_body_cell = table.first.to_a.last
expect(top_right_body_cell.value).to eq(3)
expect(top_right_body_cell.value).to be_a(Integer)
end

it "applies the same styling to the truncation indicator as to the cell content" do
Expand Down

0 comments on commit 9a5b895

Please sign in to comment.