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
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# TTY
|
2
|
-
[![
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/tty.png)][gem]
|
3
|
+
[![Build Status](https://secure.travis-ci.org/peter-murach/tty.png?branch=master)][travis]
|
4
|
+
[![Code Climate](https://codeclimate.com/github/peter-murach/tty.png)][codeclimate]
|
3
5
|
|
6
|
+
[gem]: http://badge.fury.io/rb/tty
|
4
7
|
[travis]: http://travis-ci.org/peter-murach/tty
|
5
8
|
[codeclimate]: https://codeclimate.com/github/peter-murach/tty
|
6
9
|
|
@@ -10,14 +13,16 @@ Toolbox for developing CLI clients in Ruby. This library provides a fluid interf
|
|
10
13
|
|
11
14
|
Jump-start development of your command line app:
|
12
15
|
|
13
|
-
*
|
14
|
-
* Terminal output colorization.
|
15
|
-
* Terminal & System detection utilities.
|
16
|
-
* Text
|
17
|
-
* Shell user interface.
|
18
|
-
* File diffs.
|
19
|
-
* Progress bar.
|
20
|
-
* Configuration file management.
|
16
|
+
* Table rendering with an easy-to-use API [status: In Progress]
|
17
|
+
* Terminal output colorization. [status: ✔ ]
|
18
|
+
* Terminal & System detection utilities. [status: In Progress]
|
19
|
+
* Text manipulation(wrapping/truncation) [status: In Progress]
|
20
|
+
* Shell user interface. [status: In Progress]
|
21
|
+
* File diffs. [status: TODO]
|
22
|
+
* Progress bar. [status: TODO]
|
23
|
+
* Configuration file management. [status: TODO]
|
24
|
+
* Logging [status: In Progress]
|
25
|
+
* Plugin ecosystem [status: TODO]
|
21
26
|
* Fully tested with major ruby interpreters.
|
22
27
|
* No dependencies to allow for easy gem vendoring.
|
23
28
|
|
@@ -45,7 +50,6 @@ To instantiate table pass 2-dimensional array:
|
|
45
50
|
table = TTY::Table[['a1', 'a2'], ['b1', 'b2']]
|
46
51
|
table = TTY::Table.new [['a1', 'a2'], ['b1', 'b2']]
|
47
52
|
table = TTY::Table.new rows: [['a1', 'a2'], ['b1', 'b2']]
|
48
|
-
|
49
53
|
table = TTY::Table.new ['h1', 'h2'], [['a1', 'a2'], ['b1', 'b2']]
|
50
54
|
table = TTY::Table.new header: ['h1', 'h2'], rows: [['a1', 'a2'], ['b1', 'b2']]
|
51
55
|
```
|
@@ -63,6 +67,8 @@ Apart from `rows` and `header`, you can provide other customization options such
|
|
63
67
|
column_aligns # array of cell alignments out of :left, :center and :right
|
64
68
|
renderer # enforce display type out of :basic, :color, :unicode, :ascii
|
65
69
|
orientation # either :horizontal or :vertical
|
70
|
+
border # hash of border properties out of :characters, :style, :separator keys
|
71
|
+
width # constrain the table total width, otherwise dynamically calculated based on content and terminal size
|
66
72
|
```
|
67
73
|
|
68
74
|
Table behaves like an Array so `<<`, `each` and familiar methods can be used
|
@@ -73,12 +79,15 @@ Table behaves like an Array so `<<`, `each` and familiar methods can be used
|
|
73
79
|
table << ['a1', 'a2'] << ['b1', 'b2'] # chain rows assignment
|
74
80
|
|
75
81
|
table.each { |row| ... } # iterate over rows
|
82
|
+
table.each_with_index # iterate over each element with row and column index
|
76
83
|
table[i, j] # return element at row(i) and column(j)
|
77
84
|
table.row(i) { ... } # return array for row(i)
|
78
85
|
table.column(j) { ... } # return array for column(j)
|
86
|
+
table.column(name) # return array for column(name), name of header
|
79
87
|
table.row_size # return row size
|
80
88
|
table.column_size # return column size
|
81
89
|
table.size # return an array of [row_size, column_size]
|
90
|
+
table.border # specify border properties
|
82
91
|
```
|
83
92
|
|
84
93
|
or pass your rows in a block
|
@@ -99,7 +108,9 @@ And then to print do
|
|
99
108
|
b1 b2 b3
|
100
109
|
```
|
101
110
|
|
102
|
-
|
111
|
+
#### Border
|
112
|
+
|
113
|
+
To print border around data table you need to specify `renderer` type out of `basic`, `ascii`, `unicode`. By default `basic` is used. For instance, to output unicode border:
|
103
114
|
|
104
115
|
```
|
105
116
|
table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2'], renderer: 'unicode'
|
@@ -113,26 +124,132 @@ To print border around data table you need to specify `renderer` type out of `ba
|
|
113
124
|
└───────┴───────┘
|
114
125
|
```
|
115
126
|
|
116
|
-
You can also create your own custom border by subclassing `TTY::Table::Border`
|
127
|
+
You can also create your own custom border by subclassing `TTY::Table::Border` and implementing the `def_border` method using internal DSL methods like so:
|
117
128
|
|
118
129
|
```ruby
|
119
130
|
class MyBorder < TTY::Table::Border
|
120
131
|
def_border do
|
121
|
-
|
122
|
-
|
123
|
-
'
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
}
|
132
|
+
left '$'
|
133
|
+
center '$'
|
134
|
+
right '$'
|
135
|
+
bottom ' '
|
136
|
+
bottom_mid '*'
|
137
|
+
bottom_left '*'
|
138
|
+
bottom_right '*'
|
129
139
|
end
|
130
140
|
end
|
131
141
|
```
|
132
|
-
|
142
|
+
|
143
|
+
Next pass the border class to your instantiated table
|
133
144
|
|
134
145
|
```ruby
|
146
|
+
table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']
|
135
147
|
table.renders_with MyBorder
|
148
|
+
table.to_s
|
149
|
+
|
150
|
+
$header1$header2$
|
151
|
+
$a1 $a2 $
|
152
|
+
* * *
|
153
|
+
```
|
154
|
+
|
155
|
+
Finally, if you want to introduce slight modifications to the predefined border types, you can use table `border` helper like so
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']
|
159
|
+
table.border do
|
160
|
+
mid '='
|
161
|
+
mid_mid ' '
|
162
|
+
end
|
163
|
+
|
164
|
+
table.to_s
|
165
|
+
|
166
|
+
header1 header2
|
167
|
+
======= =======
|
168
|
+
a1 a2
|
169
|
+
b1 b2
|
170
|
+
```
|
171
|
+
|
172
|
+
In addition to specifying border characters you can force table to render separator line on each row like:
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']]
|
176
|
+
table.border.separator = :each_row
|
177
|
+
table.to_s
|
178
|
+
|
179
|
+
+-------+-------+
|
180
|
+
|header1|header2|
|
181
|
+
+-------+-------+
|
182
|
+
|a1 |a2 |
|
183
|
+
+-------+-------+
|
184
|
+
|b1 |b2 |
|
185
|
+
+-------+-------+
|
186
|
+
```
|
187
|
+
|
188
|
+
Also to change the display color of your border do:
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
table.border.style = :red
|
192
|
+
```
|
193
|
+
|
194
|
+
#### Alignment
|
195
|
+
|
196
|
+
All columns are left aligned by default. You can enforce per column alignment by passing `column_aligns` option like so
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
rows = [['a1', 'a2'], ['b1', 'b2']
|
200
|
+
table = TTY::Table.new rows: rows, column_aligns: [:center, :right]
|
201
|
+
```
|
202
|
+
|
203
|
+
To align a single column do
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
table.align_column(1, :right)
|
207
|
+
```
|
208
|
+
|
209
|
+
If you require a more granular alignment you can align individual fields in a row by passing `align` option
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
table = TTY::Table.new do |t|
|
213
|
+
t << ['a1', 'a2', 'a3']
|
214
|
+
t << ['b1', {:value => 'b2', :align => :right}, 'b3']
|
215
|
+
t << ['c1', 'c2', {:value => 'c3', :align => :center}]
|
216
|
+
end
|
217
|
+
```
|
218
|
+
|
219
|
+
#### Style
|
220
|
+
|
221
|
+
To format individual fields/cells do
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
table = TTY::Table.new rows: rows, width: 40
|
225
|
+
```
|
226
|
+
|
227
|
+
#### Filter
|
228
|
+
|
229
|
+
You can define filters that will modify individual table fields value before they are rendered. A filter can be a callable such as proc. Here's an example that formats
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']
|
233
|
+
table.filter = Proc.new do |val, row_index, col_index|
|
234
|
+
if col_index == 1 and !(row_index == 0)
|
235
|
+
val.capitalize
|
236
|
+
end
|
237
|
+
end
|
238
|
+
table.to_s
|
239
|
+
|
240
|
+
+-------+-------+
|
241
|
+
|header1|header2|
|
242
|
+
+-------+-------+
|
243
|
+
|a1 |A2 |
|
244
|
+
+-------+-------+
|
245
|
+
|b1 |B2 |
|
246
|
+
+-------+-------+
|
247
|
+
|
248
|
+
```
|
249
|
+
|
250
|
+
To add background color to even fields do
|
251
|
+
|
252
|
+
```ruby
|
136
253
|
```
|
137
254
|
|
138
255
|
### Terminal
|
@@ -241,8 +358,9 @@ on the other hand, if we are interested in range answer then
|
|
241
358
|
### System
|
242
359
|
|
243
360
|
```ruby
|
244
|
-
TTY::System.unix?
|
245
|
-
TTY::System.windows?
|
361
|
+
TTY::System.unix? # => true
|
362
|
+
TTY::System.windows? # => false
|
363
|
+
TTY::System.which(cmd) # full path to executable if found, nil otherwise
|
246
364
|
```
|
247
365
|
|
248
366
|
## Contributing
|
data/benchmarks/table.rb
CHANGED
@@ -13,6 +13,7 @@ rows = (1..100).map { |n| ["row#{n}", "red"] }
|
|
13
13
|
table = TTY::Table.new(header, rows)
|
14
14
|
table_ascii = TTY::Table.new(header, rows, :renderer => :ascii)
|
15
15
|
table_unicode = TTY::Table.new(header, rows, :renderer => :unicode)
|
16
|
+
table_color = TTY::Table.new(header, rows, :renderer => :ascii, :border => { :style => :red })
|
16
17
|
|
17
18
|
Benchmark.ips do |r|
|
18
19
|
|
@@ -32,4 +33,8 @@ Benchmark.ips do |r|
|
|
32
33
|
table_unicode.to_s
|
33
34
|
end
|
34
35
|
|
36
|
+
r.report("TTY Color #to_s") do
|
37
|
+
table_color.to_s
|
38
|
+
end
|
39
|
+
|
35
40
|
end
|
data/lib/tty/logger.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
|
5
|
+
# A class providing logging system
|
6
|
+
class Logger
|
7
|
+
include TTY::Equatable
|
8
|
+
|
9
|
+
ALL = 0
|
10
|
+
INFO = 1
|
11
|
+
DEBUG = 2
|
12
|
+
WARN = 3
|
13
|
+
ERROR = 4
|
14
|
+
FATAL = 5
|
15
|
+
OFF = 6
|
16
|
+
|
17
|
+
MAX_LEVELS = 7
|
18
|
+
|
19
|
+
attr_reader :namespace
|
20
|
+
|
21
|
+
attr_reader :level
|
22
|
+
|
23
|
+
attr_reader :output
|
24
|
+
|
25
|
+
attr_reader :timestamp_format
|
26
|
+
|
27
|
+
# Initialize a Logger
|
28
|
+
#
|
29
|
+
# @param [String] name
|
30
|
+
#
|
31
|
+
# @param [Hash] options
|
32
|
+
#
|
33
|
+
# @option options [String] :output
|
34
|
+
#
|
35
|
+
# @api public
|
36
|
+
def initialize(options={})
|
37
|
+
@namespace = options.fetch(:namespace) { raise ArgumentError, "Logger must have namespace", caller }
|
38
|
+
@output = options.fetch(:output) { $stderr }
|
39
|
+
@level = options.fetch(:level) { ALL }
|
40
|
+
@timestamp_format = options.fetch(:timestamp_format) { '%Y-%m-%d %T' }
|
41
|
+
end
|
42
|
+
|
43
|
+
def level=(level)
|
44
|
+
validate_level(level)
|
45
|
+
@level = level
|
46
|
+
end
|
47
|
+
|
48
|
+
# @api public
|
49
|
+
def timestamp
|
50
|
+
Time.now.strftime(timestamp_format)
|
51
|
+
end
|
52
|
+
|
53
|
+
def validate_level(level)
|
54
|
+
unless valid_level?(level)
|
55
|
+
raise ArgumentError, "Log level must be 0..#{MAX_LEVELS}", caller
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.valid_level?(level)
|
60
|
+
!level.nil? && level.kind_of?(Numeric) && level >= ALL && level <= OFF
|
61
|
+
end
|
62
|
+
|
63
|
+
# Print formatted log to output
|
64
|
+
#
|
65
|
+
# @api public
|
66
|
+
def log(message)
|
67
|
+
output.print timestamp + ' - ' + message
|
68
|
+
end
|
69
|
+
|
70
|
+
end # Logger
|
71
|
+
end # TTY
|
@@ -85,8 +85,9 @@ module TTY
|
|
85
85
|
# @api private
|
86
86
|
def define_compare
|
87
87
|
define_method(:compare?) do |comparator, other|
|
88
|
-
|
89
|
-
|
88
|
+
klass = self.class
|
89
|
+
attrs = klass.comparison_attrs || []
|
90
|
+
attrs.all? { |attr| send(attr).send(comparator, other.send(attr)) }
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
@@ -142,6 +143,9 @@ module TTY
|
|
142
143
|
#
|
143
144
|
# @api public
|
144
145
|
def ==(other)
|
146
|
+
print '== '
|
147
|
+
p self
|
148
|
+
p other
|
145
149
|
return false unless self.class <=> other.class
|
146
150
|
compare?(__method__, other)
|
147
151
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
class System
|
5
|
+
|
6
|
+
# A class responsible for finding an executable in the PATH
|
7
|
+
class Which
|
8
|
+
|
9
|
+
# Find an executable in the PATH
|
10
|
+
#
|
11
|
+
# @param [String] command
|
12
|
+
# the command to search in the PATH
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# which("ruby") # => /usr/local/bin/ruby
|
16
|
+
#
|
17
|
+
# @return [String]
|
18
|
+
# the full path to executable if found, `nil` otherwise
|
19
|
+
#
|
20
|
+
# @api public
|
21
|
+
def which(command)
|
22
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
23
|
+
default_system_path.each do |path|
|
24
|
+
exts.each do |ext|
|
25
|
+
exec = File.join("#{path}", "#{command}#{ext}")
|
26
|
+
return exec if File.executable? exec
|
27
|
+
end
|
28
|
+
end
|
29
|
+
return nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# Find default system paths
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
def default_system_path
|
36
|
+
ENV['PATH'].split(File::PATH_SEPARATOR)
|
37
|
+
end
|
38
|
+
|
39
|
+
end # Which
|
40
|
+
end # System
|
41
|
+
end # TTY
|
data/lib/tty/system.rb
CHANGED
@@ -25,6 +25,14 @@ module TTY
|
|
25
25
|
RbConfig::CONFIG['host_os'] =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
|
26
26
|
end
|
27
27
|
|
28
|
+
# Find an executable in the PATH
|
29
|
+
#
|
30
|
+
# @see TTY::System::Which
|
31
|
+
#
|
32
|
+
# @api public
|
33
|
+
def which(command)
|
34
|
+
Which.new(command)
|
35
|
+
end
|
28
36
|
end
|
29
37
|
|
30
38
|
end # System
|
@@ -8,22 +8,21 @@ module TTY
|
|
8
8
|
class ASCII < Border
|
9
9
|
|
10
10
|
def_border do
|
11
|
-
|
12
|
-
'
|
13
|
-
|
14
|
-
|
15
|
-
'
|
16
|
-
'
|
17
|
-
|
18
|
-
|
19
|
-
'
|
20
|
-
'
|
21
|
-
|
22
|
-
|
23
|
-
'
|
24
|
-
'
|
25
|
-
|
26
|
-
}
|
11
|
+
top '-'
|
12
|
+
top_mid '+'
|
13
|
+
top_left '+'
|
14
|
+
top_right '+'
|
15
|
+
bottom '-'
|
16
|
+
bottom_mid '+'
|
17
|
+
bottom_left '+'
|
18
|
+
bottom_right '+'
|
19
|
+
mid '-'
|
20
|
+
mid_mid '+'
|
21
|
+
mid_left '+'
|
22
|
+
mid_right '+'
|
23
|
+
left '|'
|
24
|
+
center '|'
|
25
|
+
right '|'
|
27
26
|
end
|
28
27
|
|
29
28
|
end # ASCII
|
@@ -7,18 +7,23 @@ module TTY
|
|
7
7
|
# A class that represents no border.
|
8
8
|
class Null < Border
|
9
9
|
|
10
|
+
def_border do
|
11
|
+
center SPACE_CHAR
|
12
|
+
end
|
13
|
+
|
10
14
|
# A stub top line
|
11
15
|
#
|
12
16
|
# @api private
|
13
17
|
def top_line
|
14
|
-
nil
|
18
|
+
border ? super : nil
|
15
19
|
end
|
16
20
|
|
17
21
|
# A stub separator line
|
18
22
|
#
|
19
23
|
# @api private
|
20
24
|
def separator
|
21
|
-
|
25
|
+
return [] if border.separator == EACH_ROW
|
26
|
+
border ? super : nil
|
22
27
|
end
|
23
28
|
|
24
29
|
# A line spanning all columns delemited by space character.
|
@@ -27,14 +32,14 @@ module TTY
|
|
27
32
|
#
|
28
33
|
# @api private
|
29
34
|
def row_line
|
30
|
-
row.join(
|
35
|
+
(border && !border.characters.empty?) ? super : row.join(SPACE_CHAR)
|
31
36
|
end
|
32
37
|
|
33
38
|
# A stub bottom line
|
34
39
|
#
|
35
40
|
# @api private
|
36
41
|
def bottom_line
|
37
|
-
nil
|
42
|
+
border ? super : nil
|
38
43
|
end
|
39
44
|
|
40
45
|
end # Null
|
@@ -8,22 +8,21 @@ module TTY
|
|
8
8
|
class Unicode < Border
|
9
9
|
|
10
10
|
def_border do
|
11
|
-
|
12
|
-
'
|
13
|
-
'
|
14
|
-
'
|
15
|
-
'
|
16
|
-
'
|
17
|
-
'
|
18
|
-
|
19
|
-
'
|
20
|
-
'
|
21
|
-
'
|
22
|
-
'
|
23
|
-
'
|
24
|
-
'
|
25
|
-
|
26
|
-
}
|
11
|
+
top '─'
|
12
|
+
top_mid '┬'
|
13
|
+
top_left '┌'
|
14
|
+
top_right '┐'
|
15
|
+
bottom '─'
|
16
|
+
bottom_mid '┴'
|
17
|
+
bottom_left '└'
|
18
|
+
bottom_right '┘'
|
19
|
+
mid '─'
|
20
|
+
mid_mid '┼'
|
21
|
+
mid_left '├'
|
22
|
+
mid_right '┤'
|
23
|
+
left '│'
|
24
|
+
center '│'
|
25
|
+
right '│'
|
27
26
|
end
|
28
27
|
|
29
28
|
end # Unicode
|
data/lib/tty/table/border.rb
CHANGED
@@ -6,6 +6,14 @@ module TTY
|
|
6
6
|
# Abstract base class that is responsible for building the table border.
|
7
7
|
class Border
|
8
8
|
include Unicode
|
9
|
+
include TTY::Equatable
|
10
|
+
|
11
|
+
EMPTY_CHAR = ''.freeze
|
12
|
+
|
13
|
+
SPACE_CHAR = ' '.freeze
|
14
|
+
|
15
|
+
# Represent a separtor on each row
|
16
|
+
EACH_ROW = :each_row
|
9
17
|
|
10
18
|
# The row cell widths
|
11
19
|
#
|
@@ -19,6 +27,9 @@ module TTY
|
|
19
27
|
attr_reader :row
|
20
28
|
private :row
|
21
29
|
|
30
|
+
# The table custom border characters
|
31
|
+
attr_reader :border
|
32
|
+
|
22
33
|
class << self
|
23
34
|
# Store characters for border
|
24
35
|
#
|
@@ -28,23 +39,36 @@ module TTY
|
|
28
39
|
|
29
40
|
# Instantiate a new object
|
30
41
|
#
|
42
|
+
# @param [Array] row
|
43
|
+
#
|
44
|
+
# @param [BorderOptions] options
|
45
|
+
#
|
31
46
|
# @return [Object]
|
32
47
|
#
|
33
48
|
# @api private
|
34
|
-
def initialize(row=nil)
|
49
|
+
def initialize(row, options=nil)
|
35
50
|
if self.class == Border
|
36
51
|
raise NotImplementedError, "#{self} is an abstract class"
|
37
52
|
else
|
38
53
|
@row = row
|
39
54
|
@widths = row.map { |cell| cell.chars.to_a.size }
|
55
|
+
@border = TTY::Table::BorderOptions.from options
|
40
56
|
end
|
41
57
|
end
|
42
58
|
|
43
59
|
# Define border characters
|
44
60
|
#
|
61
|
+
# @param [Hash] characters
|
62
|
+
# the border characters
|
63
|
+
#
|
64
|
+
# @return [Hash]
|
65
|
+
#
|
45
66
|
# @api public
|
46
|
-
def self.def_border(&block)
|
47
|
-
|
67
|
+
def self.def_border(characters=(not_set=true), &block)
|
68
|
+
return self.characters = characters if !not_set
|
69
|
+
|
70
|
+
dsl = TTY::Table::BorderDSL.new(&block)
|
71
|
+
self.characters = dsl.characters
|
48
72
|
end
|
49
73
|
|
50
74
|
# Retrive individula character by type
|
@@ -56,7 +80,31 @@ module TTY
|
|
56
80
|
#
|
57
81
|
# @api private
|
58
82
|
def [](type)
|
59
|
-
self.class.characters
|
83
|
+
characters = self.class.characters
|
84
|
+
chars = border.nil? ? characters : characters.merge(border.characters)
|
85
|
+
chars[type] || EMPTY_CHAR
|
86
|
+
end
|
87
|
+
|
88
|
+
# Check if border color is set
|
89
|
+
#
|
90
|
+
# @return [Boolean]
|
91
|
+
#
|
92
|
+
# @api public
|
93
|
+
def color?
|
94
|
+
border && border.style
|
95
|
+
end
|
96
|
+
|
97
|
+
# Set color on characters
|
98
|
+
#
|
99
|
+
# @param [Symbol] color
|
100
|
+
#
|
101
|
+
# @param [Array[String]] array of strings
|
102
|
+
#
|
103
|
+
# @return [Array[String]]
|
104
|
+
#
|
105
|
+
# @api public
|
106
|
+
def self.set_color(color, *strings)
|
107
|
+
strings.map { |string| TTY.terminal.color.set(string, color) }
|
60
108
|
end
|
61
109
|
|
62
110
|
# A line spanning all columns marking top of a table.
|
@@ -83,7 +131,15 @@ module TTY
|
|
83
131
|
#
|
84
132
|
# @api private
|
85
133
|
def row_line
|
86
|
-
|
134
|
+
right_char = self['right']
|
135
|
+
left_char = self['left']
|
136
|
+
center_char = self['center']
|
137
|
+
|
138
|
+
if color?
|
139
|
+
right_char, center_char, left_char = Border.set_color(border.style, right_char, center_char, left_char)
|
140
|
+
end
|
141
|
+
|
142
|
+
result = left_char + row.join(center_char) + right_char
|
87
143
|
result.empty? ? nil : result
|
88
144
|
end
|
89
145
|
|
@@ -106,10 +162,14 @@ module TTY
|
|
106
162
|
# @api private
|
107
163
|
def render(type)
|
108
164
|
type = type.to_s
|
109
|
-
|
110
|
-
|
111
|
-
self["#{type}
|
112
|
-
self["#{type}
|
165
|
+
border_char = self[type]
|
166
|
+
line = render_line(border_char,
|
167
|
+
self["#{type}_left"] || border_char,
|
168
|
+
self["#{type}_right"] || border_char,
|
169
|
+
self["#{type}_mid"])
|
170
|
+
|
171
|
+
line = Border.set_color(border.style, line) if color?
|
172
|
+
line
|
113
173
|
end
|
114
174
|
|
115
175
|
# Generate a border string
|