tty 0.0.4 → 0.0.5
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 +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
|