tty-table 0.9.0 → 0.10.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -3
  3. data/CHANGELOG.md +16 -0
  4. data/Gemfile +4 -4
  5. data/README.md +3 -3
  6. data/appveyor.yml +2 -0
  7. data/benchmarks/speed.rb +3 -5
  8. data/examples/alignment.rb +3 -3
  9. data/examples/basic.rb +2 -2
  10. data/examples/orientation.rb +13 -0
  11. data/examples/padding.rb +15 -0
  12. data/examples/resize.rb +15 -0
  13. data/lib/tty/table.rb +2 -1
  14. data/lib/tty/table/border.rb +4 -12
  15. data/lib/tty/table/column_constraint.rb +15 -7
  16. data/lib/tty/table/columns.rb +42 -68
  17. data/lib/tty/table/field.rb +3 -13
  18. data/lib/tty/table/indentation.rb +9 -20
  19. data/lib/tty/table/operation/alignment.rb +2 -2
  20. data/lib/tty/table/operation/padding.rb +3 -3
  21. data/lib/tty/table/operation/truncation.rb +3 -3
  22. data/lib/tty/table/operation/wrapped.rb +3 -3
  23. data/lib/tty/table/operations.rb +3 -14
  24. data/lib/tty/table/renderer.rb +28 -24
  25. data/lib/tty/table/renderer/ascii.rb +1 -1
  26. data/lib/tty/table/renderer/basic.rb +42 -41
  27. data/lib/tty/table/renderer/unicode.rb +1 -1
  28. data/lib/tty/table/version.rb +1 -3
  29. data/spec/unit/border/ascii/rendering_spec.rb +1 -1
  30. data/spec/unit/border/null/rendering_spec.rb +1 -1
  31. data/spec/unit/border/unicode/rendering_spec.rb +1 -1
  32. data/spec/unit/column_constraint/enforce_spec.rb +2 -2
  33. data/spec/unit/columns/extract_widths_spec.rb +7 -12
  34. data/spec/unit/columns/total_width_spec.rb +3 -4
  35. data/spec/unit/indentation/indent_spec.rb +2 -6
  36. data/spec/unit/operations/new_spec.rb +3 -5
  37. data/spec/unit/renderer/ascii/padding_spec.rb +29 -0
  38. data/tty-table.gemspec +3 -4
  39. metadata +12 -24
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'equatable'
4
4
  require 'pastel'
5
- require 'unicode/display_width'
5
+ require 'strings'
6
6
 
7
7
  module TTY
8
8
  class Table
@@ -104,7 +104,7 @@ module TTY
104
104
  #
105
105
  # @api public
106
106
  def width
107
- @width || display_width(@content)
107
+ @width || Strings::Align.display_width(@content)
108
108
  end
109
109
 
110
110
  # Return number of lines this value spans.
@@ -127,7 +127,7 @@ module TTY
127
127
  # @api public
128
128
  def length
129
129
  (lines.map do |line|
130
- display_width(self.class.color.strip(line))
130
+ Strings::Align.display_width(line)
131
131
  end << 0).max
132
132
  end
133
133
 
@@ -152,16 +152,6 @@ module TTY
152
152
  def to_s
153
153
  content
154
154
  end
155
-
156
- # @api public
157
- def self.color
158
- @color ||= Pastel.new(enabled: true)
159
- end
160
-
161
- # @api public
162
- def display_width(string)
163
- Unicode::DisplayWidth.of(string)
164
- end
165
155
  end # Field
166
156
  end # Table
167
157
  end # TTY
@@ -1,36 +1,24 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module TTY
4
5
  class Table
5
- # A class responsible for indenting table representation
6
- class Indentation
7
- # The amount of indentation
8
- #
9
- # @api public
10
- attr_accessor :indentation
11
-
12
- # Initialize an Indentation
13
- #
14
- # @api public
15
- def initialize(indentation)
16
- @indentation = indentation
17
- end
18
-
6
+ # A module responsible for indenting table representation
7
+ module Indentation
19
8
  # Return a table part with indentation inserted
20
9
  #
21
10
  # @param [#map, #to_s] part
22
11
  # the rendered table part
23
12
  #
24
13
  # @api public
25
- def indent(part)
14
+ def indent(part, indentation)
26
15
  if part.respond_to?(:to_a)
27
- part.map { |line| insert_indentation(line) }
16
+ part.map { |line| insert_indentation(line, indentation) }
28
17
  else
29
- insert_indentation(part)
18
+ insert_indentation(part, indentation)
30
19
  end
31
20
  end
32
-
33
- private
21
+ module_function :indent
34
22
 
