tabulo 2.6.2 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dde64a0fb26dfd5b5624fc18d4c442989cf81433371267d2ce52dbcac4137433
4
- data.tar.gz: b0bc0295c6bb8fa5bbaf855ede1dc44fea722acfd23f2b74e1db68b36396e5df
3
+ metadata.gz: f2419c20288ae285e4fcbfefd5627f6dac370ab3940969093216283407df6ee4
4
+ data.tar.gz: '08ee67482f630a3f185319fcc7fec4844b3a64d70042f3afc9abb993e4a65260'
5
5
  SHA512:
6
- metadata.gz: 9dddd9de39377071967c86f75e65a175352f33966d52d39e5dd725012a7a5531415870b0e95a7ce546e9bec0af4c15a0fefd2a50eb3585a64a93ed99cae3bd37
7
- data.tar.gz: b936c064abfab53617eb82f7977dd2f7b1957115990ea301d211de8f23661667ada82a92fd2dbdc9c34d0d741ce00b1a3dd03a655fe73b855f610cfb663fe298
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
@@ -10,3 +10,4 @@
10
10
  **/.*.swp
11
11
  coverage
12
12
  gh-md-toc
13
+ .ruby-version
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
- [![Code Climate][CC img]][Code Climate]
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 (also known as “terminal 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, &ldquo;ASCII&rdquo;, 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](#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 [&#x2191;](#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 [&#x2191;](#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 [&#x2191;](#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 [&#x2191;](#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&mdash;see the [documentation](https://www.rubydoc.info/gems/tabulo/2.6.2/Tabulo/CellData.html)
795
+ it&mdash;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.6.2/Tabulo/Table#add_column-instance_method) for details.
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.6.2/Tabulo/Table#add_column-instance_method)
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.6.2/Tabulo/Table#initialize-instance_method)
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 [&#x2191;](#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`&#8217;s behaviour. For details, see the
966
- [documentation](https://www.rubydoc.info/gems/tabulo/2.6.2/Tabulo/Table#transpose-instance_method).
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 [&#x2191;](#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 [&#x2191;](#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/2.6.2
1358
- [Build Status]: https://travis-ci.org/matt-harvey/tabulo
1359
- [Coverage Status]: https://coveralls.io/r/matt-harvey/tabulo
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.6.2-blue.svg
1365
- [BS img]: https://img.shields.io/travis/matt-harvey/tabulo.svg
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.6.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
- line_index = 0
104
- formatted_content.split(Util::NEWLINE, -1).flat_map do |substr|
105
- subsubcells, subsubcell, subsubcell_width = [], String.new(""), 0
106
-
107
- substr.scan(/\X/).each do |grapheme_cluster|
108
- grapheme_cluster_width = Unicode::DisplayWidth.of(grapheme_cluster)
109
- if subsubcell_width + grapheme_cluster_width > @width
110
- subsubcells << style_and_align_cell_content(subsubcell, line_index)
111
- subsubcell_width = 0
112
- subsubcell.clear
113
- line_index += 1
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
- subsubcell << grapheme_cluster
117
- subsubcell_width += grapheme_cluster_width
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
- subsubcells << style_and_align_cell_content(subsubcell, line_index)
121
- line_index += 1
122
- subsubcells
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
@@ -1,3 +1,3 @@
1
1
  module Tabulo
2
- VERSION = "2.6.2"
2
+ VERSION = "2.7.2"
3
3
  end
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.7.0"
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 "coveralls"
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.6.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: 2020-12-13 00:00:00.000000000 Z
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.7.0
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.7.0
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: coveralls
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
- - ".travis.yml"
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.1.2
224
+ rubygems_version: 3.2.3
224
225
  signing_key:
225
226
  specification_version: 4
226
227
  summary: Terminal table generator
data/.travis.yml DELETED
@@ -1,10 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.1.10
5
- - 2.2.10
6
- - 2.3.8
7
- - 2.4.10
8
- - 2.5.8
9
- - 2.6.6
10
- - 2.7.2