tabulo 2.3.0 → 2.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +142 -96
- data/VERSION +1 -1
- data/lib/tabulo/table.rb +76 -92
- data/lib/tabulo/version.rb +1 -1
- data/tabulo.gemspec +4 -4
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1aa563982fa70661534282898690138b6ee57a9aacf74edec622e148d4c3cfdb
|
4
|
+
data.tar.gz: 5d4265a55ba3add10cdcef1408a81446fb4a9aa8a48da6997ac6f193eeba0f05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8737456dfe272f6b7cf3714ee17dede09be428101ea05ba7f8eef3fdd3bb7e4e9d19c121d499c40374b48ae6b92ceda341ce39c05884f624c19bfa0309f307c
|
7
|
+
data.tar.gz: 3222d37f42ea2568d6d3e6f9901fbfcf0cae94eeb10440051186f2caab375ab1effb6eafe95ba7dc43c4810fbfc905cbe5095befa264d612e4f0ef20f31ac61e
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -43,7 +43,7 @@ end
|
|
43
43
|
|
44
44
|
## Features
|
45
45
|
|
46
|
-
* Presents a [DRY initialization interface](#
|
46
|
+
* Presents a [DRY initialization interface](#adding-columns): by being “column based” rather than
|
47
47
|
“row based”, it spares the developer the burden of syncing the ordering within the header row
|
48
48
|
with that of the body rows.
|
49
49
|
* Lets you set [fixed column widths](#fixed-column-widths), then either [wrap](#overflow-handling)
|
@@ -75,12 +75,18 @@ Tabulo has also been ported to Crystal (with some modifications): see [Tablo](ht
|
|
75
75
|
* [Installation](#installation)
|
76
76
|
* [Detailed usage](#detailed-usage)
|
77
77
|
* [Requiring the gem](#requiring-the-gem)
|
78
|
-
* [
|
78
|
+
* [Creating a table](#table-initialization)
|
79
|
+
* [Adding columns](#adding-columns)
|
80
|
+
* [Quick API](#quick-api)
|
81
|
+
* [Full API](#quick-api)
|
82
|
+
* [Column labels _vs_ headers](#labels-headers)
|
83
|
+
* [Positioning columns](#column-positioning)
|
84
|
+
* [Removing columns](#removing-columns)
|
79
85
|
* [Cell alignment](#cell-alignment)
|
80
86
|
* [Column width, wrapping and truncation](#column-width-wrapping-and-truncation)
|
81
87
|
* [Configuring fixed widths](#configuring-fixed-widths)
|
82
|
-
* [Configuring padding](#configuring-padding)
|
83
88
|
* [Automating column widths](#automating-column-widths)
|
89
|
+
* [Configuring padding](#configuring-padding)
|
84
90
|
* [Overflow handling](#overflow-handling)
|
85
91
|
* [Formatting cell values](#formatting-cell-values)
|
86
92
|
* [Colours and other styling](#colours-and-styling)
|
@@ -124,33 +130,30 @@ Or install it yourself:
|
|
124
130
|
require 'tabulo'
|
125
131
|
```
|
126
132
|
|
127
|
-
|
128
|
-
|
129
|
-
You instantiate a `Tabulo::Table` by passing it an underlying `Enumerable` and then telling it
|
130
|
-
the columns you want to generate.
|
133
|
+
<a name="table-initialization"></a>
|
134
|
+
### Creating a table
|
131
135
|
|
132
|
-
|
133
|
-
|
136
|
+
You instantiate a `Tabulo::Table` by passing it an underlying `Enumerable`, being the collection of
|
137
|
+
things that you want to tabulate. Each member of this collection will end up
|
138
|
+
corresponding to a row of the table. The collection can be any `Enumerable`, for example a Ruby
|
139
|
+
`Array`, or an ActiveRecord relation:
|
134
140
|
|
135
141
|
```ruby
|
136
142
|
table = Tabulo::Table.new([1, 2, 5])
|
137
|
-
|
138
|
-
table.add_column(:even?)
|
139
|
-
table.add_column(:odd?)
|
143
|
+
other_table = Tabulo::Table.new(User.all)
|
140
144
|
```
|
141
145
|
|
142
|
-
|
146
|
+
For the table to be useful, however, it must also contain columns…
|
143
147
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
end
|
150
|
-
```
|
148
|
+
<a name="adding-columns"></a>
|
149
|
+
### Adding columns
|
150
|
+
|
151
|
+
<a name="quick-api"></a>
|
152
|
+
#### Quick API
|
151
153
|
|
152
|
-
When the columns correspond to methods
|
153
|
-
directly to `new` for each column
|
154
|
+
When the columns correspond to methods on members of the underlying enumerable, you can use
|
155
|
+
the “quick API”, by passing a symbol directly to `Tabulo::Table.new` for each column.
|
156
|
+
This symbol also provides the column header:
|
154
157
|
|
155
158
|
```ruby
|
156
159
|
table = Tabulo::Table.new([1, 2, 5], :itself, :even?, :odd?)
|
@@ -167,9 +170,32 @@ table = Tabulo::Table.new([1, 2, 5], :itself, :even?, :odd?)
|
|
167
170
|
+--------------+--------------+--------------+
|
168
171
|
```
|
169
172
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
+
<a name="full-api"></a>
|
174
|
+
#### Full API
|
175
|
+
|
176
|
+
Columns can also be added to the table one-by-one using `add_column`. This “full API” is
|
177
|
+
more verbose, but provides greater configurability:
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
table = Tabulo::Table.new([1, 2, 5])
|
181
|
+
table.add_column(:itself)
|
182
|
+
table.add_column(:even?)
|
183
|
+
table.add_column(:odd?)
|
184
|
+
```
|
185
|
+
|
186
|
+
Alternatively, you can pass an initialization block to `new`:
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
table = Tabulo::Table.new([1, 2, 5]) do |t|
|
190
|
+
t.add_column(:itself)
|
191
|
+
t.add_column(:even?)
|
192
|
+
t.add_column(:odd?)
|
193
|
+
end
|
194
|
+
```
|
195
|
+
|
196
|
+
With the full API, columns can also be initialized using a callable to which each object will be
|
197
|
+
passed to determine the value to be displayed in the table. In this case, the first argument to
|
198
|
+
`add_column` provides the header text:
|
173
199
|
|
174
200
|
```ruby
|
175
201
|
table = Tabulo::Table.new([1, 2, 5]) do |t|
|
@@ -190,6 +216,23 @@ end
|
|
190
216
|
+--------------+--------------+--------------+
|
191
217
|
```
|
192
218
|
|
219
|
+
<a name="labels-headers"></a>
|
220
|
+
#### Column labels _vs_ headers
|
221
|
+
|
222
|
+
The first argument to `add_column` is the called the _label_ for that column. It serves as the
|
223
|
+
column’s unique identifier: only one column may have a given label per table.
|
224
|
+
(`String`s and `Symbol`s are interchangeable for this purpose.) The label also forms the header shown
|
225
|
+
at the top of the column, unless a separate `header:` argument is explicitly passed:
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
table.add_column(:itself, header: "N")
|
229
|
+
table.add_column(:itself2, header: "N", &:itself) # header need not be unique
|
230
|
+
# table.add_column(:itself) # would raise Tabulo::InvalidColumnLabelError, as label must be unique
|
231
|
+
```
|
232
|
+
|
233
|
+
<a name="column-positioning"></a>
|
234
|
+
#### Positioning columns
|
235
|
+
|
193
236
|
By default, each new column is added to the right of all the other columns so far added to the
|
194
237
|
table. However, if you want to insert a new column into some other position, you can use the
|
195
238
|
`before` option, passing the label of the column to the left of which you want the new column to be added:
|
@@ -210,9 +253,15 @@ table.add_column(:even?, before: :odd?)
|
|
210
253
|
+--------------+--------------+--------------+
|
211
254
|
```
|
212
255
|
|
213
|
-
|
214
|
-
|
215
|
-
|
256
|
+
<a name="removing-columns"></a>
|
257
|
+
### Removing columns
|
258
|
+
|
259
|
+
There is also a `#remove_column` method, for deleting an existing column from a table. Pass it
|
260
|
+
the label of the column you want to remove:
|
261
|
+
|
262
|
+
```ruby
|
263
|
+
table.remove_column(:even?)
|
264
|
+
```
|
216
265
|
|
217
266
|
<a name="cell-alignment"></a>
|
218
267
|
### Cell alignment
|
@@ -279,92 +328,49 @@ table = Tabulo::Table.new([1, 2], :itself, :even?, column_width: 6)
|
|
279
328
|
|
280
329
|
Widths set for individual columns always override the default column width for the table.
|
281
330
|
|
282
|
-
<a name="configuring-padding"></a>
|
283
|
-
#### Configuring padding
|
284
|
-
|
285
|
-
The single character of padding either side of each column is not counted in the column width.
|
286
|
-
The amount of this extra padding can be configured for the table as a whole, using the `column_padding`
|
287
|
-
option passed to `Table.new`—the default value of this option being `1`.
|
288
|
-
|
289
|
-
Passing a single integer to this option causes the given amount of padding to be applied to each
|
290
|
-
side of each column. For example:
|
291
|
-
|
292
|
-
```ruby
|
293
|
-
table = Tabulo::Table.new([1, 2, 5], :itself, :even?, :odd?, column_padding: 0)
|
294
|
-
```
|
295
|
-
|
296
|
-
```
|
297
|
-
> puts table
|
298
|
-
+------------+------------+------------+
|
299
|
-
| itself | even? | odd? |
|
300
|
-
+------------+------------+------------+
|
301
|
-
| 1| false | true |
|
302
|
-
| 2| true | false |
|
303
|
-
| 5| false | true |
|
304
|
-
+------------+------------+------------+
|
305
|
-
```
|
306
|
-
|
307
|
-
Passing an array of _two_ integers to this option configures the left and right padding for each
|
308
|
-
column, according to the first and second element of the array, respectively. For example:
|
309
|
-
|
310
|
-
```ruby
|
311
|
-
table = Tabulo::Table.new([1, 2, 5], :itself, :even?, :odd?, column_padding: [0, 2])
|
312
|
-
```
|
313
|
-
|
314
|
-
```
|
315
|
-
> puts table
|
316
|
-
+--------------+--------------+--------------+
|
317
|
-
| itself | even? | odd? |
|
318
|
-
+--------------+--------------+--------------+
|
319
|
-
| 1 | false | true |
|
320
|
-
| 2 | true | false |
|
321
|
-
| 5 | false | true |
|
322
|
-
+--------------+--------------+--------------+
|
323
|
-
```
|
324
|
-
|
325
331
|
<a name="pack"></a>
|
326
332
|
#### Automating column widths
|
327
333
|
|
328
334
|
Instead of setting column widths “manually”, you can tell the table to sort out the widths
|
329
335
|
itself, so that each column is just wide enough for its header and contents (plus a character
|
330
|
-
of padding):
|
336
|
+
of padding on either side):
|
331
337
|
|
332
338
|
```ruby
|
333
|
-
table = Tabulo::Table.new([
|
339
|
+
table = Tabulo::Table.new(["short", "here is a longer phrase"], :itself, :size)
|
334
340
|
table.pack
|
335
341
|
```
|
336
342
|
|
337
343
|
```
|
338
344
|
> puts table
|
339
|
-
|
340
|
-
|
|
341
|
-
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
345
|
+
+-------------------------+------+
|
346
|
+
| itself | size |
|
347
|
+
+-------------------------+------+
|
348
|
+
| short | 5 |
|
349
|
+
| here is a longer phrase | 23 |
|
350
|
+
+-------------------------+------+
|
345
351
|
```
|
346
352
|
|
347
353
|
The `pack` method returns the table itself, so you can “pack-and-print” in one go:
|
348
354
|
|
349
355
|
```ruby
|
350
|
-
puts Tabulo::Table.new([
|
356
|
+
puts Tabulo::Table.new(["short", "here is a longer phrase"], :itself, :size).pack
|
351
357
|
```
|
352
358
|
|
353
359
|
<a name="max-table-width"></a>
|
354
360
|
You can manually place an upper limit on the total width of the table when packing:
|
355
361
|
|
356
362
|
```ruby
|
357
|
-
puts Tabulo::Table.new([
|
363
|
+
puts Tabulo::Table.new(["short", "here is a longer phrase"], :itself, :size).pack(max_table_width: 24)
|
358
364
|
```
|
359
365
|
|
360
366
|
```
|
361
|
-
|
362
|
-
|
|
363
|
-
|
364
|
-
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
367
|
+
+---------------+------+
|
368
|
+
| itself | size |
|
369
|
+
+---------------+------+
|
370
|
+
| short | 5 |
|
371
|
+
| here is a lon | 23 |
|
372
|
+
| ger phrase | |
|
373
|
+
+---------------+------+
|
368
374
|
```
|
369
375
|
|
370
376
|
Or if you simply call `pack` with no arguments (or if you explicitly call
|
@@ -391,6 +397,49 @@ resized yet again on printing. This is a consequence of the table always being e
|
|
391
397
|
table itself. There are [ways around this](#freezing-a-table), however, if this is not the desired
|
392
398
|
behaviour—see [below](#freezing-a-table).
|
393
399
|
|
400
|
+
<a name="configuring-padding"></a>
|
401
|
+
#### Configuring padding
|
402
|
+
|
403
|
+
The single character of padding either side of each column is not counted in the column width.
|
404
|
+
The amount of this extra padding can be configured for the table as a whole, using the `column_padding`
|
405
|
+
option passed to `Table.new`—the default value of this option being `1`.
|
406
|
+
|
407
|
+
Passing a single integer to this option causes the given amount of padding to be applied to each
|
408
|
+
side of each column. For example:
|
409
|
+
|
410
|
+
```ruby
|
411
|
+
table = Tabulo::Table.new([1, 2, 5], :itself, :even?, :odd?, column_padding: 0)
|
412
|
+
```
|
413
|
+
|
414
|
+
```
|
415
|
+
> puts table
|
416
|
+
+------------+------------+------------+
|
417
|
+
| itself | even? | odd? |
|
418
|
+
+------------+------------+------------+
|
419
|
+
| 1| false | true |
|
420
|
+
| 2| true | false |
|
421
|
+
| 5| false | true |
|
422
|
+
+------------+------------+------------+
|
423
|
+
```
|
424
|
+
|
425
|
+
Passing an array of _two_ integers to this option configures the left and right padding for each
|
426
|
+
column, according to the first and second element of the array, respectively. For example:
|
427
|
+
|
428
|
+
```ruby
|
429
|
+
table = Tabulo::Table.new([1, 2, 5], :itself, :even?, :odd?, column_padding: [0, 2])
|
430
|
+
```
|
431
|
+
|
432
|
+
```
|
433
|
+
> puts table
|
434
|
+
+--------------+--------------+--------------+
|
435
|
+
| itself | even? | odd? |
|
436
|
+
+--------------+--------------+--------------+
|
437
|
+
| 1 | false | true |
|
438
|
+
| 2 | true | false |
|
439
|
+
| 5 | false | true |
|
440
|
+
+--------------+--------------+--------------+
|
441
|
+
```
|
442
|
+
|
394
443
|
<a name="overflow-handling"></a>
|
395
444
|
#### Overflow handling
|
396
445
|
|
@@ -669,11 +718,8 @@ table.each do |row|
|
|
669
718
|
end
|
670
719
|
```
|
671
720
|
|
672
|
-
The
|
673
|
-
|
674
|
-
`Symbol` for purposes of accessing this `Hash`.) This key serves as a sort of “logical label”
|
675
|
-
for the column; and it need not be the same as the column header. If we want the header to be different
|
676
|
-
to the label, we can achieve this using the `header` option to `add_column`:
|
721
|
+
The column label (being the first argument that was passed to `add_column`, converted if necessary
|
722
|
+
to a `Symbol`), always forms the key for the purposes of this `Hash`:
|
677
723
|
|
678
724
|
```ruby
|
679
725
|
table = Tabulo::Table.new(1..3) do |t|
|
@@ -752,7 +798,7 @@ a new table in which the rows and columns are swapped:
|
|
752
798
|
By default, a header row is added to the new table, showing the string value of the element
|
753
799
|
represented in that column. This can be configured, however, along with other aspects of
|
754
800
|
`transpose`’s behaviour. For details, see the
|
755
|
-
[documentation](https://www.rubydoc.info/gems/tabulo/2.3.
|
801
|
+
[documentation](https://www.rubydoc.info/gems/tabulo/2.3.1/Tabulo/Table#transpose-instance_method).
|
756
802
|
|
757
803
|
<a name="borders"></a>
|
758
804
|
### Configuring borders
|
@@ -1061,14 +1107,14 @@ The gem is available as open source under the terms of the [MIT
|
|
1061
1107
|
License](http://opensource.org/licenses/MIT).
|
1062
1108
|
|
1063
1109
|
[Gem Version]: https://rubygems.org/gems/tabulo
|
1064
|
-
[Documentation]: http://www.rubydoc.info/gems/tabulo/2.3.
|
1110
|
+
[Documentation]: http://www.rubydoc.info/gems/tabulo/2.3.1
|
1065
1111
|
[Build Status]: https://travis-ci.org/matt-harvey/tabulo
|
1066
1112
|
[Coverage Status]: https://coveralls.io/r/matt-harvey/tabulo
|
1067
1113
|
[Code Climate]: https://codeclimate.com/github/matt-harvey/tabulo
|
1068
1114
|
[Awesome Ruby]: https://github.com/markets/awesome-ruby#cli-utilities
|
1069
1115
|
|
1070
1116
|
[GV img]: https://img.shields.io/gem/v/tabulo.svg
|
1071
|
-
[DC img]: https://img.shields.io/badge/documentation-v2.3.
|
1117
|
+
[DC img]: https://img.shields.io/badge/documentation-v2.3.1-blue.svg
|
1072
1118
|
[BS img]: https://img.shields.io/travis/matt-harvey/tabulo.svg
|
1073
1119
|
[CS img]: https://img.shields.io/coveralls/matt-harvey/tabulo.svg
|
1074
1120
|
[CC img]: https://codeclimate.com/github/matt-harvey/tabulo/badges/gpa.svg
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.3.
|
1
|
+
2.3.1
|
data/lib/tabulo/table.rb
CHANGED
@@ -107,23 +107,10 @@ module Tabulo
|
|
107
107
|
# @return [Table] a new {Table}
|
108
108
|
# @raise [InvalidColumnLabelError] if non-unique Symbols are provided to columns.
|
109
109
|
# @raise [InvalidBorderError] if invalid option passed to `border` parameter.
|
110
|
-
def initialize(
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
align_header: :center,
|
115
|
-
border: nil,
|
116
|
-
border_styler: nil,
|
117
|
-
column_padding: nil,
|
118
|
-
column_width: nil,
|
119
|
-
formatter: :to_s.to_proc,
|
120
|
-
header_frequency: :start,
|
121
|
-
header_styler: nil,
|
122
|
-
row_divider_frequency: nil,
|
123
|
-
styler: nil,
|
124
|
-
truncation_indicator: nil,
|
125
|
-
wrap_body_cells_to: nil,
|
126
|
-
wrap_header_cells_to: nil)
|
110
|
+
def initialize(sources, *columns, align_body: :auto, align_header: :center, border: nil,
|
111
|
+
border_styler: nil, column_padding: nil, column_width: nil, formatter: :to_s.to_proc,
|
112
|
+
header_frequency: :start, header_styler: nil, row_divider_frequency: nil, styler: nil,
|
113
|
+
truncation_indicator: nil, wrap_body_cells_to: nil, wrap_header_cells_to: nil)
|
127
114
|
|
128
115
|
@sources = sources
|
129
116
|
|
@@ -135,12 +122,7 @@ module Tabulo
|
|
135
122
|
@column_padding = (column_padding || DEFAULT_COLUMN_PADDING)
|
136
123
|
|
137
124
|
@left_column_padding, @right_column_padding =
|
138
|
-
|
139
|
-
when Array
|
140
|
-
@column_padding
|
141
|
-
else
|
142
|
-
[@column_padding, @column_padding]
|
143
|
-
end
|
125
|
+
Array === @column_padding ? @column_padding : [@column_padding, @column_padding]
|
144
126
|
|
145
127
|
@column_width = (column_width || DEFAULT_COLUMN_WIDTH)
|
146
128
|
@formatter = formatter
|
@@ -230,25 +212,10 @@ module Tabulo
|
|
230
212
|
# @raise [InvalidColumnLabelError] if label has already been used for another column in this
|
231
213
|
# Table. (This is case-sensitive, but is insensitive to whether a String or Symbol is passed
|
232
214
|
# to the label parameter.)
|
233
|
-
def add_column(
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
before: nil,
|
238
|
-
formatter: nil,
|
239
|
-
header: nil,
|
240
|
-
header_styler: nil,
|
241
|
-
styler: nil,
|
242
|
-
width: nil,
|
243
|
-
&extractor)
|
244
|
-
|
245
|
-
column_label =
|
246
|
-
case label
|
247
|
-
when Integer, Symbol
|
248
|
-
label
|
249
|
-
when String
|
250
|
-
label.to_sym
|
251
|
-
end
|
215
|
+
def add_column(label, align_body: nil, align_header: nil, before: nil, formatter: nil,
|
216
|
+
header: nil, header_styler: nil, styler: nil, width: nil, &extractor)
|
217
|
+
|
218
|
+
column_label = normalize_column_label(label)
|
252
219
|
|
253
220
|
if column_registry.include?(column_label)
|
254
221
|
raise InvalidColumnLabelError, "Column label already used in this table."
|
@@ -267,7 +234,11 @@ module Tabulo
|
|
267
234
|
width: width || @column_width,
|
268
235
|
)
|
269
236
|
|
270
|
-
|
237
|
+
if before == nil
|
238
|
+
add_column_final(column, column_label)
|
239
|
+
else
|
240
|
+
add_column_before(column, column_label, before)
|
241
|
+
end
|
271
242
|
end
|
272
243
|
|
273
244
|
# Removes the column identifed by the passed label.
|
@@ -315,22 +286,17 @@ module Tabulo
|
|
315
286
|
# Note that when printed, the first row will visually include the headers (assuming these
|
316
287
|
# were not disabled when the Table was initialized).
|
317
288
|
def each
|
289
|
+
header_frequency_is_integer = (Integer === @header_frequency)
|
318
290
|
@sources.each_with_index do |source, index|
|
291
|
+
is_first_row = (index == 0)
|
319
292
|
header =
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
if index == 0
|
325
|
-
:top
|
326
|
-
elsif index % @header_frequency == 0
|
327
|
-
:middle
|
328
|
-
end
|
329
|
-
else
|
330
|
-
@header_frequency
|
293
|
+
if is_first_row && (@header_frequency == :start || header_frequency_is_integer)
|
294
|
+
:top
|
295
|
+
elsif header_frequency_is_integer && (index % @header_frequency == 0)
|
296
|
+
:middle
|
331
297
|
end
|
332
298
|
|
333
|
-
show_divider = @row_divider_frequency &&
|
299
|
+
show_divider = @row_divider_frequency && !is_first_row && (index % @row_divider_frequency == 0)
|
334
300
|
|
335
301
|
yield Row.new(self, source, header: header, divider: show_divider)
|
336
302
|
end
|
@@ -338,7 +304,7 @@ module Tabulo
|
|
338
304
|
|
339
305
|
# @return [String] an "ASCII" graphical representation of the Table column headers.
|
340
306
|
def formatted_header
|
341
|
-
cells =
|
307
|
+
cells = get_columns.map(&:header_cell)
|
342
308
|
format_row(cells, @wrap_header_cells_to)
|
343
309
|
end
|
344
310
|
|
@@ -360,7 +326,7 @@ module Tabulo
|
|
360
326
|
# It may be that `:top`, `:middle` and `:bottom` all look the same. Whether
|
361
327
|
# this is the case depends on the characters used for the table border.
|
362
328
|
def horizontal_rule(position = :bottom)
|
363
|
-
column_widths =
|
329
|
+
column_widths = get_columns.map { |column| column.width + total_column_padding }
|
364
330
|
@border_instance.horizontal_rule(column_widths, position)
|
365
331
|
end
|
366
332
|
|
@@ -393,15 +359,12 @@ module Tabulo
|
|
393
359
|
# Table will refuse to shrink itself.
|
394
360
|
# @return [Table] the Table itself
|
395
361
|
def pack(max_table_width: :auto)
|
396
|
-
|
397
|
-
columns = column_registry.values
|
398
|
-
|
399
|
-
columns.each { |column| column.width = wrapped_width(column.header) }
|
362
|
+
get_columns.each { |column| column.width = wrapped_width(column.header) }
|
400
363
|
|
401
364
|
@sources.each do |source|
|
402
|
-
|
365
|
+
get_columns.each do |column|
|
403
366
|
width = wrapped_width(column.body_cell(source).formatted_content)
|
404
|
-
column.width = width
|
367
|
+
column.width = [width, column.width].max
|
405
368
|
end
|
406
369
|
end
|
407
370
|
|
@@ -492,20 +455,27 @@ module Tabulo
|
|
492
455
|
|
493
456
|
# @!visibility private
|
494
457
|
def formatted_body_row(source, header:, divider:)
|
495
|
-
cells =
|
458
|
+
cells = get_columns.map { |column| column.body_cell(source) }
|
496
459
|
inner = format_row(cells, @wrap_body_cells_to)
|
497
460
|
|
498
|
-
if header
|
461
|
+
if header == :top
|
462
|
+
join_lines([
|
463
|
+
horizontal_rule(:top),
|
464
|
+
formatted_header,
|
465
|
+
horizontal_rule(:middle),
|
466
|
+
inner
|
467
|
+
].reject(&:empty?))
|
468
|
+
elsif header
|
499
469
|
join_lines([
|
500
|
-
horizontal_rule(
|
470
|
+
horizontal_rule(:middle),
|
501
471
|
formatted_header,
|
502
472
|
horizontal_rule(:middle),
|
503
|
-
inner
|
473
|
+
inner
|
504
474
|
].reject(&:empty?))
|
505
475
|
elsif divider
|
506
476
|
join_lines([
|
507
477
|
horizontal_rule(:middle),
|
508
|
-
inner
|
478
|
+
inner
|
509
479
|
].reject(&:empty?))
|
510
480
|
else
|
511
481
|
inner
|
@@ -514,39 +484,49 @@ module Tabulo
|
|
514
484
|
|
515
485
|
private
|
516
486
|
|
487
|
+
# @!visibility private
|
488
|
+
def get_columns
|
489
|
+
column_registry.values
|
490
|
+
end
|
491
|
+
|
517
492
|
# @!visibility private
|
518
493
|
def add_column_before(column, label, before)
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
new_column_entries
|
524
|
-
|
525
|
-
old_column_entries.each do |entry|
|
526
|
-
if entry[0] == before
|
527
|
-
found = true
|
528
|
-
new_column_entries << [label, column]
|
529
|
-
end
|
530
|
-
new_column_entries << entry
|
531
|
-
end
|
532
|
-
unless found
|
533
|
-
raise InvalidColumnLabelError, "There is no column with label #{before}"
|
534
|
-
end
|
535
|
-
@column_registry = new_column_entries.to_h
|
494
|
+
old_column_entries = @column_registry.to_a
|
495
|
+
new_column_entries = []
|
496
|
+
|
497
|
+
old_column_entries.each do |entry|
|
498
|
+
new_column_entries << [label, column] if entry[0] == before
|
499
|
+
new_column_entries << entry
|
536
500
|
end
|
501
|
+
|
502
|
+
found = (new_column_entries.size == old_column_entries.size + 1)
|
503
|
+
raise InvalidColumnLabelError, "There is no column with label #{before}" unless found
|
504
|
+
|
505
|
+
@column_registry = new_column_entries.to_h
|
537
506
|
end
|
538
507
|
|
539
508
|
# @!visibility private
|
540
|
-
def
|
541
|
-
@
|
509
|
+
def add_column_final(column, label)
|
510
|
+
@column_registry[label] = column
|
511
|
+
end
|
512
|
+
|
513
|
+
# @!visibility private
|
514
|
+
def normalize_column_label(label)
|
515
|
+
case label
|
516
|
+
when Integer, Symbol
|
517
|
+
label
|
518
|
+
when String
|
519
|
+
label.to_sym
|
520
|
+
end
|
542
521
|
end
|
543
522
|
|
544
523
|
# @!visibility private
|
545
524
|
def shrink_to(max_table_width)
|
546
|
-
columns =
|
525
|
+
columns = get_columns
|
526
|
+
num_columns = columns.count
|
547
527
|
total_columns_width = columns.inject(0) { |sum, column| sum + column.width }
|
548
|
-
total_padding =
|
549
|
-
total_borders =
|
528
|
+
total_padding = num_columns * total_column_padding
|
529
|
+
total_borders = num_columns + 1
|
550
530
|
unadjusted_table_width = total_columns_width + total_padding + total_borders
|
551
531
|
|
552
532
|
# Ensure max table width is at least wide enough to accommodate table borders and padding
|
@@ -564,6 +544,11 @@ module Tabulo
|
|
564
544
|
end
|
565
545
|
end
|
566
546
|
|
547
|
+
# @!visibility private
|
548
|
+
def total_column_padding
|
549
|
+
@left_column_padding + @right_column_padding
|
550
|
+
end
|
551
|
+
|
567
552
|
# @!visibility private
|
568
553
|
#
|
569
554
|
# Formats a single header row or body row as a String.
|
@@ -615,8 +600,7 @@ module Tabulo
|
|
615
600
|
def wrapped_width(str)
|
616
601
|
segments = str.split($/)
|
617
602
|
segments.inject(1) do |longest_length_so_far, segment|
|
618
|
-
|
619
|
-
longest_length_so_far > length ? longest_length_so_far : length
|
603
|
+
[longest_length_so_far, Unicode::DisplayWidth.of(segment)].max
|
620
604
|
end
|
621
605
|
end
|
622
606
|
end
|
data/lib/tabulo/version.rb
CHANGED
data/tabulo.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Matthew Harvey"]
|
10
10
|
spec.email = ["software@matthewharvey.net"]
|
11
11
|
|
12
|
-
spec.summary = "
|
13
|
-
spec.description = "
|
12
|
+
spec.summary = "Terminal table generator"
|
13
|
+
spec.description = "Plain text table generator with a column-based API"
|
14
14
|
spec.homepage = "https://github.com/matt-harvey/tabulo"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -28,8 +28,8 @@ Gem::Specification.new do |spec|
|
|
28
28
|
"changelog_uri" => "https://raw.githubusercontent.com/matt-harvey/tabulo/master/CHANGELOG.md"
|
29
29
|
}
|
30
30
|
|
31
|
-
spec.add_runtime_dependency "tty-screen", "0.7.
|
32
|
-
spec.add_runtime_dependency "unicode-display_width", "1.6.
|
31
|
+
spec.add_runtime_dependency "tty-screen", "0.7.1"
|
32
|
+
spec.add_runtime_dependency "unicode-display_width", "1.6.1"
|
33
33
|
|
34
34
|
spec.add_development_dependency "bundler"
|
35
35
|
spec.add_development_dependency "rake", "~> 11.0"
|
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: 2.3.
|
4
|
+
version: 2.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Harvey
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tty-screen
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.7.
|
19
|
+
version: 0.7.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.7.
|
26
|
+
version: 0.7.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: unicode-display_width
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.6.
|
33
|
+
version: 1.6.1
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.6.
|
40
|
+
version: 1.6.1
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,7 +164,7 @@ dependencies:
|
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '1.0'
|
167
|
-
description:
|
167
|
+
description: Plain text table generator with a column-based API
|
168
168
|
email:
|
169
169
|
- software@matthewharvey.net
|
170
170
|
executables: []
|
@@ -222,5 +222,5 @@ rubyforge_project:
|
|
222
222
|
rubygems_version: 2.7.6
|
223
223
|
signing_key:
|
224
224
|
specification_version: 4
|
225
|
-
summary:
|
225
|
+
summary: Terminal table generator
|
226
226
|
test_files: []
|