tty 0.0.7 → 0.0.8
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/.travis.yml +0 -1
- data/README.md +141 -23
- data/benchmarks/table.rb +5 -0
- data/lib/tty/logger.rb +71 -0
- data/lib/tty/support/equatable.rb +6 -2
- data/lib/tty/system/which.rb +41 -0
- data/lib/tty/system.rb +8 -0
- data/lib/tty/table/border/ascii.rb +15 -16
- data/lib/tty/table/border/null.rb +9 -4
- data/lib/tty/table/border/unicode.rb +15 -16
- data/lib/tty/table/border.rb +69 -9
- data/lib/tty/table/border_dsl.rb +247 -0
- data/lib/tty/table/border_options.rb +52 -0
- data/lib/tty/table/field.rb +101 -0
- data/lib/tty/table/header.rb +115 -0
- data/lib/tty/table/operation/alignment_set.rb +14 -10
- data/lib/tty/table/operation/truncation.rb +19 -13
- data/lib/tty/table/operation/wrapped.rb +20 -9
- data/lib/tty/table/operations.rb +69 -0
- data/lib/tty/table/renderer/basic.rb +35 -26
- data/lib/tty/table/renderer.rb +13 -1
- data/lib/tty/table/row.rb +174 -0
- data/lib/tty/table.rb +96 -21
- data/lib/tty/text/truncation.rb +1 -1
- data/lib/tty/vector.rb +8 -7
- data/lib/tty/version.rb +1 -1
- data/lib/tty.rb +21 -0
- data/spec/tty/logger/new_spec.rb +36 -0
- data/spec/tty/logger/valid_level_spec.rb +33 -0
- data/spec/tty/system/platform_spec.rb +8 -0
- data/spec/tty/system/which_spec.rb +41 -0
- data/spec/tty/table/access_spec.rb +12 -1
- data/spec/tty/table/add_row_spec.rb +28 -0
- data/spec/tty/table/border/new_spec.rb +9 -4
- data/spec/tty/table/border/null/rendering_spec.rb +39 -1
- data/spec/tty/table/border/options/from_spec.rb +39 -0
- data/spec/tty/table/border/options/new_spec.rb +15 -0
- data/spec/tty/table/border/style_spec.rb +70 -0
- data/spec/tty/table/border_spec.rb +107 -0
- data/spec/tty/table/each_with_index_spec.rb +30 -0
- data/spec/tty/table/field/equality_spec.rb +51 -0
- data/spec/tty/table/field/new_spec.rb +29 -0
- data/spec/tty/table/field/width_spec.rb +21 -0
- data/spec/tty/table/header/call_spec.rb +30 -0
- data/spec/tty/table/header/new_spec.rb +25 -0
- data/spec/tty/table/header/set_spec.rb +15 -0
- data/spec/tty/table/header/to_ary_spec.rb +14 -0
- data/spec/tty/table/header_spec.rb +14 -0
- data/spec/tty/table/operation/alignment_set/align_rows_spec.rb +8 -1
- data/spec/tty/table/operation/truncation/call_spec.rb +27 -0
- data/spec/tty/table/operation/wrapped/call_spec.rb +27 -0
- data/spec/tty/table/operations/new_spec.rb +32 -0
- data/spec/tty/table/options_spec.rb +17 -9
- data/spec/tty/table/renderer/basic/alignment_spec.rb +76 -29
- data/spec/tty/table/renderer/basic/separator_spec.rb +99 -0
- data/spec/tty/table/renderer_spec.rb +7 -1
- data/spec/tty/table/renders_with_spec.rb +35 -28
- data/spec/tty/table/rotate_spec.rb +1 -0
- data/spec/tty/table/row/access_spec.rb +25 -0
- data/spec/tty/table/row/call_spec.rb +41 -0
- data/spec/tty/table/row/data_spec.rb +26 -0
- data/spec/tty/table/row/equality_spec.rb +73 -0
- data/spec/tty/table/row/new_spec.rb +41 -0
- data/spec/tty/table/row/to_ary_spec.rb +14 -0
- data/spec/tty/text/truncation/truncate_spec.rb +6 -0
- metadata +72 -10
@@ -0,0 +1,69 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
class Table
|
5
|
+
|
6
|
+
# A class holding table field operations
|
7
|
+
class Operations
|
8
|
+
|
9
|
+
# The table
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
attr_reader :table
|
13
|
+
private :table
|
14
|
+
|
15
|
+
# Initialize Operations
|
16
|
+
#
|
17
|
+
# @param [TTY::Table] table
|
18
|
+
# the table to perform operations on
|
19
|
+
#
|
20
|
+
# @return [Object]
|
21
|
+
#
|
22
|
+
# @api public
|
23
|
+
def initialize(table)
|
24
|
+
@table = table
|
25
|
+
end
|
26
|
+
|
27
|
+
# Available operations
|
28
|
+
#
|
29
|
+
# @return [Hash]
|
30
|
+
#
|
31
|
+
# @api public
|
32
|
+
def operations
|
33
|
+
@operations ||= Hash.new { |hash, key| hash[key] = [] }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Add operation
|
37
|
+
#
|
38
|
+
# @param [Symbol] type
|
39
|
+
# the operation type
|
40
|
+
# @param [Object] object
|
41
|
+
# the callable object
|
42
|
+
#
|
43
|
+
# @return [Hash]
|
44
|
+
#
|
45
|
+
# @api public
|
46
|
+
def add_operation(type, object)
|
47
|
+
operations[type] << object
|
48
|
+
end
|
49
|
+
|
50
|
+
# Apply operations to a table row
|
51
|
+
#
|
52
|
+
# @param [Symbol] type
|
53
|
+
# the operation type
|
54
|
+
# @param [#to_ary, Row] row
|
55
|
+
# the row to apply operation to
|
56
|
+
# @param [Hash] options
|
57
|
+
# the options for the row
|
58
|
+
#
|
59
|
+
# @return [Hash]
|
60
|
+
#
|
61
|
+
# @api public
|
62
|
+
def run_operations(type, row, options={})
|
63
|
+
options.merge!(:column_widths => table.column_widths)
|
64
|
+
operations[type].each { |op| op.call(row, options) }
|
65
|
+
end
|
66
|
+
|
67
|
+
end # Operations
|
68
|
+
end # Table
|
69
|
+
end # TTY
|
@@ -8,10 +8,6 @@ module TTY
|
|
8
8
|
class Basic
|
9
9
|
extend TTY::Delegatable
|
10
10
|
|
11
|
-
attr_reader :padding
|
12
|
-
|
13
|
-
attr_reader :indent
|
14
|
-
|
15
11
|
# Table to be rendered
|
16
12
|
#
|
17
13
|
# @return [TTY::Table]
|
@@ -19,7 +15,6 @@ module TTY
|
|
19
15
|
# @api public
|
20
16
|
attr_reader :table
|
21
17
|
|
22
|
-
|
23
18
|
# Table border to be rendered
|
24
19
|
#
|
25
20
|
# @return [TTY::Table::Border]
|
@@ -27,18 +22,10 @@ module TTY
|
|
27
22
|
# @api private
|
28
23
|
attr_reader :border_class
|
29
24
|
|
30
|
-
TABLE_DELEGATED_METHODS = [:column_widths, :
|
25
|
+
TABLE_DELEGATED_METHODS = [:column_widths, :column_aligns]
|
31
26
|
|
32
27
|
delegatable_method :table, *TABLE_DELEGATED_METHODS
|
33
28
|
|
34
|
-
# Return an AlignmentSet object for processing alignments
|
35
|
-
#
|
36
|
-
# @return [AlignmentSet]
|
37
|
-
#
|
38
|
-
# @api private
|
39
|
-
attr_reader :alignment_set
|
40
|
-
private :alignment_set
|
41
|
-
|
42
29
|
# Initialize and setup a Renderer
|
43
30
|
#
|
44
31
|
# @param [Hash] options
|
@@ -88,16 +75,14 @@ module TTY
|
|
88
75
|
def render(table, border_class=Border::Null)
|
89
76
|
@table = table
|
90
77
|
@border_class = table.border_class || border_class
|
78
|
+
return if table.empty?
|
91
79
|
|
92
|
-
return if table.to_a.empty?
|
93
|
-
# setup(options)
|
94
80
|
body = []
|
95
81
|
unless table.length.zero?
|
96
82
|
ColumnSet.new(table).extract_widths!
|
97
83
|
# TODO: throw an error if too many columns as compared to terminal width
|
98
84
|
# and then change table.orientation from vertical to horizontal
|
99
85
|
# TODO: Decide about table orientation
|
100
|
-
|
101
86
|
body += render_header
|
102
87
|
body += render_rows
|
103
88
|
end
|
@@ -114,10 +99,10 @@ module TTY
|
|
114
99
|
def render_header
|
115
100
|
header = table.header
|
116
101
|
if header && !header.empty?
|
117
|
-
|
118
|
-
|
119
|
-
border = border_class.new(
|
120
|
-
[border.top_line, border.row_line].compact
|
102
|
+
operations = table.operations
|
103
|
+
operations.run_operations(:alignment, header)
|
104
|
+
border = border_class.new(header, table.border)
|
105
|
+
[ border.top_line, border.row_line ].compact
|
121
106
|
else
|
122
107
|
[]
|
123
108
|
end
|
@@ -129,17 +114,41 @@ module TTY
|
|
129
114
|
#
|
130
115
|
# @api private
|
131
116
|
def render_rows
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
117
|
+
operations = table.operations
|
118
|
+
table.each do |row|
|
119
|
+
operations.run_operations(:alignment, row)
|
120
|
+
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
|
+
}
|
137
126
|
|
138
127
|
[ table.header ? first_row_border.separator : first_row_border.top_line,
|
139
128
|
aligned_border,
|
140
129
|
first_row_border.bottom_line ].compact
|
141
130
|
end
|
142
131
|
|
132
|
+
# Format a single row with border
|
133
|
+
#
|
134
|
+
# @param [Array] row
|
135
|
+
# a row to decorate
|
136
|
+
#
|
137
|
+
# @param [Boolean] is_last_row
|
138
|
+
#
|
139
|
+
# @api private
|
140
|
+
def render_row(row, is_last_row)
|
141
|
+
border = border_class.new(row, table.border)
|
142
|
+
separator = border.separator
|
143
|
+
row_line = border.row_line
|
144
|
+
|
145
|
+
if (table.border.separator == TTY::Table::Border::EACH_ROW) && is_last_row
|
146
|
+
[row_line, separator]
|
147
|
+
else
|
148
|
+
row_line
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
143
152
|
end # Basic
|
144
153
|
end # Renderer
|
145
154
|
end # Table
|
data/lib/tty/table/renderer.rb
CHANGED
@@ -59,7 +59,7 @@ module TTY
|
|
59
59
|
#
|
60
60
|
# @api private
|
61
61
|
def pick_renderer(type=nil)
|
62
|
-
type ? RENDERER_MAPPER[type].new : self.renderer
|
62
|
+
self.renderer= (type ? RENDERER_MAPPER[type].new : self.renderer)
|
63
63
|
end
|
64
64
|
|
65
65
|
# Return the default renderer
|
@@ -82,8 +82,20 @@ module TTY
|
|
82
82
|
|
83
83
|
# Add custom border for the renderer
|
84
84
|
#
|
85
|
+
# @raise [TypeError]
|
86
|
+
# raised if the klass does not inherit from Table::Border
|
87
|
+
#
|
88
|
+
# @raise [NoImplemntationError]
|
89
|
+
# raise if the klass does not implement def_border
|
90
|
+
#
|
85
91
|
# @api public
|
86
92
|
def renders_with(klass)
|
93
|
+
unless klass <= TTY::Table::Border
|
94
|
+
raise TypeError, "#{klass} should inherit from TTY::Table::Border"
|
95
|
+
end
|
96
|
+
unless klass.characters
|
97
|
+
raise NoImplementationError, "#{klass} should implement def_border"
|
98
|
+
end
|
87
99
|
@border_class = klass
|
88
100
|
end
|
89
101
|
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'tty/vector'
|
4
|
+
|
5
|
+
module TTY
|
6
|
+
class Table
|
7
|
+
|
8
|
+
# Convert an Array row into Row
|
9
|
+
#
|
10
|
+
# @return [TTY::Table::Row]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
def to_row(row, header=nil)
|
14
|
+
Row.new(row, header)
|
15
|
+
end
|
16
|
+
|
17
|
+
# A class that represents a row in a table.
|
18
|
+
class Row < Vector
|
19
|
+
include Equatable
|
20
|
+
extend Forwardable
|
21
|
+
|
22
|
+
def_delegators :to_ary, :join
|
23
|
+
|
24
|
+
# The row attributes
|
25
|
+
#
|
26
|
+
# @return [Array]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
attr_reader :attributes
|
30
|
+
|
31
|
+
# The row data
|
32
|
+
#
|
33
|
+
# @return [Hash]
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
attr_reader :data
|
37
|
+
|
38
|
+
# Initialize a Row
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# row = new TTY::Table::Row.new [1,2,3]
|
42
|
+
# row[1] # => 2
|
43
|
+
#
|
44
|
+
# row = new TTY::Table::Row.new [1,2,3], %w[a b c]
|
45
|
+
# row[0] # => 1
|
46
|
+
# row['a'] # => 1
|
47
|
+
#
|
48
|
+
# row = new TTY::Table::Row.new {"a": 1, "b": 2, "c": 3}
|
49
|
+
# row[0] # => 1
|
50
|
+
# row['a'] # => 1
|
51
|
+
#
|
52
|
+
# @param [#to_ary] data
|
53
|
+
# the row data
|
54
|
+
#
|
55
|
+
# @return [undefined]
|
56
|
+
#
|
57
|
+
# @api public
|
58
|
+
def initialize(data, header=nil)
|
59
|
+
case data
|
60
|
+
when Array
|
61
|
+
@attributes = (header || (0...data.length)).to_a
|
62
|
+
fields = data.inject([]) { |arr, datum| arr << to_field(datum) }
|
63
|
+
@data = Hash[@attributes.zip(fields)]
|
64
|
+
when Hash
|
65
|
+
@data = data.dup
|
66
|
+
fields = @data.values.inject([]){|arr, datum| arr << to_field(datum) }
|
67
|
+
@attributes = (header || data.keys).to_a
|
68
|
+
@data = Hash[@attributes.zip(fields)]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Instantiates a new field
|
73
|
+
#
|
74
|
+
# @api public
|
75
|
+
def to_field(options=nil)
|
76
|
+
Field.new(options)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Lookup a value in the row given an attribute allowing for Array or
|
80
|
+
# Hash like indexing
|
81
|
+
#
|
82
|
+
# @exmaple
|
83
|
+
# row[1]
|
84
|
+
# row[:id]
|
85
|
+
# row.call(:id)
|
86
|
+
#
|
87
|
+
# @api public
|
88
|
+
def [](attribute)
|
89
|
+
case attribute
|
90
|
+
when Integer
|
91
|
+
data[attributes[attribute]].value
|
92
|
+
else
|
93
|
+
data.fetch(attribute) do |name|
|
94
|
+
raise UnknownAttributeError, "the attribute #{name} is unkown"
|
95
|
+
end.value
|
96
|
+
end
|
97
|
+
end
|
98
|
+
alias :call :[]
|
99
|
+
|
100
|
+
# Set value at index
|
101
|
+
#
|
102
|
+
# @example
|
103
|
+
# row[attribute] = value
|
104
|
+
#
|
105
|
+
# @api public
|
106
|
+
def []=(attribute, value)
|
107
|
+
case attribute
|
108
|
+
when Integer
|
109
|
+
self.data[attributes[attribute]] = to_field(value)
|
110
|
+
else
|
111
|
+
self.data[attribute] = to_field(value)
|
112
|
+
self.attributes << attribute unless attributes.include?(attribute)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Number of data items in a row
|
117
|
+
#
|
118
|
+
# @return [Integer]
|
119
|
+
#
|
120
|
+
# @api public
|
121
|
+
def size
|
122
|
+
data.size
|
123
|
+
end
|
124
|
+
alias :length :size
|
125
|
+
|
126
|
+
# Convert the Row into Array
|
127
|
+
#
|
128
|
+
# @example
|
129
|
+
# array = row.to_ary
|
130
|
+
#
|
131
|
+
# @return [Array]
|
132
|
+
#
|
133
|
+
# @api public
|
134
|
+
def to_ary
|
135
|
+
to_hash.values_at(*attributes)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Convert the Row into hash
|
139
|
+
#
|
140
|
+
# @return [Hash]
|
141
|
+
#
|
142
|
+
# @api public
|
143
|
+
def to_hash
|
144
|
+
hash = data.dup
|
145
|
+
hash.update(hash) { |key, val| val.value if val }
|
146
|
+
end
|
147
|
+
|
148
|
+
# Check if this row is equivalent to another row
|
149
|
+
#
|
150
|
+
# @return [Boolean]
|
151
|
+
#
|
152
|
+
# @api public
|
153
|
+
def ==(other)
|
154
|
+
to_a == other.to_a
|
155
|
+
end
|
156
|
+
alias :eql? :==
|
157
|
+
|
158
|
+
# Provide a unique hash value. If a row contains the same data as another
|
159
|
+
# row, they will hash to the same value.
|
160
|
+
#
|
161
|
+
# @api public
|
162
|
+
def hash
|
163
|
+
to_a.hash
|
164
|
+
end
|
165
|
+
|
166
|
+
def map!(&block)
|
167
|
+
data.values_at(*attributes).each do |field|
|
168
|
+
field.value = block.call(field)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end # Row
|
172
|
+
|
173
|
+
end # Table
|
174
|
+
end # TTY
|
data/lib/tty/table.rb
CHANGED
@@ -4,8 +4,14 @@ require 'forwardable'
|
|
4
4
|
require 'tty/table/renderer'
|
5
5
|
require 'tty/table/error'
|
6
6
|
require 'tty/table/validatable'
|
7
|
+
require 'tty/table/header'
|
8
|
+
require 'tty/table/row'
|
7
9
|
|
8
10
|
module TTY
|
11
|
+
# A core class intended for storing data in a structured, tabular form.
|
12
|
+
# Once the data is stored in a TTY::Table various operations can be performed
|
13
|
+
# before the information is dumped into a stdout.
|
14
|
+
#
|
9
15
|
class Table
|
10
16
|
include Comparable, Enumerable, Renderer, Conversion
|
11
17
|
include Validatable, Equatable
|
@@ -35,10 +41,10 @@ module TTY
|
|
35
41
|
|
36
42
|
# The table column alignments
|
37
43
|
#
|
38
|
-
# @return [
|
44
|
+
# @return [Array]
|
39
45
|
#
|
40
46
|
# @api private
|
41
|
-
attr_reader :
|
47
|
+
attr_reader :column_aligns
|
42
48
|
|
43
49
|
# The table border class
|
44
50
|
#
|
@@ -47,11 +53,21 @@ module TTY
|
|
47
53
|
|
48
54
|
# The table orientation out of :horizontal and :vertical
|
49
55
|
#
|
50
|
-
# @
|
56
|
+
# @reutrn [TTY::Table::Orientation]
|
51
57
|
#
|
52
58
|
# @api public
|
53
59
|
attr_reader :orientation
|
54
60
|
|
61
|
+
# A callable object used for formatting field content
|
62
|
+
#
|
63
|
+
# @api public
|
64
|
+
attr_accessor :filter
|
65
|
+
|
66
|
+
# The table operations applied to rows
|
67
|
+
#
|
68
|
+
# @api public
|
69
|
+
attr_reader :operations
|
70
|
+
|
55
71
|
# Subset of safe methods that both Array and Hash implement
|
56
72
|
def_delegators(:@rows, :[], :assoc, :flatten, :include?, :index,
|
57
73
|
:length, :select, :to_a, :values_at, :pretty_print, :rassoc)
|
@@ -124,26 +140,41 @@ module TTY
|
|
124
140
|
# used to format table individual column alignment
|
125
141
|
# @option options [String] :column_widths
|
126
142
|
# used to format table individula column width
|
143
|
+
# @option options [Symbol] :orientation
|
144
|
+
# used to transform table orientation
|
127
145
|
#
|
128
146
|
# @return [TTY::Table]
|
129
147
|
#
|
130
148
|
# @api private
|
131
149
|
def initialize(options={}, &block)
|
132
150
|
validate_options! options
|
133
|
-
|
134
|
-
@
|
135
|
-
@rows = coerce options.fetch(:rows) { [] }
|
151
|
+
@header = (value = options[:header]) ? Header.new(value) : nil
|
152
|
+
@rows = coerce(options.fetch(:rows) { Row.new([]) })
|
136
153
|
@renderer = pick_renderer options[:renderer]
|
137
|
-
@
|
154
|
+
@border = TTY::Table::BorderOptions.from(options.delete(:border))
|
155
|
+
@orientation = Orientation.coerce(options.fetch(:orientation) { :horizontal })
|
138
156
|
# TODO: assert that row_size is the same as column widths & aligns
|
139
157
|
@column_widths = Array(options.delete(:column_widths)).map(&:to_i)
|
140
|
-
@
|
158
|
+
@column_aligns = Array(options.delete(:column_aligns)).map(&:to_sym)
|
159
|
+
@operations = TTY::Table::Operations.new(self)
|
160
|
+
@operations.add_operation(:alignment, Operation::AlignmentSet.new(@column_aligns))
|
161
|
+
@filter = options.fetch(:filter) { nil }
|
162
|
+
@width = options.fetch(:width) { TTY.terminal.width }
|
141
163
|
|
142
164
|
assert_row_sizes @rows
|
143
165
|
@orientation.transform(self)
|
144
166
|
yield_or_eval &block if block_given?
|
145
167
|
end
|
146
168
|
|
169
|
+
# Set table fields filter
|
170
|
+
#
|
171
|
+
# @param [#call] block
|
172
|
+
#
|
173
|
+
# @api public
|
174
|
+
def filter(&block)
|
175
|
+
@operations.add_operation(:filter, block)
|
176
|
+
end
|
177
|
+
|
147
178
|
# Sets table orientation
|
148
179
|
#
|
149
180
|
# @param [String,Symbol] value
|
@@ -155,6 +186,8 @@ module TTY
|
|
155
186
|
|
156
187
|
# Marks this table as rotated
|
157
188
|
#
|
189
|
+
# @return [Boolean]
|
190
|
+
#
|
158
191
|
# @api public
|
159
192
|
def rotated?
|
160
193
|
@rotated
|
@@ -174,7 +207,7 @@ module TTY
|
|
174
207
|
#
|
175
208
|
# @api private
|
176
209
|
def rotate_vertical
|
177
|
-
@rows = ([header].compact + rows).transpose
|
210
|
+
@rows = ([header].compact + rows).transpose.map { |row| to_row(row) }
|
178
211
|
@header = [] if header
|
179
212
|
@rotated = true
|
180
213
|
end
|
@@ -185,13 +218,31 @@ module TTY
|
|
185
218
|
def rotate_horizontal
|
186
219
|
transposed = rows.transpose
|
187
220
|
if header && header.empty?
|
188
|
-
@rows = transposed[1..-1]
|
189
221
|
@header = transposed[0]
|
222
|
+
@rows = transposed[1..-1].map { |row| to_row(row, @header) }
|
190
223
|
elsif rotated?
|
191
|
-
@rows = transposed
|
224
|
+
@rows = transposed.map { |row| to_row(row) }
|
192
225
|
end
|
193
226
|
end
|
194
227
|
|
228
|
+
# Store border characters, style and separator for the table rendering
|
229
|
+
#
|
230
|
+
# @param [Hash, BorderOptions] options
|
231
|
+
#
|
232
|
+
# @yield [] block representing border options
|
233
|
+
#
|
234
|
+
# @api public
|
235
|
+
def border(options=(not_set=true), &block)
|
236
|
+
@border = TTY::Table::BorderOptions.new unless @border
|
237
|
+
if block_given?
|
238
|
+
border_dsl = TTY::Table::BorderDSL.new(&block)
|
239
|
+
@border = border_dsl.options
|
240
|
+
elsif !not_set
|
241
|
+
@border = TTY::Table::BorderOptions.from(options)
|
242
|
+
end
|
243
|
+
@border
|
244
|
+
end
|
245
|
+
|
195
246
|
# Lookup element of the table given a row(i) and column(j)
|
196
247
|
#
|
197
248
|
# @api public
|
@@ -241,14 +292,19 @@ module TTY
|
|
241
292
|
end
|
242
293
|
|
243
294
|
# Return a column number at the index of the table as an Array.
|
295
|
+
# If the table has a header then column can be searched by header name.
|
244
296
|
# When a block is given, the elements of that Array are iterated over.
|
245
297
|
#
|
246
298
|
# @example
|
299
|
+
# header = [:h1, :h2]
|
247
300
|
# rows = [ ['a1', 'a2'], ['b1', 'b2'] ]
|
248
|
-
# table = TTY::Table.new :rows => rows
|
249
|
-
# table.column(1)
|
301
|
+
# table = TTY::Table.new :rows => rows, :header => header
|
302
|
+
# table.column(1)
|
303
|
+
# table.column(1) { |element| ... }
|
304
|
+
# table.column(:h1)
|
305
|
+
# table.column(:h1) { |element| ... }
|
250
306
|
#
|
251
|
-
# @param [Integer] index
|
307
|
+
# @param [Integer, String, Symbol] index
|
252
308
|
#
|
253
309
|
# @yield []
|
254
310
|
# optional block to execute in the iteration operation
|
@@ -257,11 +313,12 @@ module TTY
|
|
257
313
|
#
|
258
314
|
# @api public
|
259
315
|
def column(index)
|
316
|
+
index_unknown = index.is_a?(Integer) && (index >= column_size || index < 0)
|
260
317
|
if block_given?
|
261
|
-
return self if
|
262
|
-
rows.map { |row| yield row[index]
|
318
|
+
return self if index_unknown
|
319
|
+
rows.map { |row| yield row[index] }
|
263
320
|
else
|
264
|
-
return nil if
|
321
|
+
return nil if index_unknown
|
265
322
|
rows.map { |row| row[index] }.compact
|
266
323
|
end
|
267
324
|
end
|
@@ -276,7 +333,7 @@ module TTY
|
|
276
333
|
def <<(row)
|
277
334
|
rows_copy = rows.dup
|
278
335
|
assert_row_sizes rows_copy << row
|
279
|
-
rows << row
|
336
|
+
rows << to_row(row)
|
280
337
|
self
|
281
338
|
end
|
282
339
|
|
@@ -293,8 +350,25 @@ module TTY
|
|
293
350
|
# @api public
|
294
351
|
def each
|
295
352
|
return to_enum unless block_given?
|
296
|
-
rows.each
|
297
|
-
|
353
|
+
rows.each { |row| yield row }
|
354
|
+
self
|
355
|
+
end
|
356
|
+
|
357
|
+
# Iterate over each element yielding in addition row and column index
|
358
|
+
#
|
359
|
+
# @example
|
360
|
+
# table = TTY::Table.new(header, tuples)
|
361
|
+
# table.each_with_index { |el, row, col| puts "#{el} at #{row},#{col}" }
|
362
|
+
#
|
363
|
+
# @return self
|
364
|
+
#
|
365
|
+
# @api public
|
366
|
+
def each_with_index
|
367
|
+
return to_enum unless block_given?
|
368
|
+
rows.each_with_index do |row, row_index|
|
369
|
+
row.each_with_index do |el, col_index|
|
370
|
+
yield el, row_index, col_index
|
371
|
+
end
|
298
372
|
end
|
299
373
|
self
|
300
374
|
end
|
@@ -375,7 +449,8 @@ module TTY
|
|
375
449
|
#
|
376
450
|
# @api public
|
377
451
|
def coerce(rows)
|
378
|
-
convert_to_array(rows)
|
452
|
+
rows = convert_to_array(rows)
|
453
|
+
rows.map { |row| to_row(row, header) }
|
379
454
|
end
|
380
455
|
|
381
456
|
private
|
data/lib/tty/text/truncation.rb
CHANGED
@@ -57,7 +57,7 @@ module TTY
|
|
57
57
|
|
58
58
|
as_unicode do
|
59
59
|
chars = text.chars.to_a
|
60
|
-
return chars.join if chars.length
|
60
|
+
return chars.join if chars.length <= length
|
61
61
|
stop = chars[0, length_without_trailing].rindex(separator)
|
62
62
|
|
63
63
|
chars[0, stop || length_without_trailing].join + trailing
|
data/lib/tty/vector.rb
CHANGED
@@ -41,7 +41,7 @@ module TTY
|
|
41
41
|
#
|
42
42
|
# @api public
|
43
43
|
def [](indx)
|
44
|
-
elements[
|
44
|
+
elements[indx]
|
45
45
|
end
|
46
46
|
alias at []
|
47
47
|
alias element []
|
@@ -58,7 +58,7 @@ module TTY
|
|
58
58
|
#
|
59
59
|
# @api public
|
60
60
|
def []=(indx, value)
|
61
|
-
elements[
|
61
|
+
self.elements[indx] = value
|
62
62
|
end
|
63
63
|
alias set_element []=
|
64
64
|
|
@@ -71,9 +71,9 @@ module TTY
|
|
71
71
|
# @return [self]
|
72
72
|
#
|
73
73
|
# @api public
|
74
|
-
def each
|
75
|
-
return to_enum
|
76
|
-
to_ary.each
|
74
|
+
def each
|
75
|
+
return to_enum unless block_given?
|
76
|
+
to_ary.each { |element| yield element }
|
77
77
|
self
|
78
78
|
end
|
79
79
|
|
@@ -83,7 +83,7 @@ module TTY
|
|
83
83
|
#
|
84
84
|
# @api public
|
85
85
|
def to_ary
|
86
|
-
elements
|
86
|
+
@elements
|
87
87
|
end
|
88
88
|
|
89
89
|
# Check if there are not elements.
|
@@ -103,6 +103,7 @@ module TTY
|
|
103
103
|
def size
|
104
104
|
to_ary.size
|
105
105
|
end
|
106
|
+
alias :length :size
|
106
107
|
|
107
108
|
# Return the vector elements in an array.
|
108
109
|
#
|
@@ -110,7 +111,7 @@ module TTY
|
|
110
111
|
#
|
111
112
|
# @api public
|
112
113
|
def to_a
|
113
|
-
|
114
|
+
to_ary.dup
|
114
115
|
end
|
115
116
|
|
116
117
|
end # Vector
|
data/lib/tty/version.rb
CHANGED