Skip to content

Commit

Permalink
Add optional column_index parameter to header_styler
Browse files Browse the repository at this point in the history
  • Loading branch information
matt-harvey committed Mar 28, 2020
1 parent a6a28d7 commit 3a98c50
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 53 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,10 @@ to cells in the table body, use the `header_styler` option, e.g.:
table.add_column(:even?, header_styler: -> (s) { "\033[32m#{s}\033[0m" })
```

The `header_styler` option accepts either a 1- or 2-parameter callable. See the
[documentation](https://www.rubydoc.info/gems/tabulo/2.3.3/Tabulo/Table#add_column-instance_method)
for details.

<a name="default-styles"></a>
#### Setting default styles

Expand Down
15 changes: 10 additions & 5 deletions lib/tabulo/column.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ def initialize(
@index = index

@header_styler =
if header_styler
-> (_, s) { header_styler.call(s) }
if header_styler && (header_styler.arity == 2)
-> (_, str, cell_data) { header_styler.call(str, cell_data.position.column) }
elsif header_styler
-> (_, str) { header_styler.call(str) }
else
-> (_, s) { s }
-> (_, str) { str }
end

@padding_character = padding_character
Expand All @@ -40,10 +42,13 @@ def initialize(
end

def header_cell
# TODO Position should optionally feature in the header_styler callback
if @header_styler.arity == 3
position = Position.new(row: nil, column: @index)
cell_data = CellData.new(source: nil, position: position)
end
Cell.new(
alignment: @align_header,
cell_data: nil,
cell_data: cell_data,
formatter: -> (s) { s },
padding_character: @padding_character,
styler: @header_styler,
Expand Down
31 changes: 20 additions & 11 deletions lib/tabulo/table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -186,17 +186,26 @@ def initialize(sources, *columns, align_body: :auto, align_header: :center, bord
# See the documentation for {CellData} for more.
# @param [nil, #to_s] header (nil) Text to be displayed in the column header. If passed nil,
# the column's label will also be used as its header text.
# @param [nil, #to_proc] header_styler (nil) A lambda or other callable object taking
# a single parameter, representing a single line of within the header content for
# this column. For example, if the header cell content is wrapped over three lines, then
# the <tt>header_styler</tt> will be called once for each line. If passed <tt>nil</tt>, then
# no additional styling will be applied to the header cell content. If passed a callable,
# then that callable will be called for each line of content within the header cell, and the
# resulting string rendered in place of that line. The extra width of the string returned by the
# <tt>header_styler</tt> is not taken into consideration by the internal table and
# cell width calculations involved in rendering the table. Thus it can be used to apply
# ANSI escape codes to header cell content, to colour the cell content for example, without
# breaking the table formatting.
# @param [nil, #to_proc] header_styler (nil) A lambda or other callable object that will
# determine the colors or other styling applied to the header content. Can be passed
# <tt>nil</tt>, or can be passed a callable that takes either 1 or 2 parameters:
# * If passed <tt>nil</tt>, then no additional styling will be applied to the cell content
# (other than what was already applied by the <tt>formatter</tt>).
# * If passed a callable, then that callable will be called for each line of content within
# the header cell, and the resulting string rendered in place of that line.
# The extra width of the string returned by the <tt>header_styler</tt> is not taken into
# consideration by the internal table and cell width calculations involved in rendering the
# table. Thus it can be used to apply ANSI escape codes to header cell content, to color the
# cell content for example, without breaking the table formatting.
# * If the passed callable takes 1 parameter, then the first parameter is a string
# representing a single formatted line within the header cell. For example, if the header
# cell content is wrapped over three lines, then the <tt>header_styler</tt> will be called
# three times for that header cell, once for each line of content.
# * If the passed callable takes 2 parameters, then the first parameter is as above, and the
# second parameter is an Integer representing the positional index of this header's {Column},
# with the leftmost column having index 0, the next having index 1 etc.. This can be
# used, for example, to apply different styles to alternating {Column}s.
#
# Note that if the header content is truncated, then any <tt>header_styler</tt> will be applied to the
# truncation indicator character as well as to the truncated content.
# @param [nil, #to_proc] styler (nil) A lambda or other callable object that will determine
Expand Down
99 changes: 62 additions & 37 deletions spec/table_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1399,49 +1399,74 @@
end

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", header_styler: -> (str) { "\033[31;1;4m#{str}\033[0m" }) { |n| n * 3 }
context "when passed a 1-parameter callable" 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", 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 |
| 2 | 4 | 6 |
| 3 | 6 | 9 |
| 4 | 8 | 12 |
| 5 | 10 | 15 |
+--------------+--------------+--------------+).gsub(/^ +/, "")
end
expect(table.to_s).to eq \
%Q(+--------------+--------------+--------------+
| N | Doubled | \033[31;1;4mTrebled\033[0m |
+--------------+--------------+--------------+
| 1 | 2 | 3 |
| 2 | 4 | 6 |
| 3 | 6 | 9 |
| 4 | 8 | 12 |
| 5 | 10 | 15 |
+--------------+--------------+--------------+).gsub(/^ +/, "")
end

it "applies the same styling to the truncation indicator as to the cell content" do
table = Tabulo::Table.new(%w[hello yes], wrap_header_cells_to: 1)
table.add_column("itself", width: 3, header_styler: -> (str) { "\033[31m#{str}\033[0m" }) { |n| n }
it "applies the same styling to the truncation indicator as to the cell content" do
table = Tabulo::Table.new(%w[hello yes], wrap_header_cells_to: 1)
table.add_column("itself", width: 3, header_styler: -> (str) { "\033[31m#{str}\033[0m" }) { |n| n }

expect(table.to_s).to eq \
%Q(+-----+
| \033[31mits\033[0m\033[31m~\033[0m|
+-----+
| hel |
| lo |
| yes |
+-----+).gsub(/^ +/, "")
expect(table.to_s).to eq \
%Q(+-----+
| \033[31mits\033[0m\033[31m~\033[0m|
+-----+
| hel |
| lo |
| yes |
+-----+).gsub(/^ +/, "")
end

it "applies styling separately to each part of the wrapped header cell content that's on its own line" do
table = Tabulo::Table.new(%w[hello yes])
table.add_column("itself", width: 3, header_styler: -> (str) { "\033[31m#{str}\033[0m" }) { |n| n }

expect(table.to_s).to eq \
%Q(+-----+
| \033[31mits\033[0m |
| \033[31melf\033[0m |
+-----+
| hel |
| lo |
| yes |
+-----+).gsub(/^ +/, "")
end
end

it "applies styling separately to each part of the wrapped header cell content that's on its own line" do
table = Tabulo::Table.new(%w[hello yes])
table.add_column("itself", width: 3, header_styler: -> (str) { "\033[31m#{str}\033[0m" }) { |n| n }
context "when passed a 2-parameter callable" do
it "styles the header cell content by calling the header_styler on the header text without "\
"affecting width calculations, passing the header content and the column index" do
header_styler = -> (str, column_index) do
expect(column_index).to eq(2)
"\033[31;1;4m#{str}\033[0m"
end
table.add_column("Trebled", header_styler: header_styler) { |n| n * 3 }

expect(table.to_s).to eq \
%Q(+--------------+--------------+--------------+
| N | Doubled | \033[31;1;4mTrebled\033[0m |
+--------------+--------------+--------------+
| 1 | 2 | 3 |
| 2 | 4 | 6 |
| 3 | 6 | 9 |
| 4 | 8 | 12 |
| 5 | 10 | 15 |
+--------------+--------------+--------------+).gsub(/^ +/, "")
end

expect(table.to_s).to eq \
%Q(+-----+
| \033[31mits\033[0m |
| \033[31melf\033[0m |
+-----+
| hel |
| lo |
| yes |
+-----+).gsub(/^ +/, "")
end
end

Expand Down

0 comments on commit 3a98c50

Please sign in to comment.