tty 0.0.2 → 0.0.3
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/README.md +20 -3
- data/lib/tty.rb +4 -0
- data/lib/tty/support/coercion.rb +31 -0
- data/lib/tty/table.rb +31 -10
- data/lib/tty/table/operation/alignment.rb +79 -0
- data/lib/tty/table/operation/alignment_set.rb +119 -0
- data/lib/tty/table/renderer/basic.rb +36 -14
- data/lib/tty/table/validatable.rb +3 -0
- data/lib/tty/version.rb +1 -1
- data/spec/tty/support/coercion_spec.rb +41 -0
- data/spec/tty/table/empty_spec.rb +23 -0
- data/spec/tty/table/initialize_spec.rb +15 -4
- data/spec/tty/table/operation/alignment/format_spec.rb +39 -0
- data/spec/tty/table/operation/alignment/new_spec.rb +31 -0
- data/spec/tty/table/operation/alignment_set/align_rows_spec.rb +46 -0
- data/spec/tty/table/operation/alignment_set/each_spec.rb +17 -0
- data/spec/tty/table/operation/alignment_set/new_spec.rb +27 -0
- data/spec/tty/table/operation/alignment_set/to_ary_spec.rb +14 -0
- data/spec/tty/table/options_spec.rb +33 -0
- data/spec/tty/table/renderer/basic_spec.rb +24 -1
- metadata +29 -8
data/README.md
CHANGED
@@ -41,26 +41,43 @@ Or install it yourself as:
|
|
41
41
|
To instantiate table
|
42
42
|
|
43
43
|
```ruby
|
44
|
-
table = TTY::Table.new :rows => [['a1', 'a2'], ['b1', 'b2']]
|
45
44
|
table = TTY::Table[['a1', 'a2'], ['b1', 'b2']]
|
45
|
+
table = TTY::Table.new [['a1', 'a2'], ['b1', 'b2']]
|
46
|
+
table = TTY::Table.new rows: [['a1', 'a2'], ['b1', 'b2']]
|
46
47
|
```
|
47
48
|
|
48
|
-
|
49
|
+
Apart from `rows`, you can provide other customization options such as
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
column_widths # enforce maximum columns widths
|
53
|
+
column_aligns # array of cell alignments out of :left, :center and :right
|
54
|
+
renderer # enforce display type out of :basic, :color, :unicode, :ascii
|
55
|
+
```
|
56
|
+
|
57
|
+
Table behaves like an Array so `<<`, `each` and familiar methods can be used
|
49
58
|
|
50
59
|
```ruby
|
51
60
|
table << ['a1', 'a2', 'a3']
|
52
61
|
table << ['b1', 'b2', 'b3']
|
62
|
+
|
63
|
+
table.each { |row| ... } # iterate over rows
|
64
|
+
table[i, j] # return element at row(i) and column(j)
|
65
|
+
table.row(i) { ... } # return array for row(i)
|
66
|
+
table.column(j) { ... } # return array for column(j)
|
67
|
+
table.row_size # return row size
|
68
|
+
table.column_size # return column size
|
53
69
|
```
|
54
70
|
|
55
71
|
or pass your rows in a block
|
56
72
|
|
57
73
|
```ruby
|
58
|
-
table = TTY::Table.new
|
74
|
+
table = TTY::Table.new do |t|
|
59
75
|
t << ['a1', 'a2', 'a3']
|
60
76
|
t << ['b1', 'b2', 'b3']
|
61
77
|
end
|
62
78
|
```
|
63
79
|
|
80
|
+
|
64
81
|
And then to print do
|
65
82
|
|
66
83
|
```ruby
|
data/lib/tty.rb
CHANGED
@@ -5,12 +5,16 @@ require 'tty/version'
|
|
5
5
|
require 'tty/support/utils'
|
6
6
|
require 'tty/support/delegatable'
|
7
7
|
require 'tty/support/conversion'
|
8
|
+
require 'tty/support/coercion'
|
8
9
|
|
9
10
|
require 'tty/color'
|
10
11
|
require 'tty/terminal'
|
11
12
|
require 'tty/system'
|
12
13
|
require 'tty/table'
|
13
14
|
|
15
|
+
require 'tty/table/operation/alignment_set'
|
16
|
+
require 'tty/table/operation/alignment'
|
17
|
+
|
14
18
|
module TTY
|
15
19
|
|
16
20
|
# Raised when the argument type is different from expected
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
# A mixin to coerce a value into a specific class.
|
5
|
+
module Coercion
|
6
|
+
|
7
|
+
# Helper to coerce value into a specific class.
|
8
|
+
#
|
9
|
+
# @param [Object] object
|
10
|
+
#
|
11
|
+
# @param [Class] cls
|
12
|
+
#
|
13
|
+
# @param [Symbol] method
|
14
|
+
#
|
15
|
+
# @api public
|
16
|
+
def coerce_to(object, cls, method)
|
17
|
+
return object if object.kind_of?(cls)
|
18
|
+
|
19
|
+
begin
|
20
|
+
result = object.__send__(method)
|
21
|
+
rescue Exception => e
|
22
|
+
raise TypeError, "Coercion error #{e.message}"
|
23
|
+
end
|
24
|
+
unless result.kind_of? cls
|
25
|
+
raise TypeError, "Coercion error: obj.#{method} did not return a #{cls} (was #{result.class})"
|
26
|
+
end
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
end # Coercion
|
31
|
+
end # TTY
|
data/lib/tty/table.rb
CHANGED
@@ -27,9 +27,8 @@ module TTY
|
|
27
27
|
private :rows
|
28
28
|
|
29
29
|
# Subset of safe methods that both Array and Hash implement
|
30
|
-
def_delegators(:@rows, :[], :assoc, :
|
31
|
-
:
|
32
|
-
:pretty_print, :rassoc)
|
30
|
+
def_delegators(:@rows, :[], :assoc, :flatten, :include?, :index,
|
31
|
+
:inspect, :length, :select, :to_a, :values_at, :pretty_print, :rassoc)
|
33
32
|
|
34
33
|
# The table orientation
|
35
34
|
#
|
@@ -49,6 +48,10 @@ module TTY
|
|
49
48
|
|
50
49
|
# Instantiate a new Table
|
51
50
|
#
|
51
|
+
# @example of no header
|
52
|
+
# rows = [ ['a1', 'a2'], ['b1', 'b2'] ]
|
53
|
+
# table = Table.new rows
|
54
|
+
#
|
52
55
|
# @example of direct parameters
|
53
56
|
# rows = [ ['a1', 'a2'], ['b1', 'b2'] ]
|
54
57
|
# table = Table.new ['Header 1', 'Header 2'], rows
|
@@ -62,9 +65,10 @@ module TTY
|
|
62
65
|
# @api public
|
63
66
|
def self.new(*args, &block)
|
64
67
|
options = Utils.extract_options!(args)
|
65
|
-
if args.
|
66
|
-
rows = args.
|
67
|
-
|
68
|
+
if args.size.nonzero?
|
69
|
+
rows = args.pop
|
70
|
+
header = args.size.zero? ? nil : args.first
|
71
|
+
super({:header => header, :rows => rows}.merge(options), &block)
|
68
72
|
else
|
69
73
|
super(options, &block)
|
70
74
|
end
|
@@ -80,14 +84,20 @@ module TTY
|
|
80
84
|
# Array of Arrays expressin the rows
|
81
85
|
# @option options [String] :renderer
|
82
86
|
# used to format table output
|
87
|
+
# @option options [String] :alignments
|
88
|
+
# used to format table individual column alignment
|
89
|
+
# @option options [String] :column_widths
|
90
|
+
# used to format table individula column width
|
83
91
|
#
|
84
92
|
# @return [Table]
|
85
93
|
#
|
86
94
|
# @api private
|
87
95
|
def initialize(options={}, &block)
|
88
|
-
@header
|
89
|
-
@rows
|
90
|
-
@renderer
|
96
|
+
@header = options.fetch :header, []
|
97
|
+
@rows = coerce(options.fetch :rows, [])
|
98
|
+
@renderer = pick_renderer options[:renderer]
|
99
|
+
@column_aligns = options.fetch :column_aligns, []
|
100
|
+
@column_widths = options.fetch :column_widths, []
|
91
101
|
assert_row_sizes @rows
|
92
102
|
yield_or_eval &block if block_given?
|
93
103
|
end
|
@@ -241,6 +251,16 @@ module TTY
|
|
241
251
|
total_width
|
242
252
|
end
|
243
253
|
|
254
|
+
# Return true if this is an empty table, i.e. if the number of
|
255
|
+
# rows or the number of columns is 0
|
256
|
+
#
|
257
|
+
# @return [Boolean]
|
258
|
+
#
|
259
|
+
# @api public
|
260
|
+
def empty?
|
261
|
+
column_size == 0 || row_size == 0
|
262
|
+
end
|
263
|
+
|
244
264
|
# Compare this table with other table for equality
|
245
265
|
#
|
246
266
|
# @param [TTY::Table] other
|
@@ -272,7 +292,8 @@ module TTY
|
|
272
292
|
#
|
273
293
|
# @api public
|
274
294
|
def to_s
|
275
|
-
render(rows
|
295
|
+
render(rows, :column_widths => @column_widths,
|
296
|
+
:column_aligns => @column_aligns)
|
276
297
|
end
|
277
298
|
|
278
299
|
# Coerce an Enumerable into a Table
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module TTY
|
2
|
+
class Table
|
3
|
+
module Operation
|
4
|
+
class Alignment
|
5
|
+
include TTY::Coercion
|
6
|
+
|
7
|
+
LEFT = :left.freeze
|
8
|
+
|
9
|
+
RIGHT = :right.freeze
|
10
|
+
|
11
|
+
CENTER = :center.freeze
|
12
|
+
|
13
|
+
attr_reader :type
|
14
|
+
|
15
|
+
# Initialize an Alignment
|
16
|
+
#
|
17
|
+
# @return [self]
|
18
|
+
#
|
19
|
+
# @raise [TypeError]
|
20
|
+
# raise if the alignment is not supported type
|
21
|
+
#
|
22
|
+
# @api private
|
23
|
+
def initialize(type=nil)
|
24
|
+
@type = coerce_to((type || LEFT), Symbol, :to_sym)
|
25
|
+
assert_valid_type
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
# Assert the type is valid
|
30
|
+
#
|
31
|
+
# @return [undefined]
|
32
|
+
#
|
33
|
+
# @raise [TypeError]
|
34
|
+
# raise if the alignment is not supported type
|
35
|
+
#
|
36
|
+
# @api private
|
37
|
+
def assert_valid_type
|
38
|
+
unless supported.include? type
|
39
|
+
raise TypeError, "Alignment must be one of: #{supported.join(' ')}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# List supported alignment types
|
44
|
+
#
|
45
|
+
# @return [Array]
|
46
|
+
# valid alignments
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
def supported
|
50
|
+
[LEFT, RIGHT, CENTER]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Format cell with a given alignment
|
54
|
+
#
|
55
|
+
# @return [String] aligned
|
56
|
+
#
|
57
|
+
# @api public
|
58
|
+
def format(cell, column_width, space='')
|
59
|
+
case type
|
60
|
+
when :left
|
61
|
+
"%-#{column_width}s#{space}" % cell.to_s
|
62
|
+
when :right
|
63
|
+
"%#{column_width}s#{space}" % cell.to_s
|
64
|
+
when :center
|
65
|
+
chars = cell.to_s.chars.to_a
|
66
|
+
if column_width >= chars.size
|
67
|
+
right = ((pad_length = column_width - chars.length).to_f / 2).ceil
|
68
|
+
left = pad_length - right
|
69
|
+
[' ' * left, cell, ' ' * right].join
|
70
|
+
else
|
71
|
+
cell
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end # Alignment
|
77
|
+
end # Operation
|
78
|
+
end # Table
|
79
|
+
end # TTY
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
class Table
|
5
|
+
module Operation
|
6
|
+
class AlignmentSet
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
# Initialize an AlignmentSet
|
10
|
+
#
|
11
|
+
# @param [Array] alignments
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
def initialize(alignments = nil)
|
15
|
+
@alignments = alignments || []
|
16
|
+
end
|
17
|
+
|
18
|
+
# Iterate over each alignment in the set
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# alignment_set = AlignmentSet.new alignments
|
22
|
+
# alignment_set.each { |alignment| ... }
|
23
|
+
#
|
24
|
+
# @yield [alignment]
|
25
|
+
#
|
26
|
+
# @return [self]
|
27
|
+
#
|
28
|
+
# @api public
|
29
|
+
def each
|
30
|
+
return to_enum unless block_given?
|
31
|
+
to_ary.each { |alignment| yield alignment }
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
# Lookup an alignment by index
|
36
|
+
#
|
37
|
+
# @param [Integer]
|
38
|
+
#
|
39
|
+
# @return [Symbol] alignment
|
40
|
+
#
|
41
|
+
# @api public
|
42
|
+
def [](index)
|
43
|
+
@alignments.fetch(index) do |alignment_index|
|
44
|
+
:left
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return each alignment in an Array
|
49
|
+
#
|
50
|
+
# @return [Array]
|
51
|
+
#
|
52
|
+
# @api private
|
53
|
+
def alignments
|
54
|
+
map { |alignment| alignment }
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [Array]
|
58
|
+
#
|
59
|
+
# @api public
|
60
|
+
def to_ary
|
61
|
+
@alignments
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Array]
|
65
|
+
#
|
66
|
+
# @api public
|
67
|
+
def to_a
|
68
|
+
@alignments
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Boolean]
|
72
|
+
#
|
73
|
+
# @api public
|
74
|
+
def empty?
|
75
|
+
to_ary.empty?
|
76
|
+
end
|
77
|
+
|
78
|
+
# Align the supplied rows with the correct alignment
|
79
|
+
#
|
80
|
+
# @param [Array] rows
|
81
|
+
#
|
82
|
+
# @return [Array]
|
83
|
+
# the aligned rows
|
84
|
+
#
|
85
|
+
# @api private
|
86
|
+
def align_rows(rows, options={})
|
87
|
+
rows.map { |row| align_row(row, options) }
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# Align each cell in a row
|
93
|
+
#
|
94
|
+
# @param [Object] row
|
95
|
+
#
|
96
|
+
# @param [Hash] options
|
97
|
+
#
|
98
|
+
# @return [String]
|
99
|
+
#
|
100
|
+
# @api private
|
101
|
+
def align_row(row, options={})
|
102
|
+
line = ""
|
103
|
+
row.each_with_index do |cell, index|
|
104
|
+
column_width = options[:column_widths][index]
|
105
|
+
alignment = Alignment.new self[index]
|
106
|
+
|
107
|
+
if index == row.size - 1
|
108
|
+
line << alignment.format(cell, column_width)
|
109
|
+
else
|
110
|
+
line << alignment.format(cell, column_width, ' ')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
line
|
114
|
+
end
|
115
|
+
|
116
|
+
end # AlignmentSet
|
117
|
+
end # Operation
|
118
|
+
end # Table
|
119
|
+
end # TTY
|
@@ -11,8 +11,26 @@ module TTY
|
|
11
11
|
|
12
12
|
attr_reader :column_widths
|
13
13
|
|
14
|
+
attr_reader :column_aligns
|
15
|
+
|
16
|
+
# Return an array of table rows
|
17
|
+
#
|
18
|
+
# @return [Array[Array]]
|
19
|
+
#
|
20
|
+
# @api private
|
14
21
|
attr_reader :rows
|
22
|
+
private :rows
|
23
|
+
|
24
|
+
# Return an AlignmentSet object for processing alignments
|
25
|
+
#
|
26
|
+
# @return [AlignmentSet]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
attr_reader :alignment_set
|
30
|
+
private :alignment_set
|
15
31
|
|
32
|
+
# Initialize and setup a Renderer
|
33
|
+
#
|
16
34
|
# @param [Hash] options
|
17
35
|
# :indent - Indent the first column by indent value
|
18
36
|
# :padding - Pad out the row cell by padding value
|
@@ -20,11 +38,24 @@ module TTY
|
|
20
38
|
#
|
21
39
|
# @return [Table::Renderer::Basic]
|
22
40
|
def initialize(options={})
|
41
|
+
setup(options)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Setup attributes when Renderer is invoked
|
45
|
+
#
|
46
|
+
# @return [self]
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
def setup(options = {})
|
23
50
|
@padding = 0
|
24
51
|
@indent = options.fetch :indent, 0
|
25
|
-
|
52
|
+
# TODO: assert that row_size is the same as column widths & aligns
|
53
|
+
@column_widths = options.fetch :column_widths, []
|
26
54
|
@column_aligns = options.fetch :column_aligns, []
|
55
|
+
@alignment_set = TTY::Table::Operation::AlignmentSet.new column_aligns
|
56
|
+
self
|
27
57
|
end
|
58
|
+
private :setup
|
28
59
|
|
29
60
|
# Sets the output padding,
|
30
61
|
#
|
@@ -51,6 +82,7 @@ module TTY
|
|
51
82
|
# @api public
|
52
83
|
def render(rows, options={})
|
53
84
|
return if rows.empty?
|
85
|
+
setup(options)
|
54
86
|
# TODO: Decide about table orientation
|
55
87
|
@rows = rows
|
56
88
|
body = []
|
@@ -76,6 +108,7 @@ module TTY
|
|
76
108
|
#
|
77
109
|
# @api private
|
78
110
|
def extract_column_widths(rows)
|
111
|
+
return column_widths unless column_widths.empty?
|
79
112
|
# TODO: throw an error if too many columns as compared to terminal width
|
80
113
|
colcount = rows.max{ |a,b| a.size <=> b.size }.size
|
81
114
|
maximas = []
|
@@ -90,24 +123,13 @@ module TTY
|
|
90
123
|
@column_widths = maximas
|
91
124
|
end
|
92
125
|
|
93
|
-
#
|
126
|
+
# Format the rows
|
94
127
|
#
|
95
128
|
# @return [Arrays[String]]
|
96
129
|
#
|
97
130
|
# @api private
|
98
131
|
def render_rows
|
99
|
-
|
100
|
-
line = ""
|
101
|
-
row.each_with_index do |column, index|
|
102
|
-
column_width = column_widths[index]
|
103
|
-
if index == row.size - 1
|
104
|
-
line << "%-#{column_width}s" % column.to_s
|
105
|
-
else
|
106
|
-
line << "%-#{column_width}s " % column.to_s
|
107
|
-
end
|
108
|
-
end
|
109
|
-
line
|
110
|
-
end
|
132
|
+
alignment_set.align_rows rows, :column_widths => column_widths
|
111
133
|
end
|
112
134
|
|
113
135
|
end # Basic
|
data/lib/tty/version.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe TTY::Coercion do
|
6
|
+
let(:described_class) { Class.new { include TTY::Coercion } }
|
7
|
+
let(:object) { described_class.new }
|
8
|
+
let(:value) { [] }
|
9
|
+
let(:coercible) { [ value, Array, :to_a] }
|
10
|
+
|
11
|
+
subject { object.coerce_to( *coercible ) }
|
12
|
+
|
13
|
+
it { should == value }
|
14
|
+
|
15
|
+
context 'coerces into integer' do
|
16
|
+
let(:value) { '123' }
|
17
|
+
let(:coercible) { [ value, Integer, :to_i] }
|
18
|
+
|
19
|
+
it { should be_kind_of(Integer) }
|
20
|
+
|
21
|
+
it { should == value.to_i }
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'coerces into symbol' do
|
25
|
+
let(:value) { 'argument' }
|
26
|
+
let(:coercible) { [value, Symbol, :to_sym]}
|
27
|
+
|
28
|
+
it { should be_kind_of(Symbol) }
|
29
|
+
|
30
|
+
it { should == value.to_sym }
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'coerces into string' do
|
34
|
+
let(:value) { true }
|
35
|
+
let(:coercible) { [value, String, :to_s] }
|
36
|
+
|
37
|
+
it { should be_kind_of(String) }
|
38
|
+
|
39
|
+
it { should == value.to_s }
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe TTY::Table, '#empty?' do
|
6
|
+
let(:header) { ['Header1', 'Header2'] }
|
7
|
+
let(:object) { described_class.new header, rows }
|
8
|
+
|
9
|
+
subject { object.empty? }
|
10
|
+
|
11
|
+
context 'with rows containing no entries' do
|
12
|
+
let(:rows) { [] }
|
13
|
+
|
14
|
+
it { should be_true }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'with rows containing an entry' do
|
18
|
+
let(:rows) { [['a1']] }
|
19
|
+
|
20
|
+
it { should be_false }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -7,12 +7,13 @@ describe TTY::Table, '#initialize' do
|
|
7
7
|
let(:rows) { [['a1', 'a2'], ['b1', 'b2']] }
|
8
8
|
|
9
9
|
it { should be_kind_of(Enumerable) }
|
10
|
+
|
10
11
|
it { should be_kind_of(Comparable) }
|
11
12
|
|
12
13
|
it { (Enumerable === subject).should be_true }
|
13
14
|
|
14
15
|
it 'initializes table header' do
|
15
|
-
table = TTY::Table.new header
|
16
|
+
table = TTY::Table.new :header => header
|
16
17
|
table.header.should == header
|
17
18
|
end
|
18
19
|
|
@@ -22,7 +23,12 @@ describe TTY::Table, '#initialize' do
|
|
22
23
|
end
|
23
24
|
|
24
25
|
it 'initializes with rows as arguments' do
|
25
|
-
table = TTY::Table[
|
26
|
+
table = TTY::Table[*rows]
|
27
|
+
table.to_a.should == rows
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'initializes ' do
|
31
|
+
table = TTY::Table.new rows
|
26
32
|
table.to_a.should == rows
|
27
33
|
end
|
28
34
|
|
@@ -37,7 +43,7 @@ describe TTY::Table, '#initialize' do
|
|
37
43
|
end
|
38
44
|
|
39
45
|
it 'initializes table rows in a block with param' do
|
40
|
-
table = TTY::Table.new
|
46
|
+
table = TTY::Table.new do |t|
|
41
47
|
t << rows[0]
|
42
48
|
t << rows[1]
|
43
49
|
end
|
@@ -45,9 +51,14 @@ describe TTY::Table, '#initialize' do
|
|
45
51
|
end
|
46
52
|
|
47
53
|
it 'initializes table and adds rows' do
|
48
|
-
table = TTY::Table.new
|
54
|
+
table = TTY::Table.new
|
49
55
|
table << rows[0]
|
50
56
|
table << rows[1]
|
51
57
|
table.to_a.should == rows
|
52
58
|
end
|
59
|
+
|
60
|
+
it 'converts row arguments from hash to array' do
|
61
|
+
table = TTY::Table.new :rows => {:a => 1, :b => 2}
|
62
|
+
table.to_a.should include [:a, 1 ]
|
63
|
+
end
|
53
64
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe TTY::Table::Operation::Alignment, '#new' do
|
6
|
+
let(:object) { described_class.new alignment }
|
7
|
+
let(:cell) { "aaaa"}
|
8
|
+
let(:column_width) { 8 }
|
9
|
+
|
10
|
+
subject { object.format cell, column_width }
|
11
|
+
|
12
|
+
shared_examples_for 'lower column width' do
|
13
|
+
let(:column_width) { 2 }
|
14
|
+
|
15
|
+
it { should == cell }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'left aligend' do
|
19
|
+
let(:alignment) { :left }
|
20
|
+
|
21
|
+
it { should == cell + ' ' }
|
22
|
+
|
23
|
+
it_should_behave_like 'lower column width'
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'center aligned' do
|
27
|
+
let(:alignment) { :center }
|
28
|
+
|
29
|
+
it { should == ' ' + cell + ' ' }
|
30
|
+
|
31
|
+
it_should_behave_like 'lower column width'
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'right aligned' do
|
35
|
+
let(:alignment) { :right }
|
36
|
+
|
37
|
+
it_should_behave_like 'lower column width'
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe TTY::Table::Operation::Alignment, '#new' do
|
6
|
+
let(:object) { described_class }
|
7
|
+
|
8
|
+
subject { object.new(type) }
|
9
|
+
|
10
|
+
context 'with no type' do
|
11
|
+
let(:type) { nil }
|
12
|
+
|
13
|
+
it { should be_instance_of(object) }
|
14
|
+
|
15
|
+
its(:type) { should == :left }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with unrecognized type' do
|
19
|
+
let(:type) { :unknown }
|
20
|
+
|
21
|
+
it 'raises exception' do
|
22
|
+
expect { subject }.to raise_error(TTY::TypeError)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with coerced type' do
|
27
|
+
let(:type) { 'center' }
|
28
|
+
|
29
|
+
its(:type) { should == :center }
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe TTY::Table::Operation::AlignmentSet, '#align_rows' do
|
6
|
+
let(:object) { described_class.new alignments }
|
7
|
+
let(:rows) { [['a1', 'a2'], ['b1', 'b2']] }
|
8
|
+
|
9
|
+
subject { object.align_rows rows, :column_widths => widths }
|
10
|
+
|
11
|
+
context 'aligned with column widths and no alignments' do
|
12
|
+
let(:alignments) { [] }
|
13
|
+
let(:widths) { [4, 4] }
|
14
|
+
|
15
|
+
it { should be_instance_of(Array) }
|
16
|
+
|
17
|
+
it { should == ['a1 a2 ', 'b1 b2 '] }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'aligned with column widths and alignments' do
|
21
|
+
let(:alignments) { [:right, :left] }
|
22
|
+
let(:widths) { [4, 4] }
|
23
|
+
|
24
|
+
it { should be_instance_of(Array) }
|
25
|
+
|
26
|
+
it { should == [' a1 a2 ', ' b1 b2 '] }
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'aligned with no column widths and no alignments' do
|
30
|
+
let(:alignments) { [] }
|
31
|
+
let(:widths) { [] }
|
32
|
+
|
33
|
+
it { should be_instance_of(Array) }
|
34
|
+
|
35
|
+
it { should == ['a1 a2', 'b1 b2'] }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'aligned with no column widths and alignments' do
|
39
|
+
let(:alignments) { [:right, :left] }
|
40
|
+
let(:widths) { [] }
|
41
|
+
|
42
|
+
it { should be_instance_of(Array) }
|
43
|
+
|
44
|
+
it { should == ['a1 a2', 'b1 b2'] }
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe TTY::Table::Operation::AlignmentSet, '#each' do
|
6
|
+
let(:alignments) { [:left, :center, :right] }
|
7
|
+
let(:yields) { [] }
|
8
|
+
let(:object) { described_class.new alignments }
|
9
|
+
|
10
|
+
subject { object.each { |alignment| yields << alignment } }
|
11
|
+
|
12
|
+
it 'yields each alignment' do
|
13
|
+
expect { subject }.to change { yields.dup }.
|
14
|
+
from([]).
|
15
|
+
to(alignments)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe TTY::Table::Operation::AlignmentSet, '#new' do
|
6
|
+
let(:object) { described_class }
|
7
|
+
|
8
|
+
subject { object.new(argument) }
|
9
|
+
|
10
|
+
context 'with no argument' do
|
11
|
+
let(:argument) { nil }
|
12
|
+
|
13
|
+
it { should be_kind_of(Enumerable) }
|
14
|
+
|
15
|
+
it { should be_instance_of(object) }
|
16
|
+
|
17
|
+
its(:alignments) { should == [] }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with argument' do
|
21
|
+
let(:argument) { [:center, :left] }
|
22
|
+
|
23
|
+
it { should be_instance_of(object) }
|
24
|
+
|
25
|
+
its(:alignments) { should == argument }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe TTY::Table::Operation::AlignmentSet, '#to_ary' do
|
6
|
+
let(:argument) { [:center, :left] }
|
7
|
+
let(:object) { described_class.new argument }
|
8
|
+
|
9
|
+
subject { object.to_ary }
|
10
|
+
|
11
|
+
it { should be_instance_of(Array) }
|
12
|
+
|
13
|
+
it { should == argument }
|
14
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe TTY::Table, 'options' do
|
6
|
+
let(:rows) { [['a1', 'a2'], ['b1', 'b2']] }
|
7
|
+
let(:widths) { [] }
|
8
|
+
let(:aligns) { [] }
|
9
|
+
let(:object) {
|
10
|
+
described_class.new rows,
|
11
|
+
:column_widths => widths,
|
12
|
+
:column_aligns => aligns,
|
13
|
+
:renderer => :basic
|
14
|
+
}
|
15
|
+
|
16
|
+
subject { object.to_s; object.renderer }
|
17
|
+
|
18
|
+
its(:column_widths) { should == [2,2] }
|
19
|
+
|
20
|
+
its(:column_aligns) { should == [] }
|
21
|
+
|
22
|
+
context '#column_widths' do
|
23
|
+
let(:widths) { [10, 10] }
|
24
|
+
|
25
|
+
its(:column_widths) { should == widths }
|
26
|
+
end
|
27
|
+
|
28
|
+
context '#column_aligns' do
|
29
|
+
let(:aligns) { [:center, :center] }
|
30
|
+
|
31
|
+
its(:column_aligns) { should == aligns }
|
32
|
+
end
|
33
|
+
end
|
@@ -20,7 +20,7 @@ describe TTY::Table::Renderer::Basic do
|
|
20
20
|
|
21
21
|
context '#render' do
|
22
22
|
it 'displays table without styling' do
|
23
|
-
table = TTY::Table.new header, :renderer => :basic
|
23
|
+
table = TTY::Table.new :header => header, :renderer => :basic
|
24
24
|
table << rows[0]
|
25
25
|
table << rows[1]
|
26
26
|
table.to_s.should == <<-EOS.normalize
|
@@ -38,4 +38,27 @@ describe TTY::Table::Renderer::Basic do
|
|
38
38
|
EOS
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
context 'alignment' do
|
43
|
+
it 'aligns left by default' do
|
44
|
+
rows = [['aaaaa', 'a'], ['b', 'bbbbb']]
|
45
|
+
table = TTY::Table.new header, rows, :renderer => :basic
|
46
|
+
table.to_s.should == <<-EOS.normalize
|
47
|
+
aaaaa a
|
48
|
+
b bbbbb
|
49
|
+
EOS
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'aligns table elements' do
|
53
|
+
rows = [['aaaaa', 'a'], ['b', 'bbbbb']]
|
54
|
+
table = TTY::Table.new header, rows, :renderer => :basic,
|
55
|
+
:column_aligns => [:left, :right]
|
56
|
+
table.to_s.should == <<-EOS.normalize
|
57
|
+
aaaaa a
|
58
|
+
b bbbbb
|
59
|
+
EOS
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
41
64
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &2152236620 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2152236620
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &2152236180 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2152236180
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: yard
|
38
|
-
requirement: &
|
38
|
+
requirement: &2152235740 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2152235740
|
47
47
|
description: Toolbox for developing CLI clients
|
48
48
|
email:
|
49
49
|
- ''
|
@@ -62,12 +62,15 @@ files:
|
|
62
62
|
- Rakefile
|
63
63
|
- lib/tty.rb
|
64
64
|
- lib/tty/color.rb
|
65
|
+
- lib/tty/support/coercion.rb
|
65
66
|
- lib/tty/support/conversion.rb
|
66
67
|
- lib/tty/support/delegatable.rb
|
67
68
|
- lib/tty/support/utils.rb
|
68
69
|
- lib/tty/system.rb
|
69
70
|
- lib/tty/table.rb
|
70
71
|
- lib/tty/table/error.rb
|
72
|
+
- lib/tty/table/operation/alignment.rb
|
73
|
+
- lib/tty/table/operation/alignment_set.rb
|
71
74
|
- lib/tty/table/renderer.rb
|
72
75
|
- lib/tty/table/renderer/basic.rb
|
73
76
|
- lib/tty/table/renderer/color.rb
|
@@ -77,14 +80,23 @@ files:
|
|
77
80
|
- lib/tty/version.rb
|
78
81
|
- spec/spec_helper.rb
|
79
82
|
- spec/tty/color_spec.rb
|
83
|
+
- spec/tty/support/coercion_spec.rb
|
80
84
|
- spec/tty/support/conversion_spec.rb
|
81
85
|
- spec/tty/support/delegatable_spec.rb
|
82
86
|
- spec/tty/support/fixtures/classes.rb
|
83
87
|
- spec/tty/system/platform_spec.rb
|
84
88
|
- spec/tty/table/access_spec.rb
|
85
89
|
- spec/tty/table/each_spec.rb
|
90
|
+
- spec/tty/table/empty_spec.rb
|
86
91
|
- spec/tty/table/eql_spec.rb
|
87
92
|
- spec/tty/table/initialize_spec.rb
|
93
|
+
- spec/tty/table/operation/alignment/format_spec.rb
|
94
|
+
- spec/tty/table/operation/alignment/new_spec.rb
|
95
|
+
- spec/tty/table/operation/alignment_set/align_rows_spec.rb
|
96
|
+
- spec/tty/table/operation/alignment_set/each_spec.rb
|
97
|
+
- spec/tty/table/operation/alignment_set/new_spec.rb
|
98
|
+
- spec/tty/table/operation/alignment_set/to_ary_spec.rb
|
99
|
+
- spec/tty/table/options_spec.rb
|
88
100
|
- spec/tty/table/properties_spec.rb
|
89
101
|
- spec/tty/table/renderer/basic_spec.rb
|
90
102
|
- spec/tty/table/renderer_spec.rb
|
@@ -118,14 +130,23 @@ summary: Toolbox for developing CLI clients
|
|
118
130
|
test_files:
|
119
131
|
- spec/spec_helper.rb
|
120
132
|
- spec/tty/color_spec.rb
|
133
|
+
- spec/tty/support/coercion_spec.rb
|
121
134
|
- spec/tty/support/conversion_spec.rb
|
122
135
|
- spec/tty/support/delegatable_spec.rb
|
123
136
|
- spec/tty/support/fixtures/classes.rb
|
124
137
|
- spec/tty/system/platform_spec.rb
|
125
138
|
- spec/tty/table/access_spec.rb
|
126
139
|
- spec/tty/table/each_spec.rb
|
140
|
+
- spec/tty/table/empty_spec.rb
|
127
141
|
- spec/tty/table/eql_spec.rb
|
128
142
|
- spec/tty/table/initialize_spec.rb
|
143
|
+
- spec/tty/table/operation/alignment/format_spec.rb
|
144
|
+
- spec/tty/table/operation/alignment/new_spec.rb
|
145
|
+
- spec/tty/table/operation/alignment_set/align_rows_spec.rb
|
146
|
+
- spec/tty/table/operation/alignment_set/each_spec.rb
|
147
|
+
- spec/tty/table/operation/alignment_set/new_spec.rb
|
148
|
+
- spec/tty/table/operation/alignment_set/to_ary_spec.rb
|
149
|
+
- spec/tty/table/options_spec.rb
|
129
150
|
- spec/tty/table/properties_spec.rb
|
130
151
|
- spec/tty/table/renderer/basic_spec.rb
|
131
152
|
- spec/tty/table/renderer_spec.rb
|