tty 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- 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