tty-table 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/README.md +458 -142
- data/lib/tty-table.rb +6 -6
- data/lib/tty/table.rb +34 -34
- data/lib/tty/table/alignment_set.rb +73 -0
- data/lib/tty/table/border.rb +54 -36
- data/lib/tty/table/border/null.rb +4 -4
- data/lib/tty/table/{columns.rb → column_constraint.rb} +30 -32
- data/lib/tty/table/column_set.rb +18 -17
- data/lib/tty/table/field.rb +50 -25
- data/lib/tty/table/header.rb +6 -2
- data/lib/tty/table/indentation.rb +7 -12
- data/lib/tty/table/operation/alignment.rb +59 -0
- data/lib/tty/table/operation/escape.rb +1 -1
- data/lib/tty/table/operation/filter.rb +1 -1
- data/lib/tty/table/operation/padding.rb +12 -61
- data/lib/tty/table/operation/truncation.rb +2 -2
- data/lib/tty/table/operation/wrapped.rb +2 -5
- data/lib/tty/table/operations.rb +35 -17
- data/lib/tty/table/orientation/vertical.rb +4 -4
- data/lib/tty/table/renderer.rb +1 -7
- data/lib/tty/table/renderer/basic.rb +69 -63
- data/lib/tty/table/version.rb +1 -1
- data/spec/spec_helper.rb +3 -4
- data/spec/unit/access_spec.rb +8 -8
- data/spec/unit/{operation/alignment_set → alignment_set}/each_spec.rb +1 -1
- data/spec/unit/{operation/alignment_set → alignment_set}/new_spec.rb +4 -4
- data/spec/unit/{operation/alignment_set → alignment_set}/to_ary_spec.rb +1 -1
- data/spec/unit/alignment_spec.rb +71 -0
- data/spec/unit/border/ascii/rendering_spec.rb +12 -12
- data/spec/unit/border/new_spec.rb +2 -2
- data/spec/unit/border/null/rendering_spec.rb +2 -2
- data/spec/unit/border/unicode/rendering_spec.rb +10 -10
- data/spec/unit/{columns → column_constraint}/enforce_spec.rb +15 -12
- data/spec/unit/{columns → column_constraint}/widths_spec.rb +6 -6
- data/spec/unit/column_set/extract_widths_spec.rb +39 -6
- data/spec/unit/data_spec.rb +4 -6
- data/spec/unit/each_spec.rb +8 -23
- data/spec/unit/each_with_index_spec.rb +27 -33
- data/spec/unit/field/length_spec.rb +23 -9
- data/spec/unit/field/width_spec.rb +1 -1
- data/spec/unit/filter_spec.rb +7 -8
- data/spec/unit/header/new_spec.rb +6 -15
- data/spec/unit/indentation/indent_spec.rb +21 -0
- data/spec/unit/new_spec.rb +73 -0
- data/spec/unit/operation/{alignment_set → alignment}/call_spec.rb +1 -1
- data/spec/unit/operation/escape/call_spec.rb +2 -3
- data/spec/unit/operation/filter/call_spec.rb +2 -3
- data/spec/unit/operation/truncation/call_spec.rb +6 -8
- data/spec/unit/operation/wrapped/call_spec.rb +15 -8
- data/spec/unit/operations/new_spec.rb +1 -1
- data/spec/unit/orientation_spec.rb +6 -6
- data/spec/unit/padding_spec.rb +29 -32
- data/spec/unit/properties_spec.rb +4 -4
- data/spec/unit/render_repeat_spec.rb +42 -0
- data/spec/unit/render_spec.rb +1 -1
- data/spec/unit/render_with_spec.rb +3 -3
- data/spec/unit/renderer/ascii/coloring_spec.rb +70 -0
- data/spec/unit/renderer/ascii/multiline_spec.rb +101 -0
- data/spec/unit/renderer/ascii/padding_spec.rb +37 -10
- data/spec/unit/renderer/ascii/render_spec.rb +4 -4
- data/spec/unit/renderer/ascii/resizing_spec.rb +22 -22
- data/spec/unit/renderer/ascii/separator_spec.rb +1 -1
- data/spec/unit/renderer/basic/alignment_spec.rb +20 -20
- data/spec/unit/renderer/basic/coloring_spec.rb +43 -28
- data/spec/unit/renderer/basic/filter_spec.rb +3 -3
- data/spec/unit/renderer/basic/multiline_spec.rb +74 -0
- data/spec/unit/renderer/basic/options_spec.rb +9 -9
- data/spec/unit/renderer/basic/padding_spec.rb +26 -2
- data/spec/unit/renderer/basic/render_spec.rb +4 -4
- data/spec/unit/renderer/basic/resizing_spec.rb +18 -18
- data/spec/unit/renderer/basic/separator_spec.rb +1 -1
- data/spec/unit/renderer/basic/truncation_spec.rb +6 -6
- data/spec/unit/renderer/basic/wrapping_spec.rb +3 -3
- data/spec/unit/renderer/border_spec.rb +4 -4
- data/spec/unit/renderer/unicode/coloring_spec.rb +70 -0
- data/spec/unit/renderer/unicode/indentation_spec.rb +1 -1
- data/spec/unit/renderer/unicode/padding_spec.rb +26 -26
- data/spec/unit/renderer/unicode/render_spec.rb +4 -4
- data/spec/unit/renderer/unicode/separator_spec.rb +1 -1
- data/spec/unit/to_s_spec.rb +4 -11
- data/spec/unit/utf_spec.rb +33 -0
- data/tty-table.gemspec +2 -1
- metadata +52 -32
- data/lib/tty/table/operation/alignment_set.rb +0 -103
- data/lib/tty/table/padder.rb +0 -180
- data/lib/tty/table/renderer/color.rb +0 -12
- data/spec/unit/indentation/insert_indent_spec.rb +0 -27
- data/spec/unit/initialize_spec.rb +0 -88
- data/spec/unit/padder/parse_spec.rb +0 -45
- data/spec/unit/padder/to_s_spec.rb +0 -14
- data/spec/unit/renderer/basic/multiline_content_spec.rb +0 -135
- data/spec/unit/renderer/style_spec.rb +0 -72
@@ -7,24 +7,21 @@ module TTY
|
|
7
7
|
# Used internally by {Renderer::Basic} to enforce correct column widths.
|
8
8
|
#
|
9
9
|
# @api private
|
10
|
-
class
|
11
|
-
|
12
|
-
attr_reader :table
|
13
|
-
|
14
|
-
attr_reader :renderer
|
15
|
-
|
10
|
+
class ColumnConstraint
|
16
11
|
MIN_WIDTH = 1
|
17
12
|
|
18
13
|
BORDER_WIDTH = 1
|
19
14
|
|
20
15
|
# Initialize a Columns
|
21
16
|
#
|
17
|
+
# @param [TTY::Table] table
|
18
|
+
#
|
22
19
|
# @param [TTY::Table::Renderer] renderer
|
23
20
|
#
|
24
21
|
# @api public
|
25
|
-
def initialize(renderer)
|
22
|
+
def initialize(table, renderer)
|
23
|
+
@table = table
|
26
24
|
@renderer = renderer
|
27
|
-
@table = renderer.table
|
28
25
|
end
|
29
26
|
|
30
27
|
# Estimate outside border size
|
@@ -42,7 +39,17 @@ module TTY
|
|
42
39
|
#
|
43
40
|
# @api public
|
44
41
|
def border_size
|
45
|
-
BORDER_WIDTH * (table.
|
42
|
+
BORDER_WIDTH * (table.columns_size - 1) + outside_border_size
|
43
|
+
end
|
44
|
+
|
45
|
+
# Measure total padding size for a table
|
46
|
+
#
|
47
|
+
# @return [Integer]
|
48
|
+
#
|
49
|
+
# @api public
|
50
|
+
def padding_size
|
51
|
+
padding = renderer.padding
|
52
|
+
(padding.left + padding.right) * (table.columns_size - 1)
|
46
53
|
end
|
47
54
|
|
48
55
|
# Estimate minimum table width to be able to display content
|
@@ -51,7 +58,7 @@ module TTY
|
|
51
58
|
#
|
52
59
|
# @api public
|
53
60
|
def minimum_width
|
54
|
-
table.
|
61
|
+
table.columns_size * MIN_WIDTH + border_size
|
55
62
|
end
|
56
63
|
|
57
64
|
# Return column's natural unconstrained widths
|
@@ -60,7 +67,7 @@ module TTY
|
|
60
67
|
#
|
61
68
|
# @api public
|
62
69
|
def natural_width
|
63
|
-
renderer.column_widths.inject(0, &:+) + border_size
|
70
|
+
renderer.column_widths.inject(0, &:+) + border_size + padding_size
|
64
71
|
end
|
65
72
|
|
66
73
|
# Return the constrained column widths.
|
@@ -72,33 +79,22 @@ module TTY
|
|
72
79
|
def enforce
|
73
80
|
assert_minimum_width
|
74
81
|
|
75
|
-
unless renderer.padding.empty?
|
76
|
-
renderer.column_widths = adjust_padding
|
77
|
-
end
|
78
|
-
|
79
82
|
if natural_width <= renderer.width
|
80
|
-
renderer.
|
83
|
+
renderer.resize ? expand : renderer.column_widths
|
81
84
|
else
|
82
85
|
if renderer.resize
|
83
|
-
|
86
|
+
shrink
|
84
87
|
else
|
85
88
|
rotate
|
86
|
-
renderer.column_widths = ColumnSet.widths_from(table)
|
87
89
|
end
|
88
90
|
end
|
89
91
|
end
|
90
92
|
|
91
|
-
|
92
|
-
#
|
93
|
-
# @api private
|
94
|
-
def adjust_padding
|
95
|
-
padding = renderer.padding
|
96
|
-
column_size = table.column_size
|
93
|
+
private
|
97
94
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
95
|
+
attr_reader :table
|
96
|
+
|
97
|
+
attr_reader :renderer
|
102
98
|
|
103
99
|
# Rotate table to vertical orientation and print information to stdout
|
104
100
|
#
|
@@ -109,13 +105,14 @@ module TTY
|
|
109
105
|
'orientation.'
|
110
106
|
table.orientation = :vertical
|
111
107
|
table.rotate
|
108
|
+
ColumnSet.widths_from(table)
|
112
109
|
end
|
113
110
|
|
114
111
|
# Expand column widths to match the requested width
|
115
112
|
#
|
116
113
|
# @api private
|
117
114
|
def expand
|
118
|
-
column_size = table.
|
115
|
+
column_size = table.columns_size
|
119
116
|
ratio = ((renderer.width - natural_width) / column_size.to_f).floor
|
120
117
|
|
121
118
|
widths = (0...column_size).reduce([]) do |lengths, col|
|
@@ -128,7 +125,7 @@ module TTY
|
|
128
125
|
#
|
129
126
|
# @api private
|
130
127
|
def shrink
|
131
|
-
column_size = table.
|
128
|
+
column_size = table.columns_size
|
132
129
|
ratio = ((natural_width - renderer.width) / column_size.to_f).ceil
|
133
130
|
|
134
131
|
widths = (0...column_size).reduce([]) do |lengths, col|
|
@@ -155,7 +152,8 @@ module TTY
|
|
155
152
|
#
|
156
153
|
# @api private
|
157
154
|
def distribute_extra_width(widths)
|
158
|
-
column_size = table.
|
155
|
+
column_size = table.columns_size
|
156
|
+
# TODO - add padding size to fully check extra width
|
159
157
|
extra_width = renderer.width - (widths.reduce(:+) + border_size)
|
160
158
|
per_field_width = extra_width / column_size
|
161
159
|
remaining_width = extra_width % column_size
|
@@ -165,6 +163,6 @@ module TTY
|
|
165
163
|
width + per_field_width + extra[index]
|
166
164
|
end
|
167
165
|
end
|
168
|
-
end #
|
166
|
+
end # ColumnConstraint
|
169
167
|
end # Table
|
170
168
|
end # TTY
|
data/lib/tty/table/column_set.rb
CHANGED
@@ -10,13 +10,13 @@ module TTY
|
|
10
10
|
class ColumnSet
|
11
11
|
include Equatable
|
12
12
|
|
13
|
-
attr_reader :table
|
14
|
-
|
15
13
|
# Initialize a ColumnSet
|
16
14
|
#
|
15
|
+
# @param [Array[Array[Object]]] data
|
16
|
+
#
|
17
17
|
# @api public
|
18
18
|
def initialize(table)
|
19
|
-
@
|
19
|
+
@data = table.data
|
20
20
|
end
|
21
21
|
|
22
22
|
# Calculate total table width
|
@@ -34,10 +34,8 @@ module TTY
|
|
34
34
|
#
|
35
35
|
# @api private
|
36
36
|
def extract_widths
|
37
|
-
data = table.data
|
38
37
|
colcount = data.max { |row_a, row_b| row_a.size <=> row_b.size }.size
|
39
|
-
|
40
|
-
self.class.find_maximas(colcount, data)
|
38
|
+
find_maximas(colcount)
|
41
39
|
end
|
42
40
|
|
43
41
|
# Assert data integrity for column widths
|
@@ -72,10 +70,10 @@ module TTY
|
|
72
70
|
def self.widths_from(table, column_widths = nil)
|
73
71
|
case column_widths
|
74
72
|
when Array
|
75
|
-
assert_widths(column_widths, table.
|
73
|
+
assert_widths(column_widths, table.columns_size)
|
76
74
|
Array(column_widths).map(&:to_i)
|
77
75
|
when Numeric
|
78
|
-
Array.new(table.
|
76
|
+
Array.new(table.columns_size, column_widths)
|
79
77
|
when NilClass
|
80
78
|
new(table).extract_widths
|
81
79
|
else
|
@@ -85,20 +83,22 @@ module TTY
|
|
85
83
|
|
86
84
|
private
|
87
85
|
|
86
|
+
attr_reader :data
|
87
|
+
|
88
88
|
# Find maximum widths for each row and header if present.
|
89
89
|
#
|
90
90
|
# @param [Integer] colcount
|
91
91
|
# number of columns
|
92
|
-
#
|
93
|
-
#
|
92
|
+
#
|
93
|
+
# @return [Array[Integer]]
|
94
94
|
#
|
95
95
|
# @api private
|
96
|
-
def
|
96
|
+
def find_maximas(colcount)
|
97
97
|
maximas = []
|
98
98
|
start = 0
|
99
99
|
|
100
100
|
start.upto(colcount - 1) do |col_index|
|
101
|
-
maximas << find_maximum(
|
101
|
+
maximas << find_maximum(col_index)
|
102
102
|
end
|
103
103
|
maximas
|
104
104
|
end
|
@@ -106,15 +106,16 @@ module TTY
|
|
106
106
|
# Find a maximum column width. The calculation takes into account
|
107
107
|
# wether the content is escaped or not.
|
108
108
|
#
|
109
|
-
# @param [Array] data
|
110
|
-
# the table data
|
111
|
-
#
|
112
109
|
# @param [Integer] index
|
113
110
|
# the column index
|
114
111
|
#
|
112
|
+
# @return [Integer]
|
113
|
+
#
|
115
114
|
# @api private
|
116
|
-
def
|
117
|
-
data.map
|
115
|
+
def find_maximum(index)
|
116
|
+
data.map do |row|
|
117
|
+
(field = row.call(index)) ? field.length : 0
|
118
|
+
end.max
|
118
119
|
end
|
119
120
|
end # ColumnSet
|
120
121
|
end # Table
|
data/lib/tty/table/field.rb
CHANGED
@@ -4,7 +4,8 @@ module TTY
|
|
4
4
|
class Table
|
5
5
|
# A class that represents a unique element in a table.
|
6
6
|
#
|
7
|
-
# Used internally by {Table::Row} to
|
7
|
+
# Used internally by {Table::Header} and {Table::Row} to
|
8
|
+
# define internal structure.
|
8
9
|
#
|
9
10
|
# @api private
|
10
11
|
class Field
|
@@ -15,28 +16,40 @@ module TTY
|
|
15
16
|
# @api public
|
16
17
|
attr_reader :value
|
17
18
|
|
19
|
+
# The formatted value inside the field used for display
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
attr_reader :content
|
23
|
+
|
18
24
|
# The name for the value
|
19
25
|
#
|
20
26
|
# @api public
|
21
27
|
attr_reader :name
|
22
28
|
|
23
|
-
#
|
29
|
+
# The actual value
|
30
|
+
#
|
31
|
+
# @api public
|
24
32
|
attr_writer :value
|
25
33
|
|
26
|
-
# The
|
34
|
+
# The formatted string
|
27
35
|
#
|
28
36
|
# @api public
|
29
|
-
|
37
|
+
attr_writer :content
|
30
38
|
|
31
39
|
# Number of columns this field spans. Defaults to 1.
|
32
40
|
#
|
41
|
+
# @api public
|
33
42
|
attr_reader :colspan
|
34
43
|
|
35
44
|
# Number of rows this field spans. Defaults to 1.
|
36
45
|
#
|
46
|
+
# @api public
|
37
47
|
attr_reader :rowspan
|
38
48
|
|
39
|
-
|
49
|
+
# The field alignment
|
50
|
+
#
|
51
|
+
# @api public
|
52
|
+
attr_reader :alignment
|
40
53
|
|
41
54
|
# Initialize a Field
|
42
55
|
#
|
@@ -49,15 +62,16 @@ module TTY
|
|
49
62
|
# field.value # => a1
|
50
63
|
#
|
51
64
|
# @example
|
52
|
-
# field = TTY::Table::Field.new value: 'a1',
|
53
|
-
# field.value
|
54
|
-
# field.
|
65
|
+
# field = TTY::Table::Field.new value: 'a1', alignment: :center
|
66
|
+
# field.value # => a1
|
67
|
+
# field.alignment # => :center
|
55
68
|
#
|
56
69
|
# @api private
|
57
70
|
def initialize(value)
|
58
71
|
options = extract_options(value)
|
59
|
-
@
|
60
|
-
@
|
72
|
+
@content = @value.to_s
|
73
|
+
@width = options[:width]
|
74
|
+
@alignment = options.fetch(:alignment) { nil }
|
61
75
|
@colspan = options.fetch(:colspan) { 1 }
|
62
76
|
@rowspan = options.fetch(:rowspan) { 1 }
|
63
77
|
end
|
@@ -76,15 +90,18 @@ module TTY
|
|
76
90
|
options
|
77
91
|
end
|
78
92
|
|
79
|
-
#
|
93
|
+
# Reset to original value
|
80
94
|
#
|
81
95
|
# @api public
|
82
|
-
def
|
83
|
-
@
|
96
|
+
def reset!
|
97
|
+
@content = @value.to_s
|
84
98
|
end
|
85
99
|
|
86
|
-
|
87
|
-
|
100
|
+
# The content width
|
101
|
+
#
|
102
|
+
# @api public
|
103
|
+
def width
|
104
|
+
@width || UnicodeUtils.display_width(@content)
|
88
105
|
end
|
89
106
|
|
90
107
|
# Return number of lines this value spans.
|
@@ -95,8 +112,8 @@ module TTY
|
|
95
112
|
#
|
96
113
|
# @api public
|
97
114
|
def lines
|
98
|
-
escaped =
|
99
|
-
escaped.empty? ?
|
115
|
+
escaped = content.scan(/(\\n|\\t|\\r)/)
|
116
|
+
escaped.empty? ? content.split(/\n/, -1) : [content]
|
100
117
|
end
|
101
118
|
|
102
119
|
# If the string contains unescaped new lines then the longest token
|
@@ -106,7 +123,9 @@ module TTY
|
|
106
123
|
#
|
107
124
|
# @api public
|
108
125
|
def length
|
109
|
-
(lines.
|
126
|
+
(lines.map do |line|
|
127
|
+
display_width(self.class.color.strip(line))
|
128
|
+
end << 0).max
|
110
129
|
end
|
111
130
|
|
112
131
|
# Extract the number of lines this value spans
|
@@ -119,20 +138,26 @@ module TTY
|
|
119
138
|
end
|
120
139
|
|
121
140
|
def chars
|
122
|
-
|
141
|
+
content.chars
|
123
142
|
end
|
124
143
|
|
125
|
-
#
|
144
|
+
# Return field content
|
145
|
+
#
|
146
|
+
# @return [String]
|
126
147
|
#
|
127
148
|
# @api public
|
128
|
-
def
|
149
|
+
def to_s
|
150
|
+
content
|
129
151
|
end
|
130
152
|
|
131
|
-
# Return field value
|
132
|
-
#
|
133
153
|
# @api public
|
134
|
-
def
|
135
|
-
|
154
|
+
def self.color
|
155
|
+
@color ||= Pastel.new(enabled: true)
|
156
|
+
end
|
157
|
+
|
158
|
+
# @api public
|
159
|
+
def display_width(string)
|
160
|
+
UnicodeUtils.display_width(string)
|
136
161
|
end
|
137
162
|
end # Field
|
138
163
|
end # Table
|
data/lib/tty/table/header.rb
CHANGED
@@ -39,8 +39,8 @@ module TTY
|
|
39
39
|
# Iterate over each element in the vector
|
40
40
|
#
|
41
41
|
# @example
|
42
|
-
#
|
43
|
-
#
|
42
|
+
# header = TTY::Table::Header.new [1,2,3]
|
43
|
+
# header.each { |element| ... }
|
44
44
|
#
|
45
45
|
# @return [self]
|
46
46
|
#
|
@@ -158,6 +158,10 @@ module TTY
|
|
158
158
|
def to_hash
|
159
159
|
to_a.hash
|
160
160
|
end
|
161
|
+
|
162
|
+
def inspect
|
163
|
+
"#<#{self.class.name} fields=#{to_a}>"
|
164
|
+
end
|
161
165
|
end # Header
|
162
166
|
end # Table
|
163
167
|
end # TTY
|
@@ -4,21 +4,16 @@ module TTY
|
|
4
4
|
class Table
|
5
5
|
# A class responsible for indenting table representation
|
6
6
|
class Indentation
|
7
|
-
|
8
|
-
attr_reader :renderer
|
9
|
-
|
10
|
-
# Initialize an Indentation
|
7
|
+
# The amount of indentation
|
11
8
|
#
|
12
9
|
# @api public
|
13
|
-
|
14
|
-
@renderer = renderer
|
15
|
-
end
|
10
|
+
attr_accessor :indentation
|
16
11
|
|
17
|
-
#
|
12
|
+
# Initialize an Indentation
|
18
13
|
#
|
19
14
|
# @api public
|
20
|
-
def indentation
|
21
|
-
|
15
|
+
def initialize(indentation)
|
16
|
+
@indentation = indentation
|
22
17
|
end
|
23
18
|
|
24
19
|
# Return a table part with indentation inserted
|
@@ -27,7 +22,7 @@ module TTY
|
|
27
22
|
# the rendered table part
|
28
23
|
#
|
29
24
|
# @api public
|
30
|
-
def
|
25
|
+
def indent(part)
|
31
26
|
if part.respond_to?(:to_a)
|
32
27
|
part.map { |line| insert_indentation(line) }
|
33
28
|
else
|
@@ -45,7 +40,7 @@ module TTY
|
|
45
40
|
# @api public
|
46
41
|
def insert_indentation(line)
|
47
42
|
line = line.is_a?(Array) ? line[0] : line
|
48
|
-
line.insert(0, indentation) if line
|
43
|
+
line.insert(0, ' ' * indentation) if line
|
49
44
|
end
|
50
45
|
end # Indentation
|
51
46
|
end # Table
|