35
23
  # Insert indentation into a table renderd line
36
24
  #
@@ -38,10 +26,11 @@ module TTY
38
26
  # the rendered table line
39
27
  #
40
28
  # @api public
41
- def insert_indentation(line)
29
+ def insert_indentation(line, indentation)
42
30
  line = line.is_a?(Array) ? line[0] : line
43
31
  line.insert(0, ' ' * indentation) if line
44
32
  end
33
+ module_function :insert_indentation
45
34
  end # Indentation
46
35
  end # Table
47
36
  end # TTY
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'verse'
3
+ require 'strings'
4
4
 
5
5
  module TTY
6
6
  class Table
@@ -53,7 +53,7 @@ module TTY
53
53
  def align_field(field, col)
54
54
  column_width = widths[col]
55
55
  direction = field.alignment || alignments[col] || DEFAULT
56
- Verse.align(field.content, column_width, direction)
56
+ Strings.align(field.content, column_width, direction: direction)
57
57
  end
58
58
  end # Alignment
59
59
  end # Operation
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- require 'verse'
3
+ require 'strings'
4
4
 
5
5
  module TTY
6
6
  class Table
@@ -11,7 +11,7 @@ module TTY
11
11
  class Padding
12
12
  # Initialize a Padding operation
13
13
  #
14
- # @param [Verse::Padder] padding
14
+ # @param [Strings::Padder] padding
15
15
  #
16
16
  # @param [Array[Integer]] widths
17
17
  #
@@ -35,7 +35,7 @@ module TTY
35
35
  #
36
36
  # @api public
37
37
  def call(field, *)
38
- Verse.pad(field.content, padding)
38
+ Strings.pad(field.content, padding)
39
39
  end
40
40
 
41
41
  protected
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'verse'
3
+ require 'strings'
4
4
 
5
5
  module TTY
6
6
  class Table
@@ -34,8 +34,8 @@ module TTY
34
34
  #
35
35
  # @api public
36
36
  def call(field, row, col)
37
- width = widths[col] || field.width
38
- Verse.truncate(field.content, width)
37
+ column_width = widths[col] || field.width
38
+ Strings.truncate(field.content, column_width)
39
39
  end
40
40
  end # Truncation
41
41
  end # Operation
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'verse'
3
+ require 'strings'
4
4
 
5
5
  module TTY
6
6
  class Table
@@ -33,8 +33,8 @@ module TTY
33
33
  #
34
34
  # @api public
35
35
  def call(field, row, col)
36
- width = widths[col] || field.width
37
- Verse.wrap(field.content, width)
36
+ column_width = widths[col] || field.width
37
+ Strings.wrap(field.content, column_width)
38
38
  end
39
39
  end # Wrapped
40
40
  end # Operation
@@ -8,14 +8,8 @@ module TTY
8
8
  class Operations
9
9
  # Initialize Operations
10
10
  #
11
- # @param [TTY::Table] table
12
- # the table to perform operations on
13
- #
14
- # @return [Object]
15
- #
16
11
  # @api public
17
- def initialize(table)
18
- @table = table
12
+ def initialize
19
13
  @operations = Hash.new { |hash, key| hash[key] = [] }
20
14
  end
21
15
 
@@ -55,14 +49,14 @@ module TTY
55
49
  # @return [TTY::Table]
56
50
  #
57
51
  # @api public
58
- def run_operations(*args)
52
+ def apply_to(table, *args)
59
53
  operation_types = args
60
54
  table.data.each_with_index do |row, row_i|
61
55
  row.fields.each_with_index do |field, col_i|
62
56
  field.reset!
63
57
  operation_types.each do |type|
64
58
  operations[type].each do |operation|
65
- field.content = operation.call(field, row_i, col_i)
59
+ field.content = operation.(field, row_i, col_i)
66
60
  end
67
61
  end
68
62
  end
@@ -71,11 +65,6 @@ module TTY
71
65
 
72
66
  protected
73
67
 
74
- # The table
75
- #
76
- # @api private
77
- attr_reader :table
78
-
79
68
  # Available operations
80
69
  #
81
70
  # @return [Hash]
@@ -7,12 +7,12 @@ require_relative 'renderer/unicode'
7
7
 
8
8
  module TTY
9
9
  class Table
10
- # A class responsible for rendering tabular data
10
+ # A module responsible for selecting tabule data renderer
11
11
  #
12
12
  # Used internally by {Table} to render table content out.
13
13
  #
14
14
  # @api private
