tty-table 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -3
- data/CHANGELOG.md +16 -0
- data/Gemfile +4 -4
- data/README.md +3 -3
- data/appveyor.yml +2 -0
- data/benchmarks/speed.rb +3 -5
- data/examples/alignment.rb +3 -3
- data/examples/basic.rb +2 -2
- data/examples/orientation.rb +13 -0
- data/examples/padding.rb +15 -0
- data/examples/resize.rb +15 -0
- data/lib/tty/table.rb +2 -1
- data/lib/tty/table/border.rb +4 -12
- data/lib/tty/table/column_constraint.rb +15 -7
- data/lib/tty/table/columns.rb +42 -68
- data/lib/tty/table/field.rb +3 -13
- data/lib/tty/table/indentation.rb +9 -20
- data/lib/tty/table/operation/alignment.rb +2 -2
- data/lib/tty/table/operation/padding.rb +3 -3
- data/lib/tty/table/operation/truncation.rb +3 -3
- data/lib/tty/table/operation/wrapped.rb +3 -3
- data/lib/tty/table/operations.rb +3 -14
- data/lib/tty/table/renderer.rb +28 -24
- data/lib/tty/table/renderer/ascii.rb +1 -1
- data/lib/tty/table/renderer/basic.rb +42 -41
- data/lib/tty/table/renderer/unicode.rb +1 -1
- data/lib/tty/table/version.rb +1 -3
- data/spec/unit/border/ascii/rendering_spec.rb +1 -1
- data/spec/unit/border/null/rendering_spec.rb +1 -1
- data/spec/unit/border/unicode/rendering_spec.rb +1 -1
- data/spec/unit/column_constraint/enforce_spec.rb +2 -2
- data/spec/unit/columns/extract_widths_spec.rb +7 -12
- data/spec/unit/columns/total_width_spec.rb +3 -4
- data/spec/unit/indentation/indent_spec.rb +2 -6
- data/spec/unit/operations/new_spec.rb +3 -5
- data/spec/unit/renderer/ascii/padding_spec.rb +29 -0
- data/tty-table.gemspec +3 -4
- metadata +12 -24
data/lib/tty/table/field.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'equatable'
|
4
4
|
require 'pastel'
|
5
|
-
require '
|
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(
|
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
|
6
|
-
|
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 '
|
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
|
-
|
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 '
|
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 [
|
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
|
-
|
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 '
|
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
|
-
|
38
|
-
|
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 '
|
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
|
-
|
37
|
-
|
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
|
data/lib/tty/table/operations.rb
CHANGED
@@ -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
|
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
|
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.
|
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]
|
data/lib/tty/table/renderer.rb
CHANGED
@@ -7,12 +7,12 @@ require_relative 'renderer/unicode'
|
|
7
7
|
|
8
8
|
module TTY
|
9
9
|
class Table
|
10
|
-
# A
|
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
|
-
|
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
|
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
|
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
|
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
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'tty-screen'
|
4
|
-
require '
|
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
|
-
|
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
|
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 =
|
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
|
-
@
|
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 =
|
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
|
-
|
192
|
-
|
193
|
-
|
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
|
-
|
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
|
220
|
+
# Initialize operations
|
221
|
+
#
|
222
|
+
# @return [Array[String, Operation]]
|
209
223
|
#
|
210
224
|
# @api private
|
211
|
-
def
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
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,
|
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
|
-
|
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
|
-
|
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
|
-
|
312
|
+
line = [row_line, separator]
|
313
313
|
else
|
314
|
-
|
314
|
+
line = row_line
|
315
315
|
end
|
316
|
+
Indentation.indent(line, @indent)
|
316
317
|
end
|
317
318
|
end # Basic
|
318
319
|
end # Renderer
|