dashes 0.0.1
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/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: []
|