15
- class Renderer
15
+ module Renderer
16
16
  RENDERER_MAPPER = {
17
17
  ascii: TTY::Table::Renderer::ASCII,
18
18
  basic: TTY::Table::Renderer::Basic,
@@ -30,9 +30,10 @@ module TTY
30
30
  # @return [TTY::Table::Renderer]
31
31
  #
32
32
  # @api private
33
- def self.select(type)
33
+ def select(type)
34
34
  RENDERER_MAPPER[type || :basic]
35
35
  end
36
+ module_function :select
36
37
 
37
38
  # Raises an error if provided border class is of wrong type or has invalid
38
39
  # implementation
@@ -44,7 +45,7 @@ module TTY
44
45
  # raised when border class does not implement core methods
45
46
  #
46
47
  # @api public
47
- def self.assert_border_class(border_class)
48
+ def assert_border_class(border_class)
48
49
  return unless border_class
49
50
  unless border_class <= TTY::Table::Border
50
51
  fail TypeError,
@@ -55,6 +56,27 @@ module TTY
55
56
  "#{border_class} should implement def_border"
56
57
  end
57
58
  end
59
+ module_function :assert_border_class
60
+
61
+ # Render a given table and return the string representation.
62
+ #
63
+ # @param [TTY::Table] table
64
+ # the table to be rendered
65
+ #
66
+ # @param [Hash] options
67
+ # the options to render the table with
68
+ # @option options [String] :renderer
69
+ # used to format table output
70
+ #
71
+ # @return [String]
72
+ #
73
+ # @api public
74
+ def render(table, options = {}, &block)
75
+ renderer = select(options[:renderer]).new(table, options)
76
+ yield renderer if block_given?
77
+ renderer.render
78
+ end
79
+ module_function :render
58
80
 
59
81
  # Add custom border for the renderer
60
82
  #
@@ -71,30 +93,12 @@ module TTY
71
93
  # raise if the klass does not implement def_border
72
94
  #
73
95
  # @api public
74
- def self.render_with(border_class, table, options = {}, &block)
96
+ def render_with(border_class, table, options = {}, &block)
75
97
  assert_border_class(border_class)
76
98
  options[:border_class] = border_class if border_class
77
99
  render(table, options, &block)
78
100
  end
79
-
80
- # Render a given table and return the string representation.
81
- #
82
- # @param [TTY::Table] table
83
- # the table to be rendered
84
- #
85
- # @param [Hash] options
86
- # the options to render the table with
87
- # @option options [String] :renderer
88
- # used to format table output
89
- #
90
- # @return [String]
91
- #
92
- # @api public
93
- def self.render(table, options = {}, &block)
94
- renderer = select(options[:renderer]).new(table, options)
95
- yield renderer if block_given?
96
- renderer.render
97
- end
101
+ module_function :render_with
98
102
  end # Renderer
99
103
  end # Table
100
104
  end # TTY
@@ -5,7 +5,7 @@ require_relative '../renderer/basic'
5
5
 
6
6
  module TTY
7
7
  class Table
8
- class Renderer
8
+ module Renderer
9
9
  class ASCII < Basic
10
10
  # Create ASCII renderer
11
11
  #
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'tty-screen'
4
- require 'verse'
4
+ require 'strings'
5
5
 
6
6
  require_relative '../alignment_set'
7
7
  require_relative '../border_dsl'
@@ -22,7 +22,7 @@ require_relative '../validatable'
22
22
 
23
23
  module TTY
24
24
  class Table
25
- class Renderer
25
+ module Renderer
26
26
  # Renders table without any border styles.
27
27
  #
28
28
  # @api private
@@ -70,7 +70,7 @@ module TTY
70
70
  # @api public
71
71
  attr_reader :indent
72
72
 
73
- # The table totabl width
73
+ # The table total width
74
74
  #
75
75
  # @return [Integer]
76
76
  #
@@ -122,7 +122,7 @@ module TTY
122
122
  @border_class = options.fetch(:border_class) { Border::Null }
123
123
  @indent = options.fetch(:indent) { 0 }
124
124
  @resize = options.fetch(:resize) { false }
125
- @padding = Verse::Padder.parse(options[:padding])
125
+ @padding = Strings::Padder.parse(options[:padding])
126
126
  end
127
127
 
128
128
  # Parses supplied column widths, if not present
@@ -162,7 +162,7 @@ module TTY
162
162
  #
163
163
  # @api public
164
164
  def indent=(value)
165
- @indentation.indentation = value
165
+ @indent = value
166
166
  end
167
167
 
168
168
  # Sets the output padding,
@@ -172,7 +172,7 @@ module TTY
172
172
  #
173
173
  # @api public
174
174
  def padding=(value)
175
- @padding = Verse::Padder.parse(value)
175
+ @padding = Strings::Padder.parse(value)
176
176
  end
177
177
 
178
178
  # Renders table as string with border
@@ -188,32 +188,48 @@ module TTY
188
188
  def render
189
189
  return if table.empty?
190
190
 
191
- @operations = TTY::Table::Operations.new(table)
192
- @operations.add(:escape, Operation::Escape.new)
193
- @operations.run_operations(:escape) unless multiline
191
+ operations = TTY::Table::Operations.new
192
+ operations.add(:escape, Operation::Escape.new)
193
+ operations.apply_to(table, :escape) unless multiline
194
+
194
195
  column_constraint = ColumnConstraint.new(table, self)
195
196
  @column_widths = column_constraint.enforce
196
- add_operations(@column_widths)
197
+ widths_without_padding = @column_widths.map do |_width|
198
+ _width - padding.left - padding.right
199
+ end
200
+ create_operations(widths_without_padding).each do |op|
201
+ operations.add(*op)
202
+ end
203
+ operations.apply_to(table, *select_operations)
204
+
205
+ render_data.compact.join("\n")
206
+ end
207
+
208
+ # Select applicable operations for this table
209
+ #
210
+ # @api private
211
+ def select_operations
197
212
  ops = []
198
213
  ops << :escape unless multiline
199
214
  ops << :alignment
200
215
  ops << (multiline ? :wrapping : :truncation)
201
216
  ops << :padding
202
217
  ops << :filter
203
- @operations.run_operations(*ops)
204
-
205
- render_data.compact.join("\n")
206
218
  end
207
219
 
208
- # Initialize and add operations
220
+ # Initialize operations
221
+ #
222
+ # @return [Array[String, Operation]]
209
223
  #
210
224
  # @api private
211
- def add_operations(widths)
212
- @operations.add(:alignment, Operation::Alignment.new(alignments, widths))
213
- @operations.add(:filter, Operation::Filter.new(filter))
214
- @operations.add(:truncation, Operation::Truncation.new(widths))
215
- @operations.add(:wrapping, Operation::Wrapped.new(widths))
216
- @operations.add(:padding, Operation::Padding.new(padding))
225
+ def create_operations(widths)
226
+ [
227
+ [:alignment, Operation::Alignment.new(alignments, widths)],
228
+ [:filter, Operation::Filter.new(filter)],
229
+ [:truncation, Operation::Truncation.new(widths)],
230
+ [:wrapping, Operation::Wrapped.new(widths)],
231
+ [:padding, Operation::Padding.new(padding)]
232
+ ]
217
233
  end
218
234
 
219
235
  protected
@@ -225,33 +241,17 @@ module TTY
225
241
  # @api public
226
242
  attr_reader :table
227
243
 
228
- # Initializes indentation
229
- #
230
- # @return [TTY::Table::Indentation]
231
- #
232
- # @api private
233
- def indentation
234
- @indentation ||= TTY::Table::Indentation.new(indent)
235
- end
236
-
237
- # Delegate indentation insertion
238
- #
239
- # @api public
240
- def insert_indent(line)
241
- indentation.indent(line)
242
- end
243
-
244
244
  # Render table data
245
245
  #
246
246
  # @api private
247
247
  def render_data
248
248
  first_row = table.first
249
- data_border = border_class.new(column_widths, padding, border)
249
+ data_border = border_class.new(column_widths, border)
250
250
  header = render_header(first_row, data_border)
251
251
  rows_with_border = render_rows(data_border)
252
252
  bottom_line = data_border.bottom_line
253
253
 
254
- insert_indent(bottom_line) if bottom_line
254
+ Indentation.indent(bottom_line, @indent) if bottom_line
255
255
 
256
256
  [header, rows_with_border, bottom_line].compact
257
257
  end
@@ -271,7 +271,7 @@ module TTY
271
271
  top_line = data_border.top_line
272
272
  if row.is_a?(TTY::Table::Header)
273
273
  header = [top_line, data_border.row_line(row), data_border.separator]
274
- insert_indent(header.compact)
274
+ Indentation.indent(header.compact, @indent)
275
275
  else
276
276
  top_line
277
277
  end
@@ -309,10 +309,11 @@ module TTY
309
309
  row_line = data_border.row_line(row)
310
310
 
311
311
  if (border.separator == TTY::Table::Border::EACH_ROW) && is_last_row
312
- insert_indent([row_line, separator])
312
+ line = [row_line, separator]
313
313
  else
314
- insert_indent(row_line)
314
+ line = row_line
315
315
  end
316
+ Indentation.indent(line, @indent)
316
317
  end
317
318
  end # Basic
318
319
  end # Renderer