tty 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/README.md +19 -7
- data/lib/tty.rb +10 -0
- data/lib/tty/support/equatable.rb +1 -0
- data/lib/tty/support/unicode.rb +36 -0
- data/lib/tty/table.rb +3 -3
- data/lib/tty/table/border.rb +104 -0
- data/lib/tty/table/border/ascii.rb +41 -0
- data/lib/tty/table/border/null.rb +49 -0
- data/lib/tty/table/border/unicode.rb +41 -0
- data/lib/tty/table/column_set.rb +77 -0
- data/lib/tty/table/operation/alignment.rb +2 -0
- data/lib/tty/table/operation/alignment_set.rb +4 -58
- data/lib/tty/table/operation/truncation.rb +15 -19
- data/lib/tty/table/operation/wrapped.rb +34 -0
- data/lib/tty/table/renderer.rb +8 -11
- data/lib/tty/table/renderer/ascii.rb +15 -0
- data/lib/tty/table/renderer/basic.rb +21 -34
- data/lib/tty/table/renderer/unicode.rb +2 -2
- data/lib/tty/vector.rb +117 -0
- data/lib/tty/version.rb +1 -1
- data/spec/tty/table/border/ascii/rendering_spec.rb +49 -0
- data/spec/tty/table/border/new_spec.rb +21 -0
- data/spec/tty/table/border/null/rendering_spec.rb +49 -0
- data/spec/tty/table/border/unicode/rendering_spec.rb +49 -0
- data/spec/tty/table/column_set/extract_widths_spec.rb +26 -0
- data/spec/tty/table/operation/alignment_set/align_rows_spec.rb +4 -4
- data/spec/tty/table/operation/alignment_set/new_spec.rb +1 -1
- data/spec/tty/table/operation/wrapped/wrap_spec.rb +22 -0
- data/spec/tty/table/properties_spec.rb +3 -0
- data/spec/tty/table/renderer/basic/render_spec.rb +144 -33
- data/spec/tty/table/renderer/pick_renderer_spec.rb +25 -0
- data/spec/tty/table/to_s_spec.rb +51 -0
- data/spec/tty/vector/new_spec.rb +47 -0
- metadata +35 -8
@@ -5,34 +5,7 @@ module TTY
|
|
5
5
|
module Operation
|
6
6
|
|
7
7
|
# A class which responsiblity is to align table rows and header.
|
8
|
-
class AlignmentSet
|
9
|
-
include Enumerable
|
10
|
-
|
11
|
-
# Initialize an AlignmentSet
|
12
|
-
#
|
13
|
-
# @param [Array] alignments
|
14
|
-
#
|
15
|
-
# @api public
|
16
|
-
def initialize(alignments = nil)
|
17
|
-
@alignments = alignments || []
|
18
|
-
end
|
19
|
-
|
20
|
-
# Iterate over each alignment in the set
|
21
|
-
#
|
22
|
-
# @example
|
23
|
-
# alignment_set = AlignmentSet.new alignments
|
24
|
-
# alignment_set.each { |alignment| ... }
|
25
|
-
#
|
26
|
-
# @yield [alignment]
|
27
|
-
#
|
28
|
-
# @return [self]
|
29
|
-
#
|
30
|
-
# @api public
|
31
|
-
def each
|
32
|
-
return to_enum unless block_given?
|
33
|
-
to_ary.each { |alignment| yield alignment }
|
34
|
-
self
|
35
|
-
end
|
8
|
+
class AlignmentSet < Vector
|
36
9
|
|
37
10
|
# Lookup an alignment by index
|
38
11
|
#
|
@@ -42,9 +15,7 @@ module TTY
|
|
42
15
|
#
|
43
16
|
# @api public
|
44
17
|
def [](index)
|
45
|
-
|
46
|
-
:left
|
47
|
-
end
|
18
|
+
elements.fetch(index, :left)
|
48
19
|
end
|
49
20
|
|
50
21
|
# Return each alignment in an Array
|
@@ -56,28 +27,7 @@ module TTY
|
|
56
27
|
map { |alignment| alignment }
|
57
28
|
end
|
58
29
|
|
59
|
-
#
|
60
|
-
#
|
61
|
-
# @api public
|
62
|
-
def to_ary
|
63
|
-
@alignments
|
64
|
-
end
|
65
|
-
|
66
|
-
# @return [Array[Alignment]]
|
67
|
-
#
|
68
|
-
# @api public
|
69
|
-
def to_a
|
70
|
-
@alignments
|
71
|
-
end
|
72
|
-
|
73
|
-
# @return [Boolean]
|
74
|
-
#
|
75
|
-
# @api public
|
76
|
-
def empty?
|
77
|
-
to_ary.empty?
|
78
|
-
end
|
79
|
-
|
80
|
-
# Aligns table header
|
30
|
+
# Align table header
|
81
31
|
#
|
82
32
|
# @return [Array[String]]
|
83
33
|
#
|
@@ -115,11 +65,7 @@ module TTY
|
|
115
65
|
column_width = options[:column_widths][index]
|
116
66
|
alignment = Alignment.new self[index]
|
117
67
|
|
118
|
-
|
119
|
-
line << alignment.format(cell, column_width)
|
120
|
-
else
|
121
|
-
line << alignment.format(cell, column_width, ' ')
|
122
|
-
end
|
68
|
+
line << alignment.format(cell, column_width)
|
123
69
|
end
|
124
70
|
line
|
125
71
|
end
|
@@ -6,36 +6,32 @@ module TTY
|
|
6
6
|
|
7
7
|
# A class responsible for shortening text.
|
8
8
|
class Truncation
|
9
|
+
include Unicode
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
# Shorten given string with traling character.
|
12
|
+
#
|
13
|
+
# @param [String] string
|
14
|
+
# the string to truncate
|
15
|
+
# @param [Integer] width
|
16
|
+
# the maximum width
|
17
|
+
# @param [String] trailing
|
18
|
+
# the trailing character
|
19
|
+
#
|
20
|
+
# @return [String]
|
21
|
+
#
|
22
|
+
# @api public
|
23
|
+
def truncate(string, width, trailing = '…')
|
13
24
|
as_unicode do
|
14
25
|
chars = string.chars.to_a
|
15
|
-
print 'CHARS '
|
16
|
-
p chars
|
17
26
|
if chars.length < width
|
18
27
|
chars.join
|
19
28
|
else
|
20
29
|
traling_size = trailing.chars.to_a.size
|
21
|
-
( chars[0, width-traling_size].join ) + trailing
|
30
|
+
( chars[0, width - traling_size].join ) + trailing
|
22
31
|
end
|
23
32
|
end
|
24
33
|
end
|
25
34
|
|
26
|
-
if "".respond_to?(:encode)
|
27
|
-
def as_unicode
|
28
|
-
yield
|
29
|
-
end
|
30
|
-
else
|
31
|
-
def as_unicode
|
32
|
-
old, $KCODE = $KCODE, "U"
|
33
|
-
yield
|
34
|
-
ensure
|
35
|
-
$KCODE = old
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
35
|
end # Truncation
|
40
36
|
end # Operation
|
41
37
|
end # Table
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
class Table
|
5
|
+
module Operation
|
6
|
+
|
7
|
+
# A class responsible for wrapping text.
|
8
|
+
class Wrapped
|
9
|
+
include Unicode
|
10
|
+
|
11
|
+
# Wrap a long string according to the width.
|
12
|
+
#
|
13
|
+
# @param [String] string
|
14
|
+
# the string to wrap
|
15
|
+
# @param [Integer] width
|
16
|
+
# the maximum width
|
17
|
+
# @param [Boolean] addnewline
|
18
|
+
# add new line add the end
|
19
|
+
#
|
20
|
+
# @api public
|
21
|
+
def wrap(string, width)
|
22
|
+
as_unicode do
|
23
|
+
chars = string.chars.to_a
|
24
|
+
return string if chars.length <= width
|
25
|
+
idx = width
|
26
|
+
return chars[0, idx].join + "\n" + wrap(chars[idx..-1].join, width)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end # Wrapped
|
31
|
+
end # Operation
|
32
|
+
end # Table
|
33
|
+
end # TTY
|
34
|
+
|
data/lib/tty/table/renderer.rb
CHANGED
@@ -29,13 +29,15 @@ module TTY
|
|
29
29
|
module Renderer
|
30
30
|
extend TTY::Delegatable
|
31
31
|
|
32
|
+
autoload :ASCII, 'tty/table/renderer/ascii'
|
32
33
|
autoload :Basic, 'tty/table/renderer/basic'
|
33
34
|
autoload :Color, 'tty/table/renderer/color'
|
34
35
|
autoload :Unicode, 'tty/table/renderer/unicode'
|
35
36
|
|
36
|
-
RENDERER_DELEGATED_METHODS = [ :render, :
|
37
|
+
RENDERER_DELEGATED_METHODS = [ :render, :total_width]
|
37
38
|
|
38
39
|
RENDERER_MAPPER = {
|
40
|
+
:ascii => TTY::Table::Renderer::ASCII,
|
39
41
|
:basic => TTY::Table::Renderer::Basic,
|
40
42
|
:color => TTY::Table::Renderer::Color,
|
41
43
|
:unicode => TTY::Table::Renderer::Unicode
|
@@ -45,24 +47,19 @@ module TTY
|
|
45
47
|
#
|
46
48
|
# @api private
|
47
49
|
def initialize(options={})
|
48
|
-
super
|
49
|
-
self.renderer = RENDERER_MAPPER[:"#{options[:renderer]}"].new
|
50
|
+
super()
|
50
51
|
end
|
51
52
|
|
52
53
|
# Determine renderer class based on string name
|
53
54
|
#
|
54
|
-
# @param [
|
55
|
-
# the renderer used for displaying table
|
55
|
+
# @param [Symbol] renderer
|
56
|
+
# the renderer used for displaying table out of [:basic, :color, :unicode]
|
56
57
|
#
|
57
58
|
# @return [TTY::Table::Renderer]
|
58
59
|
#
|
59
60
|
# @api private
|
60
|
-
def pick_renderer(
|
61
|
-
|
62
|
-
RENDERER_MAPPER[renderer].new
|
63
|
-
else
|
64
|
-
self.renderer
|
65
|
-
end
|
61
|
+
def pick_renderer(type=nil)
|
62
|
+
type ? RENDERER_MAPPER[type].new : self.renderer
|
66
63
|
end
|
67
64
|
|
68
65
|
# Return the default renderer
|
@@ -19,6 +19,14 @@ module TTY
|
|
19
19
|
# @api public
|
20
20
|
attr_reader :table
|
21
21
|
|
22
|
+
|
23
|
+
# Table border to be rendered
|
24
|
+
#
|
25
|
+
# @return [TTY::Table::Border]
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
attr_reader :border_class
|
29
|
+
|
22
30
|
TABLE_DELEGATED_METHODS = [:column_widths, :alignments]
|
23
31
|
|
24
32
|
delegatable_method :table, *TABLE_DELEGATED_METHODS
|
@@ -77,13 +85,15 @@ module TTY
|
|
77
85
|
# @return [String] string representation of table
|
78
86
|
#
|
79
87
|
# @api public
|
80
|
-
def render(table)
|
88
|
+
def render(table, border_class=Border::Null)
|
81
89
|
@table = table
|
90
|
+
@border_class = border_class
|
91
|
+
|
82
92
|
return if table.to_a.empty?
|
83
93
|
# setup(options)
|
84
94
|
body = []
|
85
95
|
unless table.length.zero?
|
86
|
-
|
96
|
+
ColumnSet.new(table).extract_widths!
|
87
97
|
# TODO: throw an error if too many columns as compared to terminal width
|
88
98
|
# and then change table.orientation from vertical to horizontal
|
89
99
|
# TODO: Decide about table orientation
|
@@ -94,38 +104,8 @@ module TTY
|
|
94
104
|
body.compact.join("\n")
|
95
105
|
end
|
96
106
|
|
97
|
-
# Calcualte total table width
|
98
|
-
#
|
99
|
-
# @return [Integer]
|
100
|
-
#
|
101
|
-
# @api public
|
102
|
-
def total_width
|
103
|
-
column_widths.reduce(:+)
|
104
|
-
end
|
105
|
-
|
106
107
|
private
|
107
108
|
|
108
|
-
# Calcualte maximum column widths
|
109
|
-
#
|
110
|
-
# @return [Array] column widths
|
111
|
-
#
|
112
|
-
# @api private
|
113
|
-
def extract_column_widths
|
114
|
-
return column_widths unless column_widths.empty?
|
115
|
-
data = table.header ? table.to_a + [table.header] : table.to_a
|
116
|
-
colcount = data.max{ |a,b| a.size <=> b.size }.size
|
117
|
-
maximas = []
|
118
|
-
start = 0
|
119
|
-
|
120
|
-
start.upto(colcount - 1) do |index|
|
121
|
-
maximum = data.map { |row|
|
122
|
-
row[index] ? (row[index].to_s.size) : 0
|
123
|
-
}.max
|
124
|
-
maximas << maximum
|
125
|
-
end
|
126
|
-
table.column_widths = maximas
|
127
|
-
end
|
128
|
-
|
129
109
|
# Format the header
|
130
110
|
#
|
131
111
|
# @return [Array[String]]
|
@@ -136,7 +116,8 @@ module TTY
|
|
136
116
|
if header
|
137
117
|
aligned = alignments.align_header header,
|
138
118
|
:column_widths => column_widths
|
139
|
-
|
119
|
+
border = border_class.new(aligned)
|
120
|
+
[border.top_line, border.row_line].compact
|
140
121
|
else
|
141
122
|
[]
|
142
123
|
end
|
@@ -150,7 +131,13 @@ module TTY
|
|
150
131
|
def render_rows
|
151
132
|
aligned = alignments.align_rows table.to_a,
|
152
133
|
:column_widths => column_widths
|
153
|
-
|
134
|
+
|
135
|
+
first_row_border = border_class.new(aligned.first)
|
136
|
+
aligned_border = aligned.map { |row| border_class.new(row).row_line }
|
137
|
+
|
138
|
+
[ table.header ? first_row_border.separator : first_row_border.top_line,
|
139
|
+
aligned_border,
|
140
|
+
first_row_border.bottom_line ].compact
|
154
141
|
end
|
155
142
|
|
156
143
|
end # Basic
|
data/lib/tty/vector.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
|
5
|
+
# This class represents a mathematical vector.
|
6
|
+
class Vector
|
7
|
+
include Enumerable, Equatable, Conversion
|
8
|
+
|
9
|
+
attr_reader :elements
|
10
|
+
protected :elements
|
11
|
+
|
12
|
+
# Utility method to instantiate a Vector
|
13
|
+
#
|
14
|
+
# @param [Array] *array
|
15
|
+
#
|
16
|
+
# @return [Vector]
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
def self.[](*array)
|
20
|
+
new convert_to_array(array)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Instantiate a Vector
|
24
|
+
#
|
25
|
+
# @param [Array] array
|
26
|
+
#
|
27
|
+
# @return [undefined]
|
28
|
+
#
|
29
|
+
# @api public
|
30
|
+
def initialize(array=[])
|
31
|
+
@elements = convert_to_array(array)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Return element at index.
|
35
|
+
#
|
36
|
+
# @param [Integer] indx
|
37
|
+
# index of an element
|
38
|
+
#
|
39
|
+
# @return [Object]
|
40
|
+
# a value of an element
|
41
|
+
#
|
42
|
+
# @api public
|
43
|
+
def [](indx)
|
44
|
+
elements[i]
|
45
|
+
end
|
46
|
+
alias at []
|
47
|
+
alias element []
|
48
|
+
|
49
|
+
# Set a value of the element for the given index.
|
50
|
+
#
|
51
|
+
# @param [Integer] indx
|
52
|
+
# an index of an element
|
53
|
+
#
|
54
|
+
# @param [Object] value
|
55
|
+
# a value to be set
|
56
|
+
#
|
57
|
+
# @return [Object]
|
58
|
+
#
|
59
|
+
# @api public
|
60
|
+
def []=(indx, value)
|
61
|
+
elements[index] = value
|
62
|
+
end
|
63
|
+
alias set_element []=
|
64
|
+
|
65
|
+
# Iterate over each element in the vector
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# vec = Vector[1,2,3]
|
69
|
+
# vec.each { |element| ... }
|
70
|
+
#
|
71
|
+
# @return [self]
|
72
|
+
#
|
73
|
+
# @api public
|
74
|
+
def each(&block)
|
75
|
+
return to_enum(:each) unless block_given?
|
76
|
+
to_ary.each(&block)
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
# Convert to array
|
81
|
+
#
|
82
|
+
# @return [Array]
|
83
|
+
#
|
84
|
+
# @api public
|
85
|
+
def to_ary
|
86
|
+
elements
|
87
|
+
end
|
88
|
+
|
89
|
+
# Check if there are not elements.
|
90
|
+
#
|
91
|
+
# @return [Boolean]
|
92
|
+
#
|
93
|
+
# @api public
|
94
|
+
def empty?
|
95
|
+
to_ary.empty?
|
96
|
+
end
|
97
|
+
|
98
|
+
# Check number of elements.
|
99
|
+
#
|
100
|
+
# @return [Integer]
|
101
|
+
#
|
102
|
+
# @api public
|
103
|
+
def size
|
104
|
+
to_ary.size
|
105
|
+
end
|
106
|
+
|
107
|
+
# Return the vector elements in an array.
|
108
|
+
#
|
109
|
+
# @return [Array]
|
110
|
+
#
|
111
|
+
# @api public
|
112
|
+
def to_a
|
113
|
+
elements.dup
|
114
|
+
end
|
115
|
+
|
116
|
+
end # Vector
|
117
|
+
end # TTY
|