tabulo 2.6.2 → 2.7.2
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/.github/workflows/tests.yml +58 -0
- data/.gitignore +1 -0
- data/.simplecov +0 -0
- data/CHANGELOG.md +19 -0
- data/README.md +130 -17
- data/VERSION +1 -1
- data/lib/tabulo/cell.rb +76 -16
- data/lib/tabulo/column.rb +4 -0
- data/lib/tabulo/table.rb +22 -4
- data/lib/tabulo/version.rb +1 -1
- data/tabulo.gemspec +2 -2
- metadata +8 -7
- data/.travis.yml +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2419c20288ae285e4fcbfefd5627f6dac370ab3940969093216283407df6ee4
|
4
|
+
data.tar.gz: '08ee67482f630a3f185319fcc7fec4844b3a64d70042f3afc9abb993e4a65260'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 97f9cc96273afdc2fb30f341cc7dede4440cc2198209035bdbb65bf4872628a0db6a42f29287a7f9a2aa08c0fd2495bd7cdf189529ef1ce93f62797a5cfdb8dd
|
7
|
+
data.tar.gz: 96e4fd149487e51a49bb3935ec4341c0a327f101d028019b8bf73279b3e239cf3d8deb0fd5efda92c8d10d79c5bf1973b16344e45e753695b6920c6c4111f852
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Tests
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [master]
|
13
|
+
pull_request:
|
14
|
+
branches: [master]
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
test:
|
18
|
+
runs-on: ubuntu-latest
|
19
|
+
strategy:
|
20
|
+
matrix:
|
21
|
+
ruby-version: [
|
22
|
+
'2.2.10',
|
23
|
+
'2.3.8',
|
24
|
+
'2.4.10',
|
25
|
+
'2.5.9',
|
26
|
+
'2.6.9',
|
27
|
+
'2.7.5',
|
28
|
+
'3.0.3',
|
29
|
+
]
|
30
|
+
steps:
|
31
|
+
- uses: actions/checkout@v2
|
32
|
+
- name: Set up Ruby
|
33
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
34
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
35
|
+
uses: ruby/setup-ruby@v1 # Was: uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
|
36
|
+
with:
|
37
|
+
ruby-version: ${{ matrix.ruby-version }}
|
38
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
39
|
+
- name: Run tests
|
40
|
+
run: bundle exec rspec
|
41
|
+
|
42
|
+
- name: Report to Coveralls
|
43
|
+
uses: coverallsapp/github-action@v1.1.2
|
44
|
+
with:
|
45
|
+
github-token: ${{ secrets.github_token }}
|
46
|
+
flag-name: test-${{ matrix.ruby }}-${{ matrix.gemfile }}
|
47
|
+
parallel: true
|
48
|
+
|
49
|
+
finish:
|
50
|
+
needs: test
|
51
|
+
runs-on: ubuntu-latest
|
52
|
+
steps:
|
53
|
+
|
54
|
+
- name: Report completion to Coveralls
|
55
|
+
uses: coverallsapp/github-action@v1.1.2
|
56
|
+
with:
|
57
|
+
github-token: ${{ secrets.github_token }}
|
58
|
+
parallel-finished: true
|
data/.gitignore
CHANGED
data/.simplecov
ADDED
File without changes
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### v2.7.2
|
4
|
+
|
5
|
+
* Minor documentation improvements and tweaks
|
6
|
+
* Upgrade Ruby patch versions in CI config
|
7
|
+
|
8
|
+
### v2.7.1
|
9
|
+
|
10
|
+
* Dependency version upgrades
|
11
|
+
* Minor documentation improvements and tweaks
|
12
|
+
|
13
|
+
### v2.7.0
|
14
|
+
|
15
|
+
* Add `wrap_preserve` option, allowing whole words to be preserved when wrapping.
|
16
|
+
* Internal: Use GitHub actions instead of Travis
|
17
|
+
|
18
|
+
### v2.6.3
|
19
|
+
|
20
|
+
* Update dependency versions
|
21
|
+
|
3
22
|
### v2.6.2
|
4
23
|
|
5
24
|
* Ensure line break character sequences are property formatted in output, regardless
|
data/README.md
CHANGED
@@ -2,13 +2,11 @@
|
|
2
2
|
|
3
3
|
[![Gem Version][GV img]][Gem Version]
|
4
4
|
[![Documentation][DC img]][Documentation]
|
5
|
-
[![Coverage Status][CS img]][Coverage Status]
|
6
5
|
[![Build Status][BS img]][Build Status]
|
7
|
-
[![
|
6
|
+
[![Coverage Status][CS img]][Coverage Status]
|
8
7
|
[![Awesome][AR img]][Awesome Ruby]
|
9
8
|
|
10
|
-
Tabulo is a Ruby library for generating plain text tables
|
11
|
-
or “ASCII tables”). It is both highly configurable and very easy to use.
|
9
|
+
Tabulo is a Ruby library for generating plain text tables. It is both highly configurable and very easy to use.
|
12
10
|
|
13
11
|
<a name="overview"></a>
|
14
12
|
## Overview
|
@@ -63,6 +61,7 @@ end
|
|
63
61
|
* The header row can be [repeated](#repeating-headers) at arbitrary intervals
|
64
62
|
* Newlines within cell content are correctly handled
|
65
63
|
* Multibyte Unicode characters are correctly handled
|
64
|
+
* Option to [preserve whole words](#preserve-words) when wrapping content
|
66
65
|
* Apply [colours](#colours-and-styling) and other styling to table content and borders, without breaking the table
|
67
66
|
* Easily [transpose](#transposition) the table, so that rows are swapped with columns
|
68
67
|
* Choose from multiple [border configurations](#borders), including Markdown, “ASCII”, and smoothly
|
@@ -84,6 +83,7 @@ Tabulo has also been ported to Crystal (with some modifications): see [Tablo](ht
|
|
84
83
|
* [Full API](#quick-api)
|
85
84
|
* [Column labels _vs_ headers](#labels-headers)
|
86
85
|
* [Positioning columns](#column-positioning)
|
86
|
+
* [Extracting column content from a hash or array](#from-arrays-hashes)
|
87
87
|
* [Removing columns](#removing-columns)
|
88
88
|
* [Adding a title](#title)
|
89
89
|
* [Cell alignment](#cell-alignment)
|
@@ -92,6 +92,7 @@ Tabulo has also been ported to Crystal (with some modifications): see [Tablo](ht
|
|
92
92
|
* [Automating column widths](#automating-column-widths)
|
93
93
|
* [Configuring padding](#configuring-padding)
|
94
94
|
* [Overflow handling](#overflow-handling)
|
95
|
+
* [Wrapping at word boundaries](#preserve-words)
|
95
96
|
* [Manual cell wrapping](#manual-wrapping)
|
96
97
|
* [Formatting cell values](#formatting-cell-values)
|
97
98
|
* [Colours and other styling](#colours-and-styling)
|
@@ -101,7 +102,7 @@ Tabulo has also been ported to Crystal (with some modifications): see [Tablo](ht
|
|
101
102
|
* [Setting default styles](#default-styles)
|
102
103
|
* [Styling borders](#styling-borders)
|
103
104
|
* [Repeating headers](#repeating-headers)
|
104
|
-
* [Using a Table Enumerator](#
|
105
|
+
* [Using a Table Enumerator](#enumerator)
|
105
106
|
* [Accessing cell values](#accessing-cell-values)
|
106
107
|
* [Accessing the underlying enumerable](#accessing-sources)
|
107
108
|
* [Transposing rows and columns](#transposition)
|
@@ -280,6 +281,69 @@ table.add_column(:even?, before: :odd?)
|
|
280
281
|
+--------------+--------------+--------------+
|
281
282
|
```
|
282
283
|
|
284
|
+
<a name="from-arrays-hashes"></a>
|
285
|
+
#### Extracting column content from a hash or array [↑](#contents)
|
286
|
+
|
287
|
+
Sometimes the data source for the table may be a collection of hashes or arrays. For example:
|
288
|
+
|
289
|
+
```ruby
|
290
|
+
data = [
|
291
|
+
{ english: "hello", portuguese: "bom dia" },
|
292
|
+
{ english: "goodbye", portuguese: "adeus" },
|
293
|
+
]
|
294
|
+
```
|
295
|
+
|
296
|
+
or
|
297
|
+
|
298
|
+
```ruby
|
299
|
+
data = [
|
300
|
+
["hello", "bom dia"],
|
301
|
+
["goodbye", "adeus"],
|
302
|
+
]
|
303
|
+
```
|
304
|
+
|
305
|
+
To tabulate such a collection, simply use the same mechanism as described above, passing a block to
|
306
|
+
the `add_column` method to tell Tabulo how to extract the data for each column from a row. For
|
307
|
+
example, to tabulate the first example above, you could do something like this:
|
308
|
+
|
309
|
+
```ruby
|
310
|
+
table = Tabulo::Table.new(data) do |t|
|
311
|
+
t.add_column("English") { |h| h[:english] }
|
312
|
+
t.add_column("Portuguese") { |h| h[:portuguese] }
|
313
|
+
end
|
314
|
+
|
315
|
+
puts table
|
316
|
+
```
|
317
|
+
|
318
|
+
For the second example, you could do the following:
|
319
|
+
|
320
|
+
```ruby
|
321
|
+
table = Tabulo::Table.new(data) do |t|
|
322
|
+
t.add_column("English") { |a| a[0] }
|
323
|
+
t.add_column("Portuguese") { |a| a[1] }
|
324
|
+
end
|
325
|
+
|
326
|
+
puts table
|
327
|
+
```
|
328
|
+
|
329
|
+
In both cases, the output will be as follows:
|
330
|
+
|
331
|
+
```
|
332
|
+
+--------------+--------------+
|
333
|
+
| English | Portuguese |
|
334
|
+
+--------------+--------------+
|
335
|
+
| hello | bom dia |
|
336
|
+
| goodbye | adeus |
|
337
|
+
+--------------+--------------+
|
338
|
+
```
|
339
|
+
|
340
|
+
If you have previously used other terminal tabulation libraries, you may be accustomed to being _required_
|
341
|
+
to place your data into an array of hashes or arrays before you can tabulate them. Tabulo, however,
|
342
|
+
offers an API that is more general and flexible than this; your data source can be _any_
|
343
|
+
enumerable collection (not just an array), and each item in that collection can be _any_ object (not
|
344
|
+
necessarily an array or a hash). However, as shown above, it is still straightforward to tabulate an
|
345
|
+
array of hashes or arrays, if your data source happens to take that form.
|
346
|
+
|
283
347
|
<a name="removing-columns"></a>
|
284
348
|
### Removing columns [↑](#contents)
|
285
349
|
|
@@ -596,6 +660,46 @@ table = Tabulo::Table.new(
|
|
596
660
|
The character used to indicate truncation, which defaults to `~`, can be configured using the
|
597
661
|
`truncation_indicator` option passed to `Table.new`.
|
598
662
|
|
663
|
+
<a name="preserve-words"></a>
|
664
|
+
#### Wrapping at word boundaries [↑](#contents)
|
665
|
+
|
666
|
+
By passing `:word` to the `wrap_preserve` option on either table initialization (for all columns),
|
667
|
+
or when calling `add_column` (for an individual column), whole words can be preserved when wrapping:
|
668
|
+
|
669
|
+
```ruby
|
670
|
+
sentences = [
|
671
|
+
"Words are preserved.",
|
672
|
+
"Excessively long words may still be split to fit into the configured column width.",
|
673
|
+
]
|
674
|
+
table = Tabulo::Table.new(sentences, :itself, :length, column_width: 10, wrap_preserve: :word)
|
675
|
+
```
|
676
|
+
|
677
|
+
```
|
678
|
+
> puts table
|
679
|
+
+------------+------------+
|
680
|
+
| itself | length |
|
681
|
+
+------------+------------+
|
682
|
+
| Words are | 20 |
|
683
|
+
| preserved. | |
|
684
|
+
| Excessivel | 82 |
|
685
|
+
| y long | |
|
686
|
+
| words may | |
|
687
|
+
| still be | |
|
688
|
+
| split to | |
|
689
|
+
| fit into | |
|
690
|
+
| the | |
|
691
|
+
| configured | |
|
692
|
+
| column | |
|
693
|
+
| width. | |
|
694
|
+
+------------+------------+
|
695
|
+
```
|
696
|
+
|
697
|
+
When wrapping cell content, Tabulo will never insert hyphens itself, although it will recognize existing
|
698
|
+
hyphens, m-dashes and n-dashes as word boundaries.
|
699
|
+
|
700
|
+
The `wrap_preserve` option defaults to the value `:rune`, meaning by default it will _not_ respect word
|
701
|
+
boundaries when wrapping (although it will always preserve whole multibyte Unicode characters).
|
702
|
+
|
599
703
|
<a name="manual-wrapping"></a>
|
600
704
|
#### Manual cell wrapping [↑](#contents)
|
601
705
|
|
@@ -688,7 +792,7 @@ the table.
|
|
688
792
|
The `formatter` callback also has an alternative, 2-parameter version. If `formatter` is passed
|
689
793
|
a 2-parameter callable, the second parameter will be given a `CellData` instance,
|
690
794
|
containing additional information about the cell that may be useful in determining how to format
|
691
|
-
it—see the [documentation](https://www.rubydoc.info/gems/tabulo/2.
|
795
|
+
it—see the [documentation](https://www.rubydoc.info/gems/tabulo/2.7.2/Tabulo/CellData.html)
|
692
796
|
for details.
|
693
797
|
|
694
798
|
<a name="colours-and-styling"></a>
|
@@ -734,7 +838,7 @@ number is even). The second parameter represents the formatted string value of t
|
|
734
838
|
content after any processing by the [formatter](#formatting-cell-values). The third and fourth
|
735
839
|
parameters are optional, and contain further information about the cell and its contents that may be useful in
|
736
840
|
determining how to style it. See the
|
737
|
-
[documentation](https://www.rubydoc.info/gems/tabulo/2.
|
841
|
+
[documentation](https://www.rubydoc.info/gems/tabulo/2.7.2/Tabulo/Table#add_column-instance_method) for details.
|
738
842
|
|
739
843
|
If the content of a cell is wrapped over multiple lines, then the `styler` will be called once
|
740
844
|
per line, so that each line of the cell will have the escape sequence applied to it separately
|
@@ -754,7 +858,7 @@ table.add_column(:even?, header_styler: -> (s) { "\033[32m#{s}\033[0m" })
|
|
754
858
|
```
|
755
859
|
|
756
860
|
The `header_styler` option accepts a 1-, 2- or 3-parameter callable. See the
|
757
|
-
[documentation](https://www.rubydoc.info/gems/tabulo/2.
|
861
|
+
[documentation](https://www.rubydoc.info/gems/tabulo/2.7.2/Tabulo/Table#add_column-instance_method)
|
758
862
|
for details.
|
759
863
|
|
760
864
|
<a name="styling-title"></a>
|
@@ -768,7 +872,7 @@ table = Tabulo::Table.new(1..5, :itself, :even?, :odd?, title: "Numbers", title_
|
|
768
872
|
```
|
769
873
|
|
770
874
|
The `title_styler` option accepts a 1- or 2-parameter callable. See the
|
771
|
-
[documentation](https://www.rubydoc.info/gems/tabulo/2.
|
875
|
+
[documentation](https://www.rubydoc.info/gems/tabulo/2.7.2/Tabulo/Table#initialize-instance_method)
|
772
876
|
for details.
|
773
877
|
|
774
878
|
<a name="styling-borders"></a>
|
@@ -834,6 +938,12 @@ table = Tabulo::Table.new(1..10, :itself, :even?, header_frequency: 5)
|
|
834
938
|
|
835
939
|
Note that if the table has a [title](#title), it will not be repeated; only column headers are repeated.
|
836
940
|
|
941
|
+
One can achieve even finer-grained control over printing of headers within the table body by stepping
|
942
|
+
through the table a row at a time (using `.each` or other methods of `Enumerable`) and calling the
|
943
|
+
the [`formatted_header`](https://www.rubydoc.info/gems/tabulo/Tabulo/Table#formatted_header-instance_method)
|
944
|
+
method in combination with [`horizontal_rule`](https://www.rubydoc.info/gems/tabulo/Tabulo%2FTable:horizontal_rule)
|
945
|
+
to produce headers at arbitrary points in the output.
|
946
|
+
|
837
947
|
<a name="enumerator"></a>
|
838
948
|
### Using a Table Enumerator [↑](#contents)
|
839
949
|
|
@@ -963,7 +1073,7 @@ a new table in which the rows and columns are swapped:
|
|
963
1073
|
By default, a header row is added to the new table, showing the string value of the element
|
964
1074
|
represented in that column. This can be configured, however, along with other aspects of
|
965
1075
|
`transpose`’s behaviour. For details, see the
|
966
|
-
[documentation](https://www.rubydoc.info/gems/tabulo/2.
|
1076
|
+
[documentation](https://www.rubydoc.info/gems/tabulo/2.7.2/Tabulo/Table#transpose-instance_method).
|
967
1077
|
|
968
1078
|
<a name="borders"></a>
|
969
1079
|
### Configuring borders [↑](#contents)
|
@@ -1181,6 +1291,11 @@ If you want a line before every row, pass `1` to `row_divider_frequency`. For ex
|
|
1181
1291
|
+--------------+--------------+--------------+
|
1182
1292
|
```
|
1183
1293
|
|
1294
|
+
In addition to these options, it is also possible to print horizontal dividers at any chosen
|
1295
|
+
point in the table output, by stepping through the table one row at a time
|
1296
|
+
and calling the [`horizontal_rule`](https://www.rubydoc.info/gems/tabulo/Tabulo%2FTable:horizontal_rule)
|
1297
|
+
method as required.
|
1298
|
+
|
1184
1299
|
<a name="freezing-a-table"></a>
|
1185
1300
|
### Using a table as a snapshot rather than as a dynamic view [↑](#contents)
|
1186
1301
|
|
@@ -1354,15 +1469,13 @@ The gem is available as open source under the terms of the [MIT
|
|
1354
1469
|
License](http://opensource.org/licenses/MIT).
|
1355
1470
|
|
1356
1471
|
[Gem Version]: https://rubygems.org/gems/tabulo
|
1357
|
-
[Documentation]: http://www.rubydoc.info/gems/tabulo
|
1358
|
-
[Build Status]: https://
|
1359
|
-
[Coverage Status]: https://coveralls.io/
|
1360
|
-
[Code Climate]: https://codeclimate.com/github/matt-harvey/tabulo
|
1472
|
+
[Documentation]: http://www.rubydoc.info/gems/tabulo
|
1473
|
+
[Build Status]: https://github.com/matt-harvey/tabulo/actions/workflows/tests.yml
|
1474
|
+
[Coverage Status]: https://coveralls.io/github/matt-harvey/tabulo
|
1361
1475
|
[Awesome Ruby]: https://github.com/markets/awesome-ruby#cli-utilities
|
1362
1476
|
|
1363
1477
|
[GV img]: https://img.shields.io/gem/v/tabulo.svg
|
1364
|
-
[DC img]: https://img.shields.io/badge/documentation-v2.
|
1365
|
-
[BS img]: https://
|
1478
|
+
[DC img]: https://img.shields.io/badge/documentation-v2.7.2-blue.svg
|
1479
|
+
[BS img]: https://github.com/matt-harvey/tabulo/actions/workflows/tests.yml/badge.svg
|
1366
1480
|
[CS img]: https://img.shields.io/coveralls/matt-harvey/tabulo.svg
|
1367
|
-
[CC img]: https://codeclimate.com/github/matt-harvey/tabulo/badges/gpa.svg
|
1368
1481
|
[AR img]: https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.7.2
|
data/lib/tabulo/cell.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require "unicode/display_width"
|
2
4
|
|
3
5
|
module Tabulo
|
@@ -19,6 +21,7 @@ module Tabulo
|
|
19
21
|
styler:,
|
20
22
|
truncation_indicator:,
|
21
23
|
value:,
|
24
|
+
wrap_preserve:,
|
22
25
|
width:)
|
23
26
|
|
24
27
|
@alignment = alignment
|
@@ -30,6 +33,7 @@ module Tabulo
|
|
30
33
|
@styler = styler
|
31
34
|
@truncation_indicator = truncation_indicator
|
32
35
|
@value = value
|
36
|
+
@wrap_preserve = wrap_preserve
|
33
37
|
@width = width
|
34
38
|
end
|
35
39
|
|
@@ -100,30 +104,86 @@ module Tabulo
|
|
100
104
|
end
|
101
105
|
|
102
106
|
def calculate_subcells
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
subsubcell_width
|
112
|
-
|
113
|
-
|
107
|
+
case @wrap_preserve
|
108
|
+
when :rune
|
109
|
+
line_index = 0
|
110
|
+
formatted_content.split(Util::NEWLINE, -1).flat_map do |substr|
|
111
|
+
subsubcells, subsubcell, subsubcell_width = [], String.new(""), 0
|
112
|
+
|
113
|
+
substr.scan(/\X/).each do |rune|
|
114
|
+
rune_width = Unicode::DisplayWidth.of(rune)
|
115
|
+
if subsubcell_width + rune_width > @width
|
116
|
+
subsubcells << style_and_align_cell_content(subsubcell, line_index)
|
117
|
+
subsubcell_width = 0
|
118
|
+
subsubcell.clear
|
119
|
+
line_index += 1
|
120
|
+
end
|
121
|
+
|
122
|
+
subsubcell << rune
|
123
|
+
subsubcell_width += rune_width
|
114
124
|
end
|
115
125
|
|
116
|
-
|
117
|
-
|
126
|
+
subsubcells << style_and_align_cell_content(subsubcell, line_index)
|
127
|
+
line_index += 1
|
128
|
+
subsubcells
|
118
129
|
end
|
130
|
+
when :word
|
131
|
+
line_index = 0
|
132
|
+
formatted_content.split(Util::NEWLINE, -1).flat_map do |substr|
|
133
|
+
subsubcells, subsubcell, subsubcell_width = [], String.new(""), 0
|
134
|
+
|
135
|
+
substr.split(/(?<= |\-|\—|\–)\b/).each do |word|
|
136
|
+
# Each word looks like "this " or like "this-".
|
137
|
+
word_width = Unicode::DisplayWidth.of(word)
|
138
|
+
combined_width = subsubcell_width + word_width
|
139
|
+
if combined_width - 1 == @width && word[-1] == " "
|
140
|
+
# do nothing, as we're on the final word of the line and
|
141
|
+
# the space at the end will be chopped off.
|
142
|
+
elsif combined_width > @width
|
143
|
+
content = style_and_align_cell_content(subsubcell, line_index)
|
144
|
+
if content.strip.length != 0
|
145
|
+
subsubcells << content
|
146
|
+
subsubcell_width = 0
|
147
|
+
subsubcell.clear
|
148
|
+
line_index += 1
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
if word_width >= @width
|
153
|
+
word.scan(/\X/).each do |rune|
|
154
|
+
rune_width = Unicode::DisplayWidth.of(rune)
|
155
|
+
if subsubcell_width + rune_width > @width
|
156
|
+
if rune != " "
|
157
|
+
content = style_and_align_cell_content(subsubcell, line_index)
|
158
|
+
subsubcells << content
|
159
|
+
subsubcell_width = 0
|
160
|
+
subsubcell.clear
|
161
|
+
line_index += 1
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
subsubcell << rune
|
166
|
+
subsubcell_width += rune_width
|
167
|
+
end
|
168
|
+
else
|
169
|
+
subsubcell << word
|
170
|
+
subsubcell_width += word_width
|
171
|
+
end
|
172
|
+
end
|
119
173
|
|
120
|
-
|
121
|
-
|
122
|
-
|
174
|
+
content = style_and_align_cell_content(subsubcell, line_index)
|
175
|
+
subsubcells << content
|
176
|
+
line_index += 1
|
177
|
+
subsubcells
|
178
|
+
end
|
123
179
|
end
|
124
180
|
end
|
125
181
|
|
126
182
|
def style_and_align_cell_content(content, line_index)
|
183
|
+
if @wrap_preserve == :word
|
184
|
+
content.strip!
|
185
|
+
end
|
186
|
+
|
127
187
|
padding = Util.max(@width - Unicode::DisplayWidth.of(content), 0)
|
128
188
|
left_padding, right_padding =
|
129
189
|
case real_alignment
|
data/lib/tabulo/column.rb
CHANGED
@@ -22,6 +22,7 @@ module Tabulo
|
|
22
22
|
right_padding:,
|
23
23
|
styler:,
|
24
24
|
truncation_indicator:,
|
25
|
+
wrap_preserve:,
|
25
26
|
width:)
|
26
27
|
|
27
28
|
@align_body = align_body
|
@@ -50,6 +51,7 @@ module Tabulo
|
|
50
51
|
@padding_character = padding_character
|
51
52
|
@styler = styler || -> (_, s) { s }
|
52
53
|
@truncation_indicator = truncation_indicator
|
54
|
+
@wrap_preserve = wrap_preserve
|
53
55
|
@width = width
|
54
56
|
end
|
55
57
|
|
@@ -67,6 +69,7 @@ module Tabulo
|
|
67
69
|
styler: @header_styler,
|
68
70
|
truncation_indicator: @truncation_indicator,
|
69
71
|
value: @header,
|
72
|
+
wrap_preserve: @wrap_preserve,
|
70
73
|
width: @width,
|
71
74
|
)
|
72
75
|
end
|
@@ -85,6 +88,7 @@ module Tabulo
|
|
85
88
|
styler: @styler,
|
86
89
|
truncation_indicator: @truncation_indicator,
|
87
90
|
value: body_cell_value(source, row_index: row_index, column_index: column_index),
|
91
|
+
wrap_preserve: @wrap_preserve,
|
88
92
|
width: @width,
|
89
93
|
)
|
90
94
|
end
|
data/lib/tabulo/table.rb
CHANGED
@@ -124,6 +124,16 @@ module Tabulo
|
|
124
124
|
# cell's content has been truncated. If omitted or passed <tt>nil</tt>,
|
125
125
|
# defaults to {DEFAULT_TRUNCATION_INDICATOR}. If passed something other than <tt>nil</tt> or
|
126
126
|
# a single-character String, raises {InvalidTruncationIndicatorError}.
|
127
|
+
# @param [Symbol] wrap_preserve Specifies what unit of text the wrapping mechanism will try to
|
128
|
+
# preserve intact when wrapping column content when the column width is reached.
|
129
|
+
# * If passed `:rune` (the default), then it will wrap at the "character" level (approximately
|
130
|
+
# speaking, the Unicode grapheme cluster level). This means the maximum number of what
|
131
|
+
# readers usually think of as "characters" will be fit on each line, within the column's allocated
|
132
|
+
# width, before contininuing to a new line, even if it means splitting a word in the middle.
|
133
|
+
# * If passed `:word`, then it will wrap in such a way as to avoid splitting words, where
|
134
|
+
# "words" are defined as units of text separated by spaces or dashes (hyphens, m-dashes and
|
135
|
+
# n-dashes). Whitespace will be used to pad lines as required. Already-hyphenated may will be split
|
136
|
+
# at the hyphen, however hyphens will not be inserted in non-hyphenated words.
|
127
137
|
# @param [nil, Integer] wrap_body_cells_to Controls wrapping behaviour for table cells (excluding
|
128
138
|
# headers), if their content is longer than the column's fixed width. If passed <tt>nil</tt>, content will
|
129
139
|
# be wrapped for as many rows as required to accommodate it. If passed an Integer N (> 0), content will be
|
@@ -141,7 +151,7 @@ module Tabulo
|
|
141
151
|
def initialize(sources, *columns, align_body: :auto, align_header: :center, align_title: :center,
|
142
152
|
border: nil, border_styler: nil, column_padding: nil, column_width: nil, formatter: :to_s.to_proc,
|
143
153
|
header_frequency: :start, header_styler: nil, row_divider_frequency: nil, styler: nil,
|
144
|
-
title: nil, title_styler: nil, truncation_indicator: nil, wrap_body_cells_to: nil,
|
154
|
+
title: nil, title_styler: nil, truncation_indicator: nil, wrap_preserve: :rune, wrap_body_cells_to: nil,
|
145
155
|
wrap_header_cells_to: nil)
|
146
156
|
|
147
157
|
@sources = sources
|
@@ -167,6 +177,7 @@ module Tabulo
|
|
167
177
|
@title_styler = title_styler
|
168
178
|
@truncation_indicator = validate_character(truncation_indicator,
|
169
179
|
DEFAULT_TRUNCATION_INDICATOR, InvalidTruncationIndicatorError, "truncation indicator")
|
180
|
+
@wrap_preserve = wrap_preserve
|
170
181
|
@wrap_body_cells_to = wrap_body_cells_to
|
171
182
|
@wrap_header_cells_to = wrap_header_cells_to
|
172
183
|
|
@@ -291,6 +302,11 @@ module Tabulo
|
|
291
302
|
# @param [Integer] width Specifies the width of the column, excluding padding. If
|
292
303
|
# nil, then the column will take the width provided by the `column_width` param
|
293
304
|
# with which the Table was initialized.
|
305
|
+
# @param [Symbol] wrap_preserve Specifies how to wrap column content when the column width is reached.
|
306
|
+
# * If passed `nil`, or not provided, then the value passed to the `wrap_preserve` param of
|
307
|
+
# {#initialize} will be used.
|
308
|
+
# * If passed `rune` or word, then the option passed to {#initialize} will be overridden for
|
309
|
+
# this column. See the documentation under {#initialize} for the behaviour of each option.
|
294
310
|
# @param [#to_proc] extractor A block or other callable that will be passed each of the {Table}
|
295
311
|
# sources to determine the value in each cell of this column.
|
296
312
|
# * If this is not provided, then the column label will be treated as a method to be called on
|
@@ -305,7 +321,7 @@ module Tabulo
|
|
305
321
|
# Table. (This is case-sensitive, but is insensitive to whether a String or Symbol is passed
|
306
322
|
# to the label parameter.)
|
307
323
|
def add_column(label, align_body: nil, align_header: nil, before: nil, formatter: nil,
|
308
|
-
header: nil, header_styler: nil, padding: nil, styler: nil, width: nil, &extractor)
|
324
|
+
header: nil, header_styler: nil, padding: nil, styler: nil, width: nil, wrap_preserve: nil, &extractor)
|
309
325
|
|
310
326
|
column_label = normalize_column_label(label)
|
311
327
|
|
@@ -333,6 +349,7 @@ module Tabulo
|
|
333
349
|
right_padding: right_padding,
|
334
350
|
styler: styler || @styler,
|
335
351
|
truncation_indicator: @truncation_indicator,
|
352
|
+
wrap_preserve: wrap_preserve || @wrap_preserve,
|
336
353
|
width: width || @column_width,
|
337
354
|
)
|
338
355
|
|
@@ -403,7 +420,7 @@ module Tabulo
|
|
403
420
|
end
|
404
421
|
|
405
422
|
# @return [String] a graphical representation of the Table column headers formatted with fixed
|
406
|
-
# width plain text.
|
423
|
+
# width plain text, excluding any horizontal borders above or below.
|
407
424
|
def formatted_header
|
408
425
|
cells = get_columns.map(&:header_cell)
|
409
426
|
format_row(cells, @wrap_header_cells_to)
|
@@ -651,7 +668,8 @@ module Tabulo
|
|
651
668
|
styler: styler,
|
652
669
|
truncation_indicator: @truncation_indicator,
|
653
670
|
value: @title,
|
654
|
-
width: title_cell_width
|
671
|
+
width: title_cell_width,
|
672
|
+
wrap_preserve: @wrap_preserve,
|
655
673
|
)
|
656
674
|
cells = [title_cell]
|
657
675
|
max_cell_height = cells.map(&:height).max
|
data/lib/tabulo/version.rb
CHANGED
data/tabulo.gemspec
CHANGED
@@ -29,13 +29,13 @@ Gem::Specification.new do |spec|
|
|
29
29
|
}
|
30
30
|
|
31
31
|
spec.add_runtime_dependency "tty-screen", "0.8.1"
|
32
|
-
spec.add_runtime_dependency "unicode-display_width", "1.
|
32
|
+
spec.add_runtime_dependency "unicode-display_width", "2.1.0"
|
33
33
|
|
34
34
|
spec.add_development_dependency "bundler"
|
35
35
|
spec.add_development_dependency "rake", "~> 12.3.3"
|
36
36
|
spec.add_development_dependency "rspec", "~> 3.9"
|
37
37
|
spec.add_development_dependency "simplecov"
|
38
|
-
spec.add_development_dependency "
|
38
|
+
spec.add_development_dependency "simplecov-lcov"
|
39
39
|
spec.add_development_dependency "yard"
|
40
40
|
spec.add_development_dependency "redcarpet"
|
41
41
|
spec.add_development_dependency "github-markup"
|
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.
|
4
|
+
version: 2.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Harvey
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tty-screen
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.
|
33
|
+
version: 2.1.0
|
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.
|
40
|
+
version: 2.1.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: simplecov-lcov
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -172,10 +172,11 @@ extensions: []
|
|
172
172
|
extra_rdoc_files: []
|
173
173
|
files:
|
174
174
|
- ".ackrc"
|
175
|
+
- ".github/workflows/tests.yml"
|
175
176
|
- ".gitignore"
|
176
177
|
- ".rdoc_options"
|
177
178
|
- ".rspec"
|
178
|
-
- ".
|
179
|
+
- ".simplecov"
|
179
180
|
- ".yardopts"
|
180
181
|
- CHANGELOG.md
|
181
182
|
- Gemfile
|
@@ -220,7 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
220
221
|
- !ruby/object:Gem::Version
|
221
222
|
version: '0'
|
222
223
|
requirements: []
|
223
|
-
rubygems_version: 3.
|
224
|
+
rubygems_version: 3.2.3
|
224
225
|
signing_key:
|
225
226
|
specification_version: 4
|
226
227
|
summary: Terminal table generator
|