tabulo 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -14
- data/README.md +23 -16
- data/TODO.md +1 -7
- data/lib/tabulo/column.rb +25 -12
- data/lib/tabulo/row.rb +2 -2
- data/lib/tabulo/table.rb +96 -73
- data/lib/tabulo/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84dadcb8679194ba436e2e213defc55800771628
|
4
|
+
data.tar.gz: aa8d2182569ba3a439bce0b82ef8ceeeb36a4b81
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91d583322688d1db9f7c0dd21111f40d039da50fc767c78eecda2d640b75e42bae6478bc73a88b2c0810e1ce20fe35b61c7ad550a00b5c8a261fb2bf9e7c4b34
|
7
|
+
data.tar.gz: e0cee253d0513f05158b84bacd7c3e40ad0c546e5765b28c726ecab9936d7c67fa5893d032925bb43c28a96bc2002533c218105bf1ac0fdf43de07559b1106ad
|
data/CHANGELOG.md
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
|
3
|
+
### v0.6.0
|
4
4
|
|
5
|
-
*
|
5
|
+
* Correctly handle newlines in cell content.
|
6
|
+
* Use keyword arguments instead of option hashes.
|
7
|
+
* Write remaining pending specs.
|
6
8
|
|
7
|
-
|
9
|
+
### v0.5.1
|
10
|
+
|
11
|
+
* Unsuccessful attempt to fix broken appearance of http://www.rubydoc.info/gems/tabulo/0.5.1
|
12
|
+
|
13
|
+
### v0.5.0
|
8
14
|
|
9
15
|
* Add Table#shrinkwrap! method to automate column widths so they "just fit".
|
10
16
|
* Improve documentation.
|
11
|
-
* Minor tidy-ups.
|
12
17
|
|
13
|
-
|
18
|
+
### v0.4.2
|
14
19
|
|
15
20
|
* Improve README.
|
16
21
|
* Fix error when printing a Table, or a Row thereof, when the Table doesn't
|
@@ -18,44 +23,43 @@
|
|
18
23
|
* Remove unused development dependency on yard-tomdoc.
|
19
24
|
* Write more specs.
|
20
25
|
|
21
|
-
|
26
|
+
### v0.4.1
|
22
27
|
|
23
28
|
* Update README to reflect default column width of 12.
|
24
29
|
|
25
|
-
|
30
|
+
### v0.4.0
|
26
31
|
|
27
32
|
* Increase default column width from 8 to 12
|
28
33
|
* Allow default column width to be configured when initializing a Table
|
29
34
|
* Minor code tidy-ups, including removal of undocumented ability for
|
30
35
|
Table#add_column to accept a Column instance directly.
|
31
36
|
|
32
|
-
|
37
|
+
### v0.3.1
|
33
38
|
|
34
39
|
* Fix width and other options ignored by Table#add_column.
|
35
40
|
|
36
|
-
|
41
|
+
### v0.3.0
|
37
42
|
|
38
43
|
* Rename Table#header_row to Table#formatted_header
|
39
44
|
* Improve documentation, and use Yardoc instead of Tomdoc
|
40
45
|
* Remove Tabulo::Column from the publicly documented API.
|
41
46
|
|
42
|
-
|
47
|
+
### v0.2.2
|
43
48
|
|
44
49
|
* Write documentation
|
45
|
-
* Create a TODO file
|
46
50
|
|
47
|
-
|
51
|
+
### v0.2.1
|
48
52
|
|
49
53
|
* Code tidy-ups
|
50
54
|
* Tidy-ups and improvements to README, including adding badges for test coverage etc..
|
51
55
|
|
52
|
-
|
56
|
+
### v0.2.0
|
53
57
|
|
54
58
|
* Allow columns to be initialized with `columns` option in `Table` initializer
|
55
59
|
* Removed redundant `truncate` option.
|
56
60
|
* Rename `wrap_cells_to` to `wrap_body_cells_to`.
|
57
61
|
* Improve README.
|
58
62
|
|
59
|
-
|
63
|
+
### v0.1.0
|
60
64
|
|
61
65
|
Initial release.
|
data/README.md
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
[![Build Status][BS img]][Build Status]
|
5
5
|
[![Dependency Status][DS img]][Dependency Status]
|
6
6
|
[![Coverage Status][CS img]][Coverage Status]
|
7
|
+
[![Code Climate][CC img]][Code Climate]
|
7
8
|
|
8
9
|
## Overview
|
9
10
|
|
@@ -26,28 +27,30 @@ end
|
|
26
27
|
| 5000000 | 10000000 |
|
27
28
|
```
|
28
29
|
|
29
|
-
|
30
|
+
## Features
|
30
31
|
|
31
|
-
* Fix individual column widths, then either [wrap](#
|
32
|
-
[truncate](#
|
32
|
+
* [Fix](#fixed-column-widths) individual column widths, then either [wrap](#overflow-handling) or
|
33
|
+
[truncate](#overflow-handling) the overflow as you prefer.
|
33
34
|
* Alternatively, [shrinkwrap](#shrinkwrap) the table so that each column is just wide enough for
|
34
35
|
its contents.
|
35
36
|
* You can cap total table width when shrinkwrapping, to [stop it overflowing your terminal](#max-table-width)
|
36
37
|
horizontally and becoming an unreadable mess.
|
37
38
|
* Cell content alignment is [configurable](#cell-alignment), but with useful defaults, with numbers
|
38
39
|
aligned right and strings left.
|
39
|
-
* Headers
|
40
|
+
* Headers are [repeatable](#repeating-headers)
|
41
|
+
* Newlines within cell content are correctly handled.
|
40
42
|
* A `Tabulo::Table` is an `Enumerable`, so you can [step through it](#enumerator) one row at a time,
|
41
43
|
without having to wait for the entire underlying collection to load.
|
42
|
-
* Each `Tabulo::Row` is also an `Enumerable
|
44
|
+
* Each `Tabulo::Row` is also an `Enumerable`:
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
50
|
-
|
46
|
+
>
|
47
|
+
```ruby
|
48
|
+
table.each do |row|
|
49
|
+
row.each do |cell|
|
50
|
+
# cell => 1, 2 ... 2, 4 ... etc.
|
51
|
+
end
|
52
|
+
end
|
53
|
+
```
|
51
54
|
|
52
55
|
## Installation
|
53
56
|
|
@@ -139,9 +142,11 @@ the `align_header` or `align_body` options of `add_column`, e.g.:
|
|
139
142
|
table.add_column("Doubled", align_header: :left, align_body: :left) { |n| n * 2 }
|
140
143
|
```
|
141
144
|
|
142
|
-
<a name="width-wrapping-truncation"></a>
|
143
145
|
### Column width, wrapping and truncation
|
144
146
|
|
147
|
+
<a name="fixed-column-widths"></a>
|
148
|
+
#### Configuring fixed widths
|
149
|
+
|
145
150
|
By default, column width is fixed at 12 characters, plus 1 character of padding on either side.
|
146
151
|
This can be adjusted on a column-by-column basis using the `width` option of `add_column`:
|
147
152
|
|
@@ -180,7 +185,7 @@ table = Tabulo::Table.new([1, 2], columns: %i(itself even?), column_width: 6)
|
|
180
185
|
Widths set for individual columns always override the default column width for the table.
|
181
186
|
|
182
187
|
<a name="shrinkwrap"></a>
|
183
|
-
|
188
|
+
#### Automating column widths
|
184
189
|
|
185
190
|
Instead of setting column widths "manually", you can tell the table to sort out the widths
|
186
191
|
itself, so that each column is just wide enough for its header and contents (plus a character
|
@@ -222,7 +227,7 @@ puts Tabulo::Table.new([1, 2], columns: %i(itself even?)).shrinkwrap!(max_table_
|
|
222
227
|
| 2 | true |
|
223
228
|
```
|
224
229
|
|
225
|
-
If the table cannot be fit within `
|
230
|
+
If the table cannot be fit within `max_table_width`, column widths are reduced as required, with
|
226
231
|
wrapping or truncation then occuring as necessary (see [Overflow handling](#overflow-handling)).
|
227
232
|
Under the hood, a character of width is deducted column by column—the widest column being
|
228
233
|
targetted each time—until the table will fit. This is very useful when you want to ensure the
|
@@ -233,7 +238,7 @@ the maximum cell width needs to be calculated for each column. You may not want
|
|
233
238
|
if the collection is very large.
|
234
239
|
|
235
240
|
<a name="overflow-handling"></a>
|
236
|
-
|
241
|
+
#### Overflow handling
|
237
242
|
|
238
243
|
By default, if cell contents exceed their column width, they are wrapped for as many rows as
|
239
244
|
required:
|
@@ -394,8 +399,10 @@ License](http://opensource.org/licenses/MIT).
|
|
394
399
|
[Build Status]: https://travis-ci.org/matt-harvey/tabulo
|
395
400
|
[Dependency Status]: https://gemnasium.com/matt-harvey/tabulo
|
396
401
|
[Coverage Status]: https://coveralls.io/r/matt-harvey/tabulo
|
402
|
+
[Code Climate]: https://codeclimate.com/github/matt-harvey/tabulo
|
397
403
|
|
398
404
|
[GV img]: https://img.shields.io/gem/v/tabulo.svg
|
399
405
|
[BS img]: https://img.shields.io/travis/matt-harvey/tabulo.svg
|
400
406
|
[DS img]: https://img.shields.io/gemnasium/matt-harvey/tabulo.svg
|
401
407
|
[CS img]: https://img.shields.io/coveralls/matt-harvey/tabulo.svg
|
408
|
+
[CC img]: https://img.shields.io/codeclimate/github/matt-harvey/tabulo.svg
|
data/TODO.md
CHANGED
@@ -1,9 +1,3 @@
|
|
1
1
|
# TODO
|
2
2
|
|
3
|
-
*
|
4
|
-
* Raise an ArgumentError for disallowed arguments and options (this is
|
5
|
-
a library!)
|
6
|
-
* Column#initialize should have the same signature as Table#add_column.
|
7
|
-
* Handle multiline cell content (i.e. when the calculated cell value
|
8
|
-
itself contains a newline).
|
9
|
-
* Pending specs.
|
3
|
+
* Fix broken appearance of http://www.rubydoc.info/gems/tabulo/<version> .
|
data/lib/tabulo/column.rb
CHANGED
@@ -7,31 +7,34 @@ module Tabulo
|
|
7
7
|
attr_reader :header, :label
|
8
8
|
|
9
9
|
# @!visibility private
|
10
|
-
def initialize(
|
11
|
-
|
12
|
-
|
13
|
-
@
|
14
|
-
@
|
15
|
-
@
|
16
|
-
@
|
10
|
+
def initialize(label:, header:, width:, align_header:, align_body:,
|
11
|
+
formatter:, extractor:)
|
12
|
+
|
13
|
+
@label = label
|
14
|
+
@header = header
|
15
|
+
@width = width
|
16
|
+
@align_header = align_header
|
17
|
+
@align_body = align_body
|
18
|
+
@formatter = formatter
|
19
|
+
@extractor = extractor
|
17
20
|
end
|
18
21
|
|
19
22
|
# @!visibility private
|
20
|
-
def
|
21
|
-
|
23
|
+
def header_subcells
|
24
|
+
infilled_subcells(@header, @align_header)
|
22
25
|
end
|
23
26
|
|
24
27
|
# @!visibility private
|
25
28
|
def horizontal_rule
|
26
|
-
Table::HORIZONTAL_RULE_CHARACTER *
|
29
|
+
Table::HORIZONTAL_RULE_CHARACTER * width
|
27
30
|
end
|
28
31
|
|
29
32
|
# @!visibility private
|
30
|
-
def
|
33
|
+
def body_subcells(source)
|
31
34
|
cell_datum = body_cell_value(source)
|
32
35
|
formatted_content = @formatter.call(cell_datum)
|
33
36
|
real_alignment = (@align_body || infer_alignment(cell_datum))
|
34
|
-
|
37
|
+
infilled_subcells(formatted_content, real_alignment)
|
35
38
|
end
|
36
39
|
|
37
40
|
# @!visibility private
|
@@ -46,6 +49,16 @@ module Tabulo
|
|
46
49
|
|
47
50
|
private
|
48
51
|
|
52
|
+
# @!visibility private
|
53
|
+
def infilled_subcells(str, real_alignment)
|
54
|
+
str.split($/, -1).flat_map do |substr|
|
55
|
+
num_subsubcells = [1, (substr.length.to_f / width).ceil].max
|
56
|
+
(0...num_subsubcells).map do |i|
|
57
|
+
align_cell_content(substr.slice(i * width, width), real_alignment)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
49
62
|
# @!visibility private
|
50
63
|
def align_cell_content(content, real_alignment)
|
51
64
|
padding = [@width - content.length, 0].max
|
data/lib/tabulo/row.rb
CHANGED
@@ -4,10 +4,10 @@ module Tabulo
|
|
4
4
|
include Enumerable
|
5
5
|
|
6
6
|
# @!visibility private
|
7
|
-
def initialize(table, source,
|
7
|
+
def initialize(table, source, with_header: true)
|
8
8
|
@table = table
|
9
9
|
@source = source
|
10
|
-
@with_header =
|
10
|
+
@with_header = with_header
|
11
11
|
end
|
12
12
|
|
13
13
|
# Calls the given block once for each cell in the {Row}, passing that cell as parameter.
|
data/lib/tabulo/table.rb
CHANGED
@@ -15,73 +15,67 @@ module Tabulo
|
|
15
15
|
attr_reader :columns
|
16
16
|
|
17
17
|
# @param [Enumerable] sources the underlying Enumerable from which the table will derive its data
|
18
|
-
# @param [
|
19
|
-
# @option options [Array[Symbol]] :columns ([]) Specifies the initial columns.
|
18
|
+
# @param [Array[Symbol]] columns Specifies the initial columns.
|
20
19
|
# Each element of the Array will be used to create a column whose content is
|
21
20
|
# created by calling the corresponding method on each element of sources. Note
|
22
21
|
# the {#add_column} method is a much more flexible way to set up columns on the table.
|
23
|
-
# @
|
22
|
+
# @param [Fixnum, nil] column_width The default column width for columns in this
|
24
23
|
# table, not excluding padding. If nil, then DEFAULT_COLUMN_WIDTH will be used.
|
25
|
-
# @
|
24
|
+
# @param [:start, nil, Fixnum] header_frequency Controls the display of column headers.
|
26
25
|
# If passed <tt>:start</tt>, headers will be shown at the top of the table only. If passed <tt>nil</tt>,
|
27
26
|
# headers will not be shown. If passed a Fixnum N (> 0), headers will be shown at the top of the table,
|
28
27
|
# then repeated every N rows.
|
29
|
-
# @
|
28
|
+
# @param [nil, Fixnum] wrap_header_cells_to Controls wrapping behaviour for header
|
30
29
|
# cells if the content thereof is longer than the column's fixed width. If passed <tt>nil</tt> (default),
|
31
30
|
# content will be wrapped for as many rows as required to accommodate it. If passed a Fixnum N (> 0),
|
32
31
|
# content will be wrapped up to N rows and then truncated thereafter.
|
33
|
-
# @
|
32
|
+
# @param [nil, Fixnum] wrap_body_cells_to Controls wrapping behaviour for table cells (excluding
|
34
33
|
# headers), if their content is longer than the column's fixed width. If passed <tt>nil</tt>, content will
|
35
34
|
# be wrapped for as many rows as required to accommodate it. If passed a Fixnum N (> 0), content will be
|
36
35
|
# wrapped up to N rows and then truncated thereafter.
|
37
36
|
#
|
38
37
|
# @return [Table] a new Table
|
39
|
-
def initialize(sources,
|
40
|
-
|
41
|
-
columns: [],
|
42
|
-
column_width: DEFAULT_COLUMN_WIDTH,
|
43
|
-
header_frequency: :start,
|
38
|
+
def initialize(sources, columns: [], column_width: nil, header_frequency: :start,
|
39
|
+
wrap_header_cells_to: nil, wrap_body_cells_to: nil)
|
44
40
|
|
45
|
-
|
46
|
-
|
47
|
-
|
41
|
+
@sources = sources
|
42
|
+
@header_frequency = header_frequency
|
43
|
+
@wrap_header_cells_to = wrap_header_cells_to
|
44
|
+
@wrap_body_cells_to = wrap_body_cells_to
|
48
45
|
|
49
|
-
|
46
|
+
@default_column_width = (column_width || DEFAULT_COLUMN_WIDTH)
|
50
47
|
|
51
|
-
@header_frequency = opts[:header_frequency]
|
52
|
-
@wrap_header_cells_to = opts[:wrap_header_cells_to]
|
53
|
-
@wrap_body_cells_to = opts[:wrap_body_cells_to]
|
54
|
-
@sources = sources
|
55
48
|
@joiner = "|"
|
56
49
|
@truncation_indicator = "~"
|
57
50
|
@padding_character = " "
|
58
|
-
|
59
|
-
@columns =
|
51
|
+
|
52
|
+
@columns = []
|
53
|
+
columns.each { |item| add_column(item) }
|
54
|
+
|
60
55
|
yield self if block_given?
|
61
56
|
end
|
62
57
|
|
63
58
|
# Adds a column to the Table.
|
64
59
|
#
|
65
60
|
# @param [Symbol, String] label A unique identifier for this column, which by default will
|
66
|
-
# also be used as the column header text (see also the header
|
61
|
+
# also be used as the column header text (see also the header param). If the
|
67
62
|
# extractor argument is not also provided, then the label argument should correspond to
|
68
63
|
# a method to be called on each item in the table sources to provide the content
|
69
64
|
# for this column.
|
70
65
|
#
|
71
|
-
# @param [
|
72
|
-
#
|
73
|
-
#
|
74
|
-
# @option options [:left, :center, :right] :align_header (:center) Specifies how the header text
|
66
|
+
# @param [nil, #to_s] header (nil) Text to be displayed in the column header. If passed nil,
|
67
|
+
# the column's label will also be used as its header text.
|
68
|
+
# @param [:left, :center, :right] align_header (:center) Specifies how the header text
|
75
69
|
# should be aligned.
|
76
|
-
# @
|
70
|
+
# @param [:left, :center, :right, nil] align_body (nil) Specifies how the cell body contents
|
77
71
|
# should be aligned. Possible If <tt>nil</tt> is passed, then the alignment is determined
|
78
72
|
# by the type of the cell value, with numbers aligned right, booleans center-aligned, and
|
79
73
|
# other values left-aligned. Note header text alignment is configured separately using the
|
80
|
-
# :align_header
|
81
|
-
# @
|
82
|
-
# nil, then the column will take the width provided by the `column_width`
|
74
|
+
# :align_header param.
|
75
|
+
# @param [Fixnum] width (nil) Specifies the width of the column, excluding padding. If
|
76
|
+
# nil, then the column will take the width provided by the `column_width` param
|
83
77
|
# with which the Table was initialized.
|
84
|
-
# @
|
78
|
+
# @param [#to_proc] formatter (:to_s.to_proc) A lambda or other callable object that
|
85
79
|
# will be passed the calculated value of each cell to determine how it should be displayed. This
|
86
80
|
# is distinct from the extractor (see below). For example, if the extractor for this column
|
87
81
|
# generates a Date, then the formatter might format that Date in a particular way.
|
@@ -92,8 +86,18 @@ module Tabulo
|
|
92
86
|
# column. If this is not provided, then the column label will be treated as a method to be
|
93
87
|
# called on each source item to determine each cell's value.
|
94
88
|
#
|
95
|
-
def add_column(label,
|
96
|
-
|
89
|
+
def add_column(label, header: nil, align_header: :center, align_body: nil,
|
90
|
+
width: nil, formatter: :to_s.to_proc, &extractor)
|
91
|
+
|
92
|
+
@columns << Column.new(
|
93
|
+
label: label.to_sym,
|
94
|
+
header: (header || label).to_s,
|
95
|
+
align_header: align_header,
|
96
|
+
align_body: align_body,
|
97
|
+
width: (width || @default_column_width),
|
98
|
+
formatter: formatter,
|
99
|
+
extractor: (extractor || label.to_proc)
|
100
|
+
)
|
97
101
|
end
|
98
102
|
|
99
103
|
# @return [String] a graphical "ASCII" representation of the Table, suitable for
|
@@ -132,7 +136,7 @@ module Tabulo
|
|
132
136
|
|
133
137
|
# @return [String] an "ASCII" graphical representation of the Table column headers.
|
134
138
|
def formatted_header
|
135
|
-
format_row(
|
139
|
+
format_row(@wrap_header_cells_to, &:header_subcells)
|
136
140
|
end
|
137
141
|
|
138
142
|
# @return [String] an "ASCII" graphical representation of a horizontal
|
@@ -145,7 +149,8 @@ module Tabulo
|
|
145
149
|
# end
|
146
150
|
#
|
147
151
|
def horizontal_rule
|
148
|
-
|
152
|
+
inner = @columns.map { |column| surround(column.horizontal_rule, HORIZONTAL_RULE_CHARACTER) }
|
153
|
+
surround_join(inner, CORNER_CHARACTER)
|
149
154
|
end
|
150
155
|
|
151
156
|
# Reset all the column widths so that each column is *just* wide enough to accommodate
|
@@ -157,23 +162,28 @@ module Tabulo
|
|
157
162
|
# be traversed and all the column extractors and formatters to be applied in order
|
158
163
|
# to calculate the required widths.
|
159
164
|
#
|
160
|
-
# @param [
|
161
|
-
# @option options [String] :max_table_width (nil) If provided, stops the total table
|
165
|
+
# @param [nil, Numeric] max_table_width (nil) If provided, stops the total table
|
162
166
|
# width (including padding and borders) from expanding beyond this number of characters.
|
163
167
|
# Width is deducted from columns if required to achieve this, with one character progressively
|
164
168
|
# deducted from the width of the widest column until the target is reached. When the
|
165
169
|
# table is printed, wrapping or truncation will then occur in these columns as required
|
166
|
-
# (depending on how they were configured).
|
170
|
+
# (depending on how they were configured). Note that regardless of the value passed to
|
171
|
+
# max_table_width, the table will always be left wide enough to accommodate at least
|
172
|
+
# 1 character's width of content, 1 character of left padding and 1 character of right padding
|
173
|
+
# in each column, together with border characters (1 on each side of the table and 1 between
|
174
|
+
# adjacent columns). I.e. there is a certain width below width the Table will refuse to
|
175
|
+
# shrink itself.
|
167
176
|
#
|
168
177
|
# @return [Table] the Table itself
|
169
|
-
def shrinkwrap!(
|
178
|
+
def shrinkwrap!(max_table_width: nil)
|
170
179
|
return self if columns.none?
|
171
|
-
max_table_width = options[:max_table_width]
|
172
180
|
|
173
181
|
header_widths = columns.map { |c| c.header.length }
|
174
182
|
|
175
183
|
column_widths = @sources.inject(header_widths) do |widths, source|
|
176
|
-
columns.map
|
184
|
+
columns.map do |c|
|
185
|
+
c.formatted_cell_content(source).split($/, -1).map(&:length).max || 1
|
186
|
+
end.zip(widths).map(&:max)
|
177
187
|
end
|
178
188
|
|
179
189
|
columns.zip(column_widths).each do |column, width|
|
@@ -188,7 +198,6 @@ module Tabulo
|
|
188
198
|
|
189
199
|
# Ensure max table width is at least wide enough to accommodate table borders and padding
|
190
200
|
# and one character of content.
|
191
|
-
# TODO Document this behaviour.
|
192
201
|
min_table_width = total_padding + total_borders + columns.count
|
193
202
|
max_table_width = min_table_width if min_table_width > max_table_width
|
194
203
|
|
@@ -207,9 +216,9 @@ module Tabulo
|
|
207
216
|
end
|
208
217
|
|
209
218
|
# @!visibility private
|
210
|
-
def formatted_body_row(source,
|
211
|
-
inner = format_row { |column| column.
|
212
|
-
if
|
219
|
+
def formatted_body_row(source, with_header: false)
|
220
|
+
inner = format_row(@wrap_body_cells_to) { |column| column.body_subcells(source) }
|
221
|
+
if with_header
|
213
222
|
join_lines([horizontal_rule, formatted_header, horizontal_rule, inner])
|
214
223
|
else
|
215
224
|
inner
|
@@ -219,56 +228,70 @@ module Tabulo
|
|
219
228
|
private
|
220
229
|
|
221
230
|
# @!visibility private
|
222
|
-
def body_row(source,
|
223
|
-
Row.new(self, source,
|
231
|
+
def body_row(source, with_header: false)
|
232
|
+
Row.new(self, source, with_header: with_header)
|
224
233
|
end
|
225
234
|
|
226
235
|
# @!visibility private
|
227
|
-
|
228
|
-
|
236
|
+
#
|
237
|
+
# Yields each column to passed block, then wraps and joins the results to form
|
238
|
+
# a formatted row.
|
239
|
+
def format_row(wrap_cells_to)
|
240
|
+
|
241
|
+
# Create an array of "cell stacks", each of which is an array of strings that
|
242
|
+
# will be stacked on top of each other to form a wrapped cell.
|
229
243
|
cell_stacks = @columns.map do |column|
|
230
|
-
raw = yield column
|
231
|
-
wrap = (header ? @wrap_header_cells_to : @wrap_body_cells_to)
|
232
244
|
column_width = column.width
|
233
|
-
|
234
|
-
truncated
|
235
|
-
|
236
|
-
|
237
|
-
(
|
238
|
-
|
239
|
-
|
240
|
-
|
245
|
+
|
246
|
+
# Get the raw, non-wrapped, non-truncated content of the cell.
|
247
|
+
raw_subcells = yield column
|
248
|
+
|
249
|
+
truncated = (wrap_cells_to && (raw_subcells.size > wrap_cells_to))
|
250
|
+
subcells = (wrap_cells_to ? raw_subcells[0...wrap_cells_to] : raw_subcells)
|
251
|
+
|
252
|
+
subcells.map.with_index do |subcell, i|
|
253
|
+
lpad = @padding_character
|
254
|
+
rpad = (truncated && (i == subcells.size - 1) ? @truncation_indicator : @padding_character)
|
255
|
+
"#{lpad}#{subcell}#{rpad}"
|
241
256
|
end
|
242
257
|
end
|
243
258
|
|
244
|
-
|
259
|
+
max_cell_stack_height = cell_stacks.map(&:size).max || 1
|
260
|
+
|
261
|
+
# A subrow is a string representing a single horizontal slice of this row that's
|
262
|
+
# strictly one character high.
|
263
|
+
subrows = (0...max_cell_stack_height).map do |subrow_index|
|
245
264
|
cell_stacks.map.with_index do |cell_stack, column_index|
|
246
265
|
if subrow_index < cell_stack.size
|
266
|
+
# This cell stack is at least as "deep" as the subrow we're on. So just
|
267
|
+
# grab the subcell for this subrow from this cell stack.
|
247
268
|
cell_stack[subrow_index]
|
248
269
|
else
|
249
|
-
|
270
|
+
# This cell stack is not "deep" enough. So we make an empty subcell to
|
271
|
+
# add to this subrow for this column
|
272
|
+
surround(' ' * @columns[column_index].width, @padding_character)
|
250
273
|
end
|
251
274
|
end
|
252
275
|
end
|
253
276
|
|
254
|
-
|
277
|
+
# Join each subrow with border characters, then join these with newlines, to form
|
278
|
+
# the wrapped, formatted row as a single string.
|
279
|
+
join_lines(subrows.map { |subrow| surround_join(subrow, @joiner) })
|
255
280
|
end
|
256
281
|
|
257
282
|
# @!visibility private
|
258
|
-
def
|
259
|
-
|
283
|
+
def surround(str, ch0)
|
284
|
+
"#{ch0}#{str}#{ch0}"
|
285
|
+
end
|
286
|
+
|
287
|
+
# @!visibility private
|
288
|
+
def surround_join(arr, ch)
|
289
|
+
surround(arr.join(ch), ch)
|
260
290
|
end
|
261
291
|
|
262
292
|
# @!visibility private
|
263
|
-
def
|
264
|
-
|
265
|
-
label: item.to_sym,
|
266
|
-
header: item.to_s,
|
267
|
-
align_header: :center,
|
268
|
-
width: @default_column_width,
|
269
|
-
formatter: :to_s.to_proc
|
270
|
-
|
271
|
-
}.merge(options))
|
293
|
+
def join_lines(lines)
|
294
|
+
lines.join($/) # join strings with cross-platform newline
|
272
295
|
end
|
273
296
|
end
|
274
297
|
end
|
data/lib/tabulo/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tabulo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Harvey
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|