tty 0.0.9 → 0.0.10
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.
- data/.rspec +2 -1
- data/.travis.yml +3 -6
- data/README.md +232 -134
- data/lib/tty/plugins/plugin.rb +56 -0
- data/lib/tty/plugins.rb +75 -0
- data/lib/tty/shell/suggestion.rb +102 -0
- data/lib/tty/shell.rb +41 -14
- data/lib/tty/system/editor.rb +111 -0
- data/lib/tty/system/which.rb +13 -1
- data/lib/tty/system.rb +44 -28
- data/lib/tty/table/border/null.rb +0 -9
- data/lib/tty/table/border/row_line.rb +21 -0
- data/lib/tty/table/border.rb +63 -32
- data/lib/tty/table/border_dsl.rb +1 -1
- data/lib/tty/table/column_set.rb +16 -17
- data/lib/tty/table/field.rb +27 -7
- data/lib/tty/table/header.rb +18 -9
- data/lib/tty/table/operation/alignment_set.rb +20 -25
- data/lib/tty/table/operation/escape.rb +30 -0
- data/lib/tty/table/operation/filter.rb +36 -0
- data/lib/tty/table/operation/truncation.rb +22 -11
- data/lib/tty/table/operation/wrapped.rb +21 -10
- data/lib/tty/table/operations.rb +10 -8
- data/lib/tty/table/orientation/horizontal.rb +1 -1
- data/lib/tty/table/renderer/ascii.rb +3 -3
- data/lib/tty/table/renderer/basic.rb +135 -65
- data/lib/tty/table/renderer/color.rb +1 -4
- data/lib/tty/table/renderer/unicode.rb +3 -3
- data/lib/tty/table/renderer.rb +48 -61
- data/lib/tty/table/row.rb +30 -3
- data/lib/tty/table/transformation.rb +38 -0
- data/lib/tty/table/validatable.rb +7 -5
- data/lib/tty/table.rb +78 -99
- data/lib/tty/terminal/color.rb +2 -2
- data/lib/tty/terminal/echo.rb +1 -1
- data/lib/tty/terminal/pager/basic.rb +52 -0
- data/lib/tty/terminal/pager/system.rb +39 -0
- data/lib/tty/terminal/pager.rb +95 -0
- data/lib/tty/terminal.rb +30 -1
- data/lib/tty/version.rb +1 -1
- data/lib/tty.rb +41 -1
- data/spec/spec_helper.rb +20 -0
- data/spec/tty/plugins/find_spec.rb +28 -0
- data/spec/tty/plugins/load_spec.rb +20 -0
- data/spec/tty/plugins/plugin/load_spec.rb +30 -0
- data/spec/tty/plugins/plugin/new_spec.rb +18 -0
- data/spec/tty/shell/suggest_spec.rb +50 -0
- data/spec/tty/support/conversion_spec.rb +3 -3
- data/spec/tty/support/delegatable_spec.rb +1 -1
- data/spec/tty/support/equatable_spec.rb +6 -9
- data/spec/tty/system/editor/available_spec.rb +40 -0
- data/spec/tty/system/editor/build_spec.rb +40 -0
- data/spec/tty/system/editor/command_spec.rb +16 -0
- data/spec/tty/system/editor/executables_spec.rb +13 -0
- data/spec/tty/system/editor/invoke_spec.rb +38 -0
- data/spec/tty/system/editor/open_spec.rb +27 -0
- data/spec/tty/system/platform_spec.rb +4 -6
- data/spec/tty/system/which/which_spec.rb +48 -0
- data/spec/tty/system/which_spec.rb +8 -34
- data/spec/tty/table/border/ascii/rendering_spec.rb +19 -5
- data/spec/tty/table/border/new_spec.rb +1 -1
- data/spec/tty/table/border/null/rendering_spec.rb +24 -8
- data/spec/tty/table/border/unicode/rendering_spec.rb +19 -5
- data/spec/tty/table/column_set/extract_widths_spec.rb +4 -15
- data/spec/tty/table/column_set/total_width_spec.rb +15 -0
- data/spec/tty/table/data_spec.rb +14 -0
- data/spec/tty/table/each_spec.rb +17 -4
- data/spec/tty/table/each_with_index_spec.rb +34 -6
- data/spec/tty/table/field/length_spec.rb +21 -0
- data/spec/tty/table/field/lines_spec.rb +21 -0
- data/spec/tty/table/filter_spec.rb +23 -0
- data/spec/tty/table/header/call_spec.rb +1 -1
- data/spec/tty/table/header/height_spec.rb +27 -0
- data/spec/tty/table/initialize_spec.rb +6 -6
- data/spec/tty/table/operation/alignment_set/call_spec.rb +39 -0
- data/spec/tty/table/operation/escape/call_spec.rb +16 -0
- data/spec/tty/table/operation/filter/call_spec.rb +17 -0
- data/spec/tty/table/operation/truncation/call_spec.rb +15 -10
- data/spec/tty/table/operation/truncation/truncate_spec.rb +1 -1
- data/spec/tty/table/operation/wrapped/call_spec.rb +15 -10
- data/spec/tty/table/operation/wrapped/wrap_spec.rb +1 -1
- data/spec/tty/table/operations/new_spec.rb +4 -4
- data/spec/tty/table/options_spec.rb +0 -28
- data/spec/tty/table/orientation_spec.rb +5 -6
- data/spec/tty/table/properties_spec.rb +1 -4
- data/spec/tty/table/render_spec.rb +57 -0
- data/spec/tty/table/{renders_with_spec.rb → render_with_spec.rb} +29 -10
- data/spec/tty/table/renderer/ascii/render_spec.rb +68 -0
- data/spec/tty/table/renderer/ascii/separator_spec.rb +28 -0
- data/spec/tty/table/renderer/basic/alignment_spec.rb +18 -16
- data/spec/tty/table/renderer/basic/extract_column_widths_spec.rb +17 -12
- data/spec/tty/table/renderer/basic/filter_spec.rb +53 -0
- data/spec/tty/table/renderer/basic/multiline_content_spec.rb +135 -0
- data/spec/tty/table/renderer/basic/new_spec.rb +13 -2
- data/spec/tty/table/renderer/basic/options_spec.rb +48 -0
- data/spec/tty/table/renderer/basic/render_spec.rb +19 -121
- data/spec/tty/table/renderer/basic/separator_spec.rb +14 -48
- data/spec/tty/table/renderer/basic/truncation_spec.rb +35 -0
- data/spec/tty/table/renderer/basic/wrapping_spec.rb +40 -0
- data/spec/tty/table/{border_spec.rb → renderer/border_spec.rb} +17 -20
- data/spec/tty/table/renderer/select_spec.rb +22 -0
- data/spec/tty/table/{border → renderer}/style_spec.rb +13 -14
- data/spec/tty/table/renderer/unicode/render_spec.rb +68 -0
- data/spec/tty/table/renderer/unicode/separator_spec.rb +26 -0
- data/spec/tty/table/rotate_spec.rb +2 -3
- data/spec/tty/table/row/call_spec.rb +1 -1
- data/spec/tty/table/row/each_spec.rb +31 -0
- data/spec/tty/table/row/height_spec.rb +27 -0
- data/spec/tty/table/to_s_spec.rb +3 -3
- data/spec/tty/table/transformation/extract_tuples_spec.rb +35 -0
- data/spec/tty/table/validatable/validate_options_spec.rb +1 -2
- data/spec/tty/terminal/home_spec.rb +3 -3
- data/spec/tty/terminal/page_spec.rb +13 -0
- data/spec/tty/terminal/pager/available_spec.rb +40 -0
- data/spec/tty/terminal/pager/basic/page_spec.rb +54 -0
- data/spec/tty/terminal/pager/command_spec.rb +16 -0
- data/spec/tty/terminal/pager/executables_spec.rb +13 -0
- data/spec/tty/terminal/pager/page_spec.rb +47 -0
- data/spec/tty/terminal/pager/system/page_spec.rb +29 -0
- data/spec/tty/text/distance/distance_spec.rb +12 -0
- data/tty.gemspec +7 -3
- metadata +160 -27
- data/spec/tty/table/operation/alignment_set/align_rows_spec.rb +0 -53
- data/spec/tty/table/renderer/pick_renderer_spec.rb +0 -25
- data/spec/tty/table/renderer_spec.rb +0 -49
@@ -1,12 +1,14 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
|
+
require 'tty/table/validatable'
|
4
|
+
|
3
5
|
module TTY
|
4
6
|
class Table
|
5
|
-
|
7
|
+
class Renderer
|
6
8
|
|
7
9
|
# Renders table without any border styles.
|
8
10
|
class Basic
|
9
|
-
|
11
|
+
include TTY::Table::Validatable
|
10
12
|
|
11
13
|
# Table to be rendered
|
12
14
|
#
|
@@ -14,40 +16,108 @@ module TTY
|
|
14
16
|
#
|
15
17
|
# @api public
|
16
18
|
attr_reader :table
|
19
|
+
private :table
|
17
20
|
|
18
21
|
# Table border to be rendered
|
19
22
|
#
|
20
23
|
# @return [TTY::Table::Border]
|
21
24
|
#
|
22
25
|
# @api private
|
23
|
-
|
26
|
+
attr_accessor :border_class
|
24
27
|
|
25
|
-
|
28
|
+
# The table enforced column widths
|
29
|
+
#
|
30
|
+
# @return [Array]
|
31
|
+
#
|
32
|
+
# @api public
|
33
|
+
attr_accessor :column_widths
|
26
34
|
|
27
|
-
|
35
|
+
# The table column alignments
|
36
|
+
#
|
37
|
+
# @return [Array]
|
38
|
+
#
|
39
|
+
# @api private
|
40
|
+
attr_accessor :column_aligns
|
28
41
|
|
29
|
-
#
|
42
|
+
# The table operations applied to rows
|
43
|
+
#
|
44
|
+
# @api public
|
45
|
+
attr_reader :operations
|
46
|
+
|
47
|
+
# A callable object used for formatting field content
|
48
|
+
#
|
49
|
+
# @api public
|
50
|
+
attr_accessor :filter
|
51
|
+
|
52
|
+
# The table column span behaviour. When true the column's line breaks
|
53
|
+
# cause the column to span multiple rows. By default set to false.
|
54
|
+
#
|
55
|
+
# @return [Boolean]
|
56
|
+
#
|
57
|
+
# @api public
|
58
|
+
attr_accessor :multiline
|
59
|
+
|
60
|
+
# Initialize a Renderer
|
30
61
|
#
|
31
62
|
# @param [Hash] options
|
63
|
+
# @option options [String] :column_aligns
|
64
|
+
# used to format table individual column alignment
|
65
|
+
# @option options [String] :column_widths
|
66
|
+
# used to format table individula column width
|
67
|
+
#
|
32
68
|
# :indent - Indent the first column by indent value
|
33
69
|
# :padding - Pad out the row cell by padding value
|
34
70
|
#
|
35
|
-
# @return [Table::Renderer::Basic]
|
36
|
-
|
37
|
-
|
71
|
+
# @return [TTY::Table::Renderer::Basic]
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
def initialize(table, options={})
|
75
|
+
validate_rendering_options!(options)
|
76
|
+
@table = table || (raise ArgumentRequired, "Expected TTY::Table instance, got #{table.inspect}")
|
77
|
+
@multiline = options.fetch(:multiline) { false }
|
78
|
+
@operations = TTY::Table::Operations.new(table)
|
79
|
+
unless multiline
|
80
|
+
@operations.add_operation(:escape, Operation::Escape.new)
|
81
|
+
@operations.run_operations(:escape)
|
82
|
+
end
|
83
|
+
|
84
|
+
@border = TTY::Table::BorderOptions.from(options.delete(:border))
|
85
|
+
@column_widths = Array(options.fetch(:column_widths) {
|
86
|
+
ColumnSet.new(table).extract_widths
|
87
|
+
}).map(&:to_i)
|
88
|
+
@column_aligns = Array(options.delete(:column_aligns)).map(&:to_sym)
|
89
|
+
@filter = options.fetch(:filter) { proc { |val, row, col| val } }
|
90
|
+
@width = options.fetch(:width) { TTY.terminal.width }
|
91
|
+
@border_class = options.fetch(:border_class) { Border::Null }
|
38
92
|
end
|
39
93
|
|
40
|
-
#
|
94
|
+
# Store border characters, style and separator for the table rendering
|
95
|
+
#
|
96
|
+
# @param [Hash, BorderOptions] options
|
41
97
|
#
|
42
|
-
# @
|
98
|
+
# @yield [] block representing border options
|
99
|
+
#
|
100
|
+
# @api public
|
101
|
+
def border(options=(not_set=true), &block)
|
102
|
+
@border = TTY::Table::BorderOptions.new unless @border
|
103
|
+
if block_given?
|
104
|
+
border_dsl = TTY::Table::BorderDSL.new(&block)
|
105
|
+
@border = border_dsl.options
|
106
|
+
elsif !not_set
|
107
|
+
@border = TTY::Table::BorderOptions.from(options)
|
108
|
+
end
|
109
|
+
@border
|
110
|
+
end
|
111
|
+
|
112
|
+
# Initialize and add operations
|
43
113
|
#
|
44
114
|
# @api private
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
115
|
+
def add_operations
|
116
|
+
operations.add_operation(:alignment, Operation::AlignmentSet.new(column_aligns, column_widths))
|
117
|
+
operations.add_operation(:filter, Operation::Filter.new(filter))
|
118
|
+
operations.add_operation(:truncation, Operation::Truncation.new(column_widths))
|
119
|
+
operations.add_operation(:wrapping, Operation::Wrapped.new(column_widths))
|
49
120
|
end
|
50
|
-
private :setup
|
51
121
|
|
52
122
|
# Sets the output padding,
|
53
123
|
#
|
@@ -59,74 +129,72 @@ module TTY
|
|
59
129
|
@padding = [0, value].max
|
60
130
|
end
|
61
131
|
|
62
|
-
# @api public
|
63
|
-
def self.render(table, options={})
|
64
|
-
new(options).render(table)
|
65
|
-
end
|
66
|
-
|
67
132
|
# Renders table
|
68
133
|
#
|
69
|
-
# @param [TTY::Table] table
|
70
|
-
# the table to be rendered
|
71
|
-
#
|
72
134
|
# @return [String] string representation of table
|
73
135
|
#
|
74
136
|
# @api public
|
75
|
-
def render
|
76
|
-
@table = table
|
77
|
-
@border_class = table.border_class || border_class
|
137
|
+
def render
|
78
138
|
return if table.empty?
|
79
139
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
end
|
89
|
-
body.compact.join("\n")
|
140
|
+
# TODO: throw an error if too many columns as compared to terminal width
|
141
|
+
# and then change table.orientation from vertical to horizontal
|
142
|
+
# TODO: Decide about table orientation
|
143
|
+
add_operations
|
144
|
+
ops = [:filter, :alignment]
|
145
|
+
multiline ? ops << :wrapping : ops << :truncation
|
146
|
+
operations.run_operations(*ops)
|
147
|
+
render_data.compact.join("\n")
|
90
148
|
end
|
91
149
|
|
92
150
|
private
|
93
151
|
|
94
|
-
#
|
152
|
+
# Render table data
|
153
|
+
#
|
154
|
+
# @api private
|
155
|
+
def render_data
|
156
|
+
first_row = table.first
|
157
|
+
data_border = border_class.new(column_widths, border)
|
158
|
+
header = render_header(first_row, data_border)
|
159
|
+
rows_with_border = render_rows(data_border)
|
160
|
+
|
161
|
+
[header, rows_with_border, data_border.bottom_line].compact
|
162
|
+
end
|
163
|
+
|
164
|
+
# Format the header if present
|
165
|
+
#
|
166
|
+
# @param [TTY::Table::Row, TTY::Table::Header] row
|
167
|
+
# the first row in the table
|
168
|
+
#
|
169
|
+
# @param [TTY::Table::Border] data_boder
|
170
|
+
# the border for this table
|
95
171
|
#
|
96
|
-
# @return [
|
172
|
+
# @return [String]
|
97
173
|
#
|
98
174
|
# @api private
|
99
|
-
def render_header
|
100
|
-
|
101
|
-
if
|
102
|
-
|
103
|
-
operations.run_operations(:alignment, header)
|
104
|
-
border = border_class.new(header, table.border)
|
105
|
-
[ border.top_line, border.row_line ].compact
|
175
|
+
def render_header(row, data_border)
|
176
|
+
top_line = data_border.top_line
|
177
|
+
if row.is_a?(TTY::Table::Header)
|
178
|
+
[top_line, data_border.row_line(row), data_border.separator].compact
|
106
179
|
else
|
107
|
-
|
180
|
+
top_line
|
108
181
|
end
|
109
182
|
end
|
110
183
|
|
111
184
|
# Format the rows
|
112
185
|
#
|
186
|
+
# @param [TTY::Table::Border] data_boder
|
187
|
+
# the border for this table
|
188
|
+
#
|
113
189
|
# @return [Arrays[String]]
|
114
190
|
#
|
115
191
|
# @api private
|
116
|
-
def render_rows
|
117
|
-
|
118
|
-
|
119
|
-
|
192
|
+
def render_rows(data_border)
|
193
|
+
rows = table.rows
|
194
|
+
size = rows.size
|
195
|
+
rows.each_with_index.map do |row, index|
|
196
|
+
render_row(row, data_border, size != (index += 1))
|
120
197
|
end
|
121
|
-
aligned = table.to_a
|
122
|
-
first_row_border = border_class.new(aligned.first, table.border)
|
123
|
-
aligned_border = aligned.each_with_index.map { |row, index|
|
124
|
-
render_row(row, aligned.size != (index += 1))
|
125
|
-
}
|
126
|
-
|
127
|
-
[ table.header ? first_row_border.separator : first_row_border.top_line,
|
128
|
-
aligned_border,
|
129
|
-
first_row_border.bottom_line ].compact
|
130
198
|
end
|
131
199
|
|
132
200
|
# Format a single row with border
|
@@ -134,15 +202,17 @@ module TTY
|
|
134
202
|
# @param [Array] row
|
135
203
|
# a row to decorate
|
136
204
|
#
|
205
|
+
# @param [TTY::Table::Border] data_boder
|
206
|
+
# the border for this table
|
207
|
+
#
|
137
208
|
# @param [Boolean] is_last_row
|
138
209
|
#
|
139
210
|
# @api private
|
140
|
-
def render_row(row, is_last_row)
|
141
|
-
|
142
|
-
|
143
|
-
row_line = border.row_line
|
211
|
+
def render_row(row, data_border, is_last_row)
|
212
|
+
separator = data_border.separator
|
213
|
+
row_line = data_border.row_line(row)
|
144
214
|
|
145
|
-
if (
|
215
|
+
if (border.separator == TTY::Table::Border::EACH_ROW) && is_last_row
|
146
216
|
[row_line, separator]
|
147
217
|
else
|
148
218
|
row_line
|
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
module TTY
|
4
4
|
class Table
|
5
|
-
|
5
|
+
class Renderer
|
6
6
|
class Unicode < Basic
|
7
7
|
|
8
|
-
def
|
9
|
-
super
|
8
|
+
def initialize(table, options={})
|
9
|
+
super(table, options.merge(:border_class => TTY::Table::Border::Unicode))
|
10
10
|
end
|
11
11
|
|
12
12
|
end # Unicode
|
data/lib/tty/table/renderer.rb
CHANGED
@@ -3,39 +3,13 @@
|
|
3
3
|
module TTY
|
4
4
|
class Table
|
5
5
|
|
6
|
-
#
|
7
|
-
|
8
|
-
# @return [TTY::Table::Renderer]
|
9
|
-
#
|
10
|
-
# @api public
|
11
|
-
def self.renderer
|
12
|
-
@renderer ||= if TTY.terminal.color?
|
13
|
-
TTY::Table::Renderer::Color
|
14
|
-
else
|
15
|
-
TTY::Table::Renderer::Basic
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
# @api public
|
20
|
-
def self.renderer=(klass)
|
21
|
-
@renderer = klass
|
22
|
-
end
|
23
|
-
|
24
|
-
# A mixin to allow common rendering methods
|
25
|
-
#
|
26
|
-
# @return [self]
|
27
|
-
#
|
28
|
-
# @api public
|
29
|
-
module Renderer
|
30
|
-
extend TTY::Delegatable
|
31
|
-
|
6
|
+
# A class responsible for rendering tabular data
|
7
|
+
class Renderer
|
32
8
|
autoload :ASCII, 'tty/table/renderer/ascii'
|
33
9
|
autoload :Basic, 'tty/table/renderer/basic'
|
34
10
|
autoload :Color, 'tty/table/renderer/color'
|
35
11
|
autoload :Unicode, 'tty/table/renderer/unicode'
|
36
12
|
|
37
|
-
RENDERER_DELEGATED_METHODS = [ :render, :total_width]
|
38
|
-
|
39
13
|
RENDERER_MAPPER = {
|
40
14
|
:ascii => TTY::Table::Renderer::ASCII,
|
41
15
|
:basic => TTY::Table::Renderer::Basic,
|
@@ -43,44 +17,45 @@ module TTY
|
|
43
17
|
:unicode => TTY::Table::Renderer::Unicode
|
44
18
|
}
|
45
19
|
|
46
|
-
#
|
47
|
-
#
|
48
|
-
# @api private
|
49
|
-
def initialize(options={})
|
50
|
-
super()
|
51
|
-
end
|
52
|
-
|
53
|
-
# Determine renderer class based on string name
|
20
|
+
# Select renderer class based on string name
|
54
21
|
#
|
55
22
|
# @param [Symbol] renderer
|
56
|
-
# the renderer used for displaying table out of [:basic, :
|
23
|
+
# the renderer used for displaying table out of [:basic, :ascii, :unicode, :color]
|
57
24
|
#
|
58
25
|
# @return [TTY::Table::Renderer]
|
59
26
|
#
|
60
27
|
# @api private
|
61
|
-
def
|
62
|
-
|
28
|
+
def self.select(type)
|
29
|
+
RENDERER_MAPPER[type || :basic]
|
63
30
|
end
|
64
31
|
|
65
|
-
#
|
32
|
+
# Raises an error if provided border class is of wrong type or has invalid
|
33
|
+
# implementation
|
66
34
|
#
|
67
|
-
# @
|
35
|
+
# @raise [TypeError]
|
36
|
+
# raised when providing wrong class for border
|
37
|
+
#
|
38
|
+
# @raise [NoImplementationError]
|
39
|
+
# raised when border class does not implement core methods
|
68
40
|
#
|
69
41
|
# @api public
|
70
|
-
def
|
71
|
-
|
42
|
+
def self.assert_border_class(border_class)
|
43
|
+
return unless border_class
|
44
|
+
unless border_class <= TTY::Table::Border
|
45
|
+
raise TypeError, "#{border_class} should inherit from TTY::Table::Border"
|
46
|
+
end
|
47
|
+
unless border_class.characters
|
48
|
+
raise NoImplementationError, "#{border_class} should implement def_border"
|
49
|
+
end
|
72
50
|
end
|
73
51
|
|
74
|
-
#
|
52
|
+
# Add custom border for the renderer
|
75
53
|
#
|
76
|
-
# @
|
54
|
+
# @param [TTY::Table::Border] border_class
|
77
55
|
#
|
78
|
-
# @
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
# Add custom border for the renderer
|
56
|
+
# @param [TTY::Table] table
|
57
|
+
#
|
58
|
+
# @param [Hash] options
|
84
59
|
#
|
85
60
|
# @raise [TypeError]
|
86
61
|
# raised if the klass does not inherit from Table::Border
|
@@ -89,18 +64,30 @@ module TTY
|
|
89
64
|
# raise if the klass does not implement def_border
|
90
65
|
#
|
91
66
|
# @api public
|
92
|
-
def
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
unless klass.characters
|
97
|
-
raise NoImplementationError, "#{klass} should implement def_border"
|
98
|
-
end
|
99
|
-
@border_class = klass
|
67
|
+
def self.render_with(border_class, table, options={}, &block)
|
68
|
+
assert_border_class(border_class)
|
69
|
+
options[:border_class] = border_class if border_class
|
70
|
+
render(table, options, &block)
|
100
71
|
end
|
101
72
|
|
102
|
-
|
103
|
-
|
73
|
+
# Render a given table and return the string representation.
|
74
|
+
#
|
75
|
+
# @param [TTY::Table] table
|
76
|
+
# the table to be rendered
|
77
|
+
#
|
78
|
+
# @param [Hash] options
|
79
|
+
# the options to render the table with
|
80
|
+
# @option options [String] :renderer
|
81
|
+
# used to format table output
|
82
|
+
#
|
83
|
+
# @return [String]
|
84
|
+
#
|
85
|
+
# @api public
|
86
|
+
def self.render(table, options={}, &block)
|
87
|
+
renderer = select(options[:renderer]).new(table, options)
|
88
|
+
yield renderer if block_given?
|
89
|
+
renderer.render
|
90
|
+
end
|
104
91
|
end # Renderer
|
105
92
|
|
106
93
|
end # Table
|
data/lib/tty/table/row.rb
CHANGED
@@ -35,6 +35,8 @@ module TTY
|
|
35
35
|
# @api private
|
36
36
|
attr_reader :data
|
37
37
|
|
38
|
+
attr_reader :fields
|
39
|
+
|
38
40
|
# Initialize a Row
|
39
41
|
#
|
40
42
|
# @example
|
@@ -59,11 +61,11 @@ module TTY
|
|
59
61
|
case data
|
60
62
|
when Array
|
61
63
|
@attributes = (header || (0...data.length)).to_a
|
62
|
-
fields = data.inject([]) { |arr, datum| arr << to_field(datum) }
|
64
|
+
@fields = data.inject([]) { |arr, datum| arr << to_field(datum) }
|
63
65
|
@data = Hash[@attributes.zip(fields)]
|
64
66
|
when Hash
|
65
67
|
@data = data.dup
|
66
|
-
fields = @data.values.inject([]){|arr, datum| arr << to_field(datum) }
|
68
|
+
@fields = @data.values.inject([]){|arr, datum| arr << to_field(datum) }
|
67
69
|
@attributes = (header || data.keys).to_a
|
68
70
|
@data = Hash[@attributes.zip(fields)]
|
69
71
|
end
|
@@ -95,7 +97,13 @@ module TTY
|
|
95
97
|
end.value
|
96
98
|
end
|
97
99
|
end
|
98
|
-
|
100
|
+
|
101
|
+
# Lookup attribute without evaluation
|
102
|
+
#
|
103
|
+
# @api public
|
104
|
+
def call(attribute)
|
105
|
+
data[attributes[attribute]]
|
106
|
+
end
|
99
107
|
|
100
108
|
# Set value at index
|
101
109
|
#
|
@@ -123,6 +131,15 @@ module TTY
|
|
123
131
|
end
|
124
132
|
alias :length :size
|
125
133
|
|
134
|
+
# Find maximum row height
|
135
|
+
#
|
136
|
+
# @return [Integer]
|
137
|
+
#
|
138
|
+
# @api public
|
139
|
+
def height
|
140
|
+
fields.map { |field| field.height }.max
|
141
|
+
end
|
142
|
+
|
126
143
|
# Convert the Row into Array
|
127
144
|
#
|
128
145
|
# @example
|
@@ -163,11 +180,21 @@ module TTY
|
|
163
180
|
to_a.hash
|
164
181
|
end
|
165
182
|
|
183
|
+
# Map field values
|
184
|
+
#
|
185
|
+
# @api public
|
166
186
|
def map!(&block)
|
167
187
|
data.values_at(*attributes).each do |field|
|
168
188
|
field.value = block.call(field)
|
169
189
|
end
|
170
190
|
end
|
191
|
+
|
192
|
+
# String representation of a row with its fields
|
193
|
+
#
|
194
|
+
# @api public
|
195
|
+
def inspect
|
196
|
+
"#<#{self.class.name} fields=#{to_a}>"
|
197
|
+
end
|
171
198
|
end # Row
|
172
199
|
|
173
200
|
end # Table
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
class Table
|
5
|
+
|
6
|
+
# A class for transforming table values
|
7
|
+
class Transformation
|
8
|
+
|
9
|
+
# Extract the header and row tuples from the value
|
10
|
+
#
|
11
|
+
# @param [Array] args
|
12
|
+
#
|
13
|
+
# @return [Object]
|
14
|
+
#
|
15
|
+
# @api public
|
16
|
+
def self.extract_tuples(args)
|
17
|
+
rows = args.pop
|
18
|
+
header = args.size.zero? ? nil : args.first
|
19
|
+
if rows.first.is_a?(Hash)
|
20
|
+
header, rows = group_header_and_rows(rows)
|
21
|
+
end
|
22
|
+
{ header: header, rows: rows }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Group hash keys into header and values into rows
|
26
|
+
#
|
27
|
+
# @params [Hash] value
|
28
|
+
#
|
29
|
+
# @api public
|
30
|
+
def self.group_header_and_rows(value)
|
31
|
+
header = value.map(&:keys).flatten.uniq
|
32
|
+
rows = value.inject([]) { |arr, el| arr + el.values }
|
33
|
+
[header, rows]
|
34
|
+
end
|
35
|
+
|
36
|
+
end # Transformation
|
37
|
+
end # Table
|
38
|
+
end # TTY
|
@@ -29,6 +29,13 @@ module TTY
|
|
29
29
|
def assert_string_values(rows)
|
30
30
|
end
|
31
31
|
|
32
|
+
def validate_rendering_options!(options)
|
33
|
+
if (column_widths = options[:column_widths]) &&
|
34
|
+
(!column_widths.kind_of?(Array) || column_widths.empty?)
|
35
|
+
raise InvalidArgument, ":column_widths must be a non-empty array"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
32
39
|
# Check if options are of required type
|
33
40
|
#
|
34
41
|
# @api private
|
@@ -42,11 +49,6 @@ module TTY
|
|
42
49
|
!(rows.kind_of?(Array) || rows.kind_of?(Hash))
|
43
50
|
raise InvalidArgument, ":rows must be a non-empty array or hash"
|
44
51
|
end
|
45
|
-
|
46
|
-
if (column_widths = options[:column_widths]) &&
|
47
|
-
(!column_widths.kind_of?(Array) || column_widths.empty?)
|
48
|
-
raise InvalidArgument, ":column_widths must be a non-empty array"
|
49
|
-
end
|
50
52
|
end
|
51
53
|
|
52
54
|
end # Validatable
|