dashes 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.md +23 -0
- data/README.md +87 -0
- data/lib/dashes.rb +260 -0
- data/test/dashes_test.rb +332 -0
- metadata +65 -0
data/LICENSE.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2012, Hugh Bien
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
Redistributions of source code must retain the above copyright notice, this list
|
8
|
+
of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
Redistributions in binary form must reproduce the above copyright notice, this
|
11
|
+
list of conditions and the following disclaimer in the documentation and/or
|
12
|
+
other materials provided with the distribution.
|
13
|
+
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
15
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
16
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
17
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
18
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
19
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
20
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
21
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
22
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
23
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
Description
|
2
|
+
===========
|
3
|
+
|
4
|
+
Dashline formats data into a dashboard of charts/tables on the command line.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
============
|
8
|
+
|
9
|
+
$ gem install dashline
|
10
|
+
|
11
|
+
Usage
|
12
|
+
=====
|
13
|
+
|
14
|
+
Making a table:
|
15
|
+
|
16
|
+
> table = Dashline::Table.new
|
17
|
+
> table.align :left, :right, :right # :center is available too
|
18
|
+
> table.row 'Label', 'Num', 'Pct'
|
19
|
+
> table.separator
|
20
|
+
> table.row 'First', 1, 2
|
21
|
+
> table.row 'Second', 3, 4
|
22
|
+
> puts table.to_s
|
23
|
+
+--------+-----+-----+
|
24
|
+
| Label | Num | Pct |
|
25
|
+
+--------+-----+-----+
|
26
|
+
| First | 1 | 2 |
|
27
|
+
| Second | 3 | 4 |
|
28
|
+
+--------+-----+-----+
|
29
|
+
|
30
|
+
Some display options for tables:
|
31
|
+
|
32
|
+
table.width(integer)
|
33
|
+
table.max_width(integer) # width takes priority
|
34
|
+
table.align(*alignments) # :left, :center, or :right
|
35
|
+
table.spacing(*spaces) # :min or :max, :min means never pad the cell
|
36
|
+
|
37
|
+
Making a chart:
|
38
|
+
|
39
|
+
> chart = Dashline::Chart.new
|
40
|
+
> chart.title 'Title'
|
41
|
+
> chart.row 'First', 7
|
42
|
+
> chart.row 'Second', 12
|
43
|
+
> chart.row 'Third', 2
|
44
|
+
> puts chart.to_s
|
45
|
+
+---------------------+
|
46
|
+
| Title |
|
47
|
+
+---------------------+
|
48
|
+
| First ======= |
|
49
|
+
| Second ============ |
|
50
|
+
| Third == |
|
51
|
+
+---------------------+
|
52
|
+
|
53
|
+
Some display options for charts:
|
54
|
+
|
55
|
+
chart.width(integer)
|
56
|
+
chart.max_width(integer) # width takes priority
|
57
|
+
|
58
|
+
Combine tables and charts into a grid:
|
59
|
+
|
60
|
+
> grid = Dashline::Grid.new
|
61
|
+
> grid.width(30) # 80 is the default , use `tput cols`.to_i for max width
|
62
|
+
> grid.add table1
|
63
|
+
> grid.add chart1
|
64
|
+
> grid.add table2
|
65
|
+
> grid.add table3
|
66
|
+
> puts grid.to_s
|
67
|
+
+---+---+---+ +-----------+
|
68
|
+
| 1 | 1 | 1 | | a ===== |
|
69
|
+
| 1 | 1 | 1 | | bb === |
|
70
|
+
| 1 | 1 | 1 | +-----------+
|
71
|
+
+---+---+---+ +-----------+
|
72
|
+
| 3 | 3 | 3 | | 2 | 2 | 2 |
|
73
|
+
+---+---+---+ +---+---+---+
|
74
|
+
|
75
|
+
Nodes (tables or charts) are added in a left-to-right, top-to-down order.
|
76
|
+
The Grid class will fill in nodes as space allows.
|
77
|
+
|
78
|
+
Development
|
79
|
+
===========
|
80
|
+
|
81
|
+
Tests are setup to run via `ruby test/*_test.rb` or via `rake`.
|
82
|
+
|
83
|
+
License
|
84
|
+
=======
|
85
|
+
|
86
|
+
Copyright Hugh Bien - http://hughbien.com.
|
87
|
+
Released under BSD License, see LICENSE.md for more info.
|
data/lib/dashes.rb
ADDED
@@ -0,0 +1,260 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
module Dashes
|
4
|
+
VERSION = '0.0.1'
|
5
|
+
|
6
|
+
def self.clean(str)
|
7
|
+
str.to_s.
|
8
|
+
gsub(/\x1b(\[|\(|\))[;?0-9]*[0-9A-Za-z]/, '').
|
9
|
+
gsub(/\x1b(\[|\(|\))[;?0-9]*[0-9A-Za-z]/, '').
|
10
|
+
gsub(/(\x03|\x1a)/, '')
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.strlen(str)
|
14
|
+
str.nil? ? 0 : clean(str).length
|
15
|
+
end
|
16
|
+
|
17
|
+
class Node
|
18
|
+
def width(width); raise NotImplementedError; end
|
19
|
+
def max_width(max_width); raise NotImplementedError; end
|
20
|
+
def to_s; raise NotImplementedError; end
|
21
|
+
def total_width; raise NotImplementedError; end
|
22
|
+
|
23
|
+
private
|
24
|
+
def cell(data, width, align=:left)
|
25
|
+
str = data.to_s
|
26
|
+
length = Dashes.strlen(str)
|
27
|
+
if length > width
|
28
|
+
str[0...width]
|
29
|
+
elsif align == :center
|
30
|
+
lpad = " " * ((width - length) / 2)
|
31
|
+
rpad = lpad.clone
|
32
|
+
lpad += " " if (width - length).odd?
|
33
|
+
lpad + str + rpad
|
34
|
+
else
|
35
|
+
pad = " " * (width - length)
|
36
|
+
align == :left ?
|
37
|
+
"#{str}#{pad}" :
|
38
|
+
"#{pad}#{str}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Table < Node
|
44
|
+
def initialize
|
45
|
+
@rows = []
|
46
|
+
@separators = []
|
47
|
+
@aligns = []
|
48
|
+
@width = nil
|
49
|
+
@max_width = nil
|
50
|
+
@spacing = nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def row(*data)
|
54
|
+
@rows << data.map(&:to_s)
|
55
|
+
end
|
56
|
+
|
57
|
+
def separator
|
58
|
+
@separators << @rows.length
|
59
|
+
end
|
60
|
+
|
61
|
+
def align(*alignments)
|
62
|
+
@aligns = alignments
|
63
|
+
end
|
64
|
+
|
65
|
+
def width(width)
|
66
|
+
@width = width
|
67
|
+
end
|
68
|
+
|
69
|
+
def max_width(max_width)
|
70
|
+
@max_width = max_width
|
71
|
+
end
|
72
|
+
|
73
|
+
def spacing(*spacing)
|
74
|
+
@spacing = spacing
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_s
|
78
|
+
return '' if @rows.empty?
|
79
|
+
widths = col_widths
|
80
|
+
format = []
|
81
|
+
separator = "+-#{widths.map {|w| '-'*w}.join('-+-')}-+"
|
82
|
+
format << separator
|
83
|
+
@rows.each_with_index do |row, index|
|
84
|
+
@separators.select { |s| s == index }.count.times { format << separator }
|
85
|
+
line = []
|
86
|
+
row.each_with_index do |data, col|
|
87
|
+
line << cell(data, widths[col], @aligns[col] || :left)
|
88
|
+
end
|
89
|
+
format << "| #{line.join(' | ')} |"
|
90
|
+
end
|
91
|
+
@separators.select { |s| s == @rows.length }.count.times { format << separator }
|
92
|
+
format << separator
|
93
|
+
format.join("\n")
|
94
|
+
end
|
95
|
+
|
96
|
+
def total_width
|
97
|
+
if @rows.empty?
|
98
|
+
0
|
99
|
+
elsif @width
|
100
|
+
@width
|
101
|
+
else
|
102
|
+
width = col_widths.reduce { |a,b| a+b }
|
103
|
+
cols = @rows.first.size
|
104
|
+
twidth = width + (2 * cols) + (cols + 1)
|
105
|
+
@max_width ? [twidth, @max_width].min : twidth
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
def col_widths
|
111
|
+
return [] if @rows.empty?
|
112
|
+
cols = @rows.first.size
|
113
|
+
widths = [0] * cols
|
114
|
+
(0...cols).map do |col|
|
115
|
+
@rows.each do |row|
|
116
|
+
widths[col] = [Dashes.strlen(row[col]), widths[col]].max
|
117
|
+
end
|
118
|
+
end
|
119
|
+
pad = (2 * cols) + (cols + 1) # cell padding/borders
|
120
|
+
sum = widths.reduce {|a,b| a+b} + pad
|
121
|
+
if sum == @width || (@width.nil? && (@max_width.nil? || sum <= @max_width))
|
122
|
+
widths
|
123
|
+
else
|
124
|
+
indexes = (0...cols).to_a
|
125
|
+
if @spacing && @spacing.uniq.length > 1
|
126
|
+
# which columns to spread the padding within
|
127
|
+
cols = @spacing.select { |s| s == :max }.length
|
128
|
+
indexes = @spacing.each_index.select { |i| @spacing[i] == :max }
|
129
|
+
end
|
130
|
+
twidth = @width || (@max_width ? [sum, @max_width].min : sum)
|
131
|
+
delta = twidth >= sum ? 1 : -1
|
132
|
+
pad = ((twidth - sum).abs / cols) * delta
|
133
|
+
uneven = (twidth - sum).abs % cols
|
134
|
+
indexes.each do |index|
|
135
|
+
widths[index] += pad
|
136
|
+
widths[index] += delta if index < uneven
|
137
|
+
widths[index] = 0 if widths[index] < 0
|
138
|
+
end
|
139
|
+
widths
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Chart < Node
|
145
|
+
def initialize
|
146
|
+
@title = nil
|
147
|
+
@rows = []
|
148
|
+
@width = nil
|
149
|
+
@max_width = nil
|
150
|
+
end
|
151
|
+
|
152
|
+
def title(title)
|
153
|
+
@title = title
|
154
|
+
end
|
155
|
+
|
156
|
+
def row(label, num)
|
157
|
+
@rows << [label, num]
|
158
|
+
end
|
159
|
+
|
160
|
+
def width(width)
|
161
|
+
@width = width
|
162
|
+
end
|
163
|
+
|
164
|
+
def max_width(max_width)
|
165
|
+
@max_width = max_width
|
166
|
+
end
|
167
|
+
|
168
|
+
def to_s
|
169
|
+
return '' if @rows.empty?
|
170
|
+
wbar, wlabel = bar_width, label_width
|
171
|
+
wtotal = total_width - 4 # 4 for side borders and padding
|
172
|
+
bar_space = wtotal - wlabel - 1
|
173
|
+
bar_ratio = wbar > bar_space ? bar_space/wbar.to_f : 1
|
174
|
+
|
175
|
+
separator = "+-#{'-'*wtotal}-+"
|
176
|
+
format = [separator]
|
177
|
+
if @title
|
178
|
+
format << "| #{cell(@title, wtotal)} |"
|
179
|
+
format << separator
|
180
|
+
end
|
181
|
+
@rows.each do |label, num|
|
182
|
+
bar = '=' * (num * bar_ratio).floor
|
183
|
+
format << "| #{cell(label, wlabel, :right)} #{cell(bar, bar_space)} |"
|
184
|
+
end
|
185
|
+
format << separator
|
186
|
+
format.join("\n")
|
187
|
+
end
|
188
|
+
|
189
|
+
def total_width
|
190
|
+
if @rows.empty?
|
191
|
+
0
|
192
|
+
elsif @width
|
193
|
+
@width
|
194
|
+
else
|
195
|
+
# 4 for borders/padding
|
196
|
+
twidth = [bar_width + label_width + 1, title_width].max + 4
|
197
|
+
@max_width ? [twidth, @max_width].min : twidth
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
private
|
202
|
+
def bar_width
|
203
|
+
@rows.map { |row| row[1] }.max
|
204
|
+
end
|
205
|
+
|
206
|
+
def label_width
|
207
|
+
@rows.map { |row| Dashes.strlen(row[0]) }.max
|
208
|
+
end
|
209
|
+
|
210
|
+
def title_width
|
211
|
+
Dashes.strlen(@title)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
class Grid
|
216
|
+
def initialize
|
217
|
+
@nodes = []
|
218
|
+
@width = 80
|
219
|
+
end
|
220
|
+
|
221
|
+
def add(node)
|
222
|
+
@nodes << node
|
223
|
+
end
|
224
|
+
|
225
|
+
def width(width)
|
226
|
+
@width = width
|
227
|
+
end
|
228
|
+
|
229
|
+
def to_s
|
230
|
+
return '' if @nodes.empty?
|
231
|
+
buffer = []
|
232
|
+
node_width = [@nodes.map(&:total_width).max, @width].min
|
233
|
+
space_matcher = " "*(node_width+1) # 1 for padding
|
234
|
+
@nodes.each do |node|
|
235
|
+
node = node.clone
|
236
|
+
node.width(node_width)
|
237
|
+
if (index = buffer.index { |l| l.include?(space_matcher) })
|
238
|
+
# there's space for the table in a row, fit it in
|
239
|
+
col = Dashes.clean(buffer[index]) =~ Regexp.new(space_matcher)
|
240
|
+
node.to_s.split("\n").each do |line|
|
241
|
+
if buffer[index].nil?
|
242
|
+
buffer[index] = "#{" "*@width}"
|
243
|
+
end
|
244
|
+
new_line = col == 0 ? "#{line} " : " #{line}"
|
245
|
+
# handle offset from special characters like color strings
|
246
|
+
pre_line = buffer[index].split(space_matcher).first.to_s
|
247
|
+
offset = pre_line.length - Dashes.clean(pre_line).length
|
248
|
+
buffer[index][col+offset..(col+node_width+offset)] = new_line
|
249
|
+
index += 1
|
250
|
+
end
|
251
|
+
else
|
252
|
+
# there's no more room, just add the table below
|
253
|
+
rpad = " "*(@width - node_width)
|
254
|
+
buffer += node.to_s.split("\n").map { |line| "#{line}#{rpad}" }
|
255
|
+
end
|
256
|
+
end
|
257
|
+
buffer.map(&:rstrip).join("\n")
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
data/test/dashes_test.rb
ADDED
@@ -0,0 +1,332 @@
|
|
1
|
+
require File.expand_path('../lib/dashes', File.dirname(__FILE__))
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
class DashesTableTest < MiniTest::Unit::TestCase
|
5
|
+
def test_empty
|
6
|
+
table = Dashes::Table.new
|
7
|
+
assert_equal('', table.to_s)
|
8
|
+
assert_equal(0, table.total_width)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_cell
|
12
|
+
table = Dashes::Table.new
|
13
|
+
assert_equal("x", table.send(:cell, "x", 1))
|
14
|
+
assert_equal("xx", table.send(:cell, "xxxxx", 2))
|
15
|
+
assert_equal("x ", table.send(:cell, "x", 5))
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_cell_alignment
|
19
|
+
table = Dashes::Table.new
|
20
|
+
assert_equal("x ", table.send(:cell, "x", 3, :left))
|
21
|
+
assert_equal(" x ", table.send(:cell, "x", 3, :center))
|
22
|
+
assert_equal(" x", table.send(:cell, "x", 3, :right))
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_separators
|
26
|
+
table = Dashes::Table.new
|
27
|
+
table.separator
|
28
|
+
table.separator
|
29
|
+
table.row 'First', 'Second', 'Third'
|
30
|
+
table.separator
|
31
|
+
table.separator
|
32
|
+
table.row 1, 2, 3
|
33
|
+
table.separator
|
34
|
+
table.separator
|
35
|
+
|
36
|
+
assert_equal([5, 6, 5], table.send(:col_widths))
|
37
|
+
assert_equal(26, table.total_width)
|
38
|
+
assert_equal(
|
39
|
+
"+-------+--------+-------+\n" +
|
40
|
+
"+-------+--------+-------+\n" +
|
41
|
+
"+-------+--------+-------+\n" +
|
42
|
+
"| First | Second | Third |\n" +
|
43
|
+
"+-------+--------+-------+\n" +
|
44
|
+
"+-------+--------+-------+\n" +
|
45
|
+
"| 1 | 2 | 3 |\n" +
|
46
|
+
"+-------+--------+-------+\n" +
|
47
|
+
"+-------+--------+-------+\n" +
|
48
|
+
"+-------+--------+-------+",
|
49
|
+
table.to_s)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_alignment
|
53
|
+
table = Dashes::Table.new
|
54
|
+
table.align :left, :center, :right
|
55
|
+
table.row 'First', 'Second', 'Third'
|
56
|
+
table.separator
|
57
|
+
table.row 1, 2, 3
|
58
|
+
assert_equal(
|
59
|
+
"+-------+--------+-------+\n" +
|
60
|
+
"| First | Second | Third |\n" +
|
61
|
+
"+-------+--------+-------+\n" +
|
62
|
+
"| 1 | 2 | 3 |\n" +
|
63
|
+
"+-------+--------+-------+",
|
64
|
+
table.to_s)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_width
|
68
|
+
table = Dashes::Table.new
|
69
|
+
table.width 26
|
70
|
+
table.row '1', '2', '3'
|
71
|
+
assert_equal(26, table.total_width)
|
72
|
+
assert_equal(
|
73
|
+
"+--------+-------+-------+\n" +
|
74
|
+
"| 1 | 2 | 3 |\n" +
|
75
|
+
"+--------+-------+-------+",
|
76
|
+
table.to_s)
|
77
|
+
|
78
|
+
table.spacing :min, :min, :max
|
79
|
+
assert_equal(
|
80
|
+
"+---+---+----------------+\n" +
|
81
|
+
"| 1 | 2 | 3 |\n" +
|
82
|
+
"+---+---+----------------+",
|
83
|
+
table.to_s)
|
84
|
+
|
85
|
+
table.spacing :max, :max, :min
|
86
|
+
assert_equal(
|
87
|
+
"+----------+---------+---+\n" +
|
88
|
+
"| 1 | 2 | 3 |\n" +
|
89
|
+
"+----------+---------+---+",
|
90
|
+
table.to_s)
|
91
|
+
|
92
|
+
table.spacing :min, :min, :min
|
93
|
+
assert_equal(
|
94
|
+
"+--------+-------+-------+\n" +
|
95
|
+
"| 1 | 2 | 3 |\n" +
|
96
|
+
"+--------+-------+-------+",
|
97
|
+
table.to_s)
|
98
|
+
|
99
|
+
table.spacing :max, :max, :max
|
100
|
+
assert_equal(
|
101
|
+
"+--------+-------+-------+\n" +
|
102
|
+
"| 1 | 2 | 3 |\n" +
|
103
|
+
"+--------+-------+-------+",
|
104
|
+
table.to_s)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_max_width
|
108
|
+
table = Dashes::Table.new
|
109
|
+
table.max_width 26
|
110
|
+
table.row 'First', 'Second', 'Third'
|
111
|
+
table.row 1, 2, 3
|
112
|
+
assert_equal(
|
113
|
+
"+-------+--------+-------+\n" +
|
114
|
+
"| First | Second | Third |\n" +
|
115
|
+
"| 1 | 2 | 3 |\n" +
|
116
|
+
"+-------+--------+-------+",
|
117
|
+
table.to_s)
|
118
|
+
|
119
|
+
table.max_width 14
|
120
|
+
assert_equal(
|
121
|
+
"+---+----+---+\n" +
|
122
|
+
"| F | Se | T |\n" +
|
123
|
+
"| 1 | 2 | 3 |\n" +
|
124
|
+
"+---+----+---+",
|
125
|
+
table.to_s)
|
126
|
+
|
127
|
+
table.width 26 # width takes priority
|
128
|
+
assert_equal(
|
129
|
+
"+-------+--------+-------+\n" +
|
130
|
+
"| First | Second | Third |\n" +
|
131
|
+
"| 1 | 2 | 3 |\n" +
|
132
|
+
"+-------+--------+-------+",
|
133
|
+
table.to_s)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class DashesChartTest < MiniTest::Unit::TestCase
|
138
|
+
def test_empty
|
139
|
+
chart = Dashes::Chart.new
|
140
|
+
assert_equal('', chart.to_s)
|
141
|
+
assert_equal(0, chart.total_width)
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_basic_chart
|
145
|
+
chart = Dashes::Chart.new
|
146
|
+
chart.title 'Title'
|
147
|
+
chart.row 'a', 20
|
148
|
+
chart.row 'bb', 15
|
149
|
+
chart.row 'ccc', 5
|
150
|
+
chart.row 'dddd', 1
|
151
|
+
|
152
|
+
assert_equal(
|
153
|
+
"+---------------------------+\n" +
|
154
|
+
"| Title |\n" +
|
155
|
+
"+---------------------------+\n" +
|
156
|
+
"| a ==================== |\n" +
|
157
|
+
"| bb =============== |\n" +
|
158
|
+
"| ccc ===== |\n" +
|
159
|
+
"| dddd = |\n" +
|
160
|
+
"+---------------------------+",
|
161
|
+
chart.to_s)
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_normalized_width
|
165
|
+
chart = Dashes::Chart.new
|
166
|
+
chart.width(29)
|
167
|
+
chart.row 'a', 40
|
168
|
+
chart.row 'bb', 30
|
169
|
+
chart.row 'ccc', 10
|
170
|
+
chart.row 'dddd', 2
|
171
|
+
assert_equal(
|
172
|
+
"+---------------------------+\n" +
|
173
|
+
"| a ==================== |\n" +
|
174
|
+
"| bb =============== |\n" +
|
175
|
+
"| ccc ===== |\n" +
|
176
|
+
"| dddd = |\n" +
|
177
|
+
"+---------------------------+",
|
178
|
+
chart.to_s)
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_max_width
|
182
|
+
chart = Dashes::Chart.new
|
183
|
+
chart.max_width(100)
|
184
|
+
chart.row 'a', 4
|
185
|
+
chart.row 'bb', 3
|
186
|
+
chart.row 'ccc', 2
|
187
|
+
chart.row 'dddd', 1
|
188
|
+
assert_equal(
|
189
|
+
"+-----------+\n" +
|
190
|
+
"| a ==== |\n" +
|
191
|
+
"| bb === |\n" +
|
192
|
+
"| ccc == |\n" +
|
193
|
+
"| dddd = |\n" +
|
194
|
+
"+-----------+",
|
195
|
+
chart.to_s)
|
196
|
+
|
197
|
+
chart2 = Dashes::Chart.new
|
198
|
+
chart2.max_width(13)
|
199
|
+
chart2.row 'a', 8
|
200
|
+
chart2.row 'bb', 6
|
201
|
+
chart2.row 'ccc', 4
|
202
|
+
chart2.row 'dddd', 2
|
203
|
+
assert_equal(
|
204
|
+
"+-----------+\n" +
|
205
|
+
"| a ==== |\n" +
|
206
|
+
"| bb === |\n" +
|
207
|
+
"| ccc == |\n" +
|
208
|
+
"| dddd = |\n" +
|
209
|
+
"+-----------+",
|
210
|
+
chart2.to_s)
|
211
|
+
|
212
|
+
chart2.width(17) # width should take priority
|
213
|
+
assert_equal(
|
214
|
+
"+---------------+\n" +
|
215
|
+
"| a ======== |\n" +
|
216
|
+
"| bb ====== |\n" +
|
217
|
+
"| ccc ==== |\n" +
|
218
|
+
"| dddd == |\n" +
|
219
|
+
"+---------------+",
|
220
|
+
chart2.to_s)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
class DashesGridTest < MiniTest::Unit::TestCase
|
225
|
+
def test_empty
|
226
|
+
grid = Dashes::Grid.new
|
227
|
+
assert_equal('', grid.to_s)
|
228
|
+
|
229
|
+
grid.add Dashes::Table.new
|
230
|
+
grid.add Dashes::Chart.new
|
231
|
+
assert_equal('', grid.to_s)
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_basic_grid
|
235
|
+
table = Dashes::Table.new
|
236
|
+
table.row 'a', 'a', 'a'
|
237
|
+
table.separator
|
238
|
+
table.row 'a', 'a', 'a'
|
239
|
+
table.separator
|
240
|
+
table.row 'a', 'a', 'a'
|
241
|
+
table2 = Dashes::Table.new
|
242
|
+
table2.row 'b', 'b', 'b'
|
243
|
+
table3 = Dashes::Table.new
|
244
|
+
table3.row 'c', 'c', 'c'
|
245
|
+
|
246
|
+
grid = Dashes::Grid.new
|
247
|
+
grid.width 27
|
248
|
+
grid.add table
|
249
|
+
grid.add table2
|
250
|
+
grid.add table3
|
251
|
+
|
252
|
+
assert_equal(
|
253
|
+
"+---+---+---+ +---+---+---+\n" +
|
254
|
+
"| a | a | a | | b | b | b |\n" +
|
255
|
+
"+---+---+---+ +---+---+---+\n" +
|
256
|
+
"| a | a | a | +---+---+---+\n" +
|
257
|
+
"+---+---+---+ | c | c | c |\n" +
|
258
|
+
"| a | a | a | +---+---+---+\n" +
|
259
|
+
"+---+---+---+",
|
260
|
+
grid.to_s)
|
261
|
+
|
262
|
+
table4 = Dashes::Table.new
|
263
|
+
table4.row 'a', 'a', 'a'
|
264
|
+
table4.row 'a', 'a', 'a'
|
265
|
+
table4.row 'a', 'a', 'a'
|
266
|
+
|
267
|
+
grid2 = Dashes::Grid.new
|
268
|
+
grid2.width 27
|
269
|
+
grid2.add table4
|
270
|
+
grid2.add table3
|
271
|
+
grid2.add table2
|
272
|
+
|
273
|
+
assert_equal(
|
274
|
+
"+---+---+---+ +---+---+---+\n" +
|
275
|
+
"| a | a | a | | c | c | c |\n" +
|
276
|
+
"| a | a | a | +---+---+---+\n" +
|
277
|
+
"| a | a | a | +---+---+---+\n" +
|
278
|
+
"+---+---+---+ | b | b | b |\n" +
|
279
|
+
" +---+---+---+",
|
280
|
+
grid2.to_s)
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_mixed_grid
|
284
|
+
table = Dashes::Table.new
|
285
|
+
table.row 'a', 'a', 'a'
|
286
|
+
table.row 'a', 'a', 'a'
|
287
|
+
table.row 'a', 'a', 'a'
|
288
|
+
|
289
|
+
chart = Dashes::Chart.new
|
290
|
+
chart.row 'a', 5
|
291
|
+
chart.row 'bb', 3
|
292
|
+
chart.row 'ccc', 1
|
293
|
+
|
294
|
+
grid = Dashes::Grid.new
|
295
|
+
grid.add table
|
296
|
+
grid.add chart
|
297
|
+
assert_equal(
|
298
|
+
"+---+---+---+ +-----------+\n" +
|
299
|
+
"| a | a | a | | a ===== |\n" +
|
300
|
+
"| a | a | a | | bb === |\n" +
|
301
|
+
"| a | a | a | | ccc = |\n" +
|
302
|
+
"+---+---+---+ +-----------+",
|
303
|
+
grid.to_s)
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_alternating_grid
|
307
|
+
short = Dashes::Table.new
|
308
|
+
short.row 'a', 'a', 'a'
|
309
|
+
|
310
|
+
short2 = Dashes::Table.new
|
311
|
+
short2.row 'b', 'b', 'b'
|
312
|
+
|
313
|
+
long = Dashes::Table.new
|
314
|
+
long.row 'd', 'd', 'd'
|
315
|
+
long.row 'd', 'd', 'd'
|
316
|
+
long.row 'd', 'd', 'd'
|
317
|
+
|
318
|
+
grid = Dashes::Grid.new
|
319
|
+
grid.width(27)
|
320
|
+
grid.add short
|
321
|
+
grid.add long
|
322
|
+
grid.add short2
|
323
|
+
assert_equal(
|
324
|
+
"+---+---+---+ +---+---+---+\n" +
|
325
|
+
"| a | a | a | | d | d | d |\n" +
|
326
|
+
"+---+---+---+ | d | d | d |\n" +
|
327
|
+
"+---+---+---+ | d | d | d |\n" +
|
328
|
+
"| b | b | b | +---+---+---+\n" +
|
329
|
+
"+---+---+---+",
|
330
|
+
grid.to_s)
|
331
|
+
end
|
332
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dashes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Hugh Bien
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: minitest
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: Format data into a dashboard of charts/tables on the command line.
|
31
|
+
email:
|
32
|
+
- hugh@hughbien.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- LICENSE.md
|
38
|
+
- README.md
|
39
|
+
- lib/dashes.rb
|
40
|
+
- test/dashes_test.rb
|
41
|
+
homepage: https://github.com/hughbien/dashes
|
42
|
+
licenses: []
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 1.3.6
|
59
|
+
requirements: []
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.8.23
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Good looking charts for your terminal.
|
65
|
+
test_files: []
|