text_layout 0.1.1 → 0.2.0
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/Manifest.txt +1 -0
- data/README.rdoc +20 -6
- data/lib/text_layout.rb +1 -1
- data/lib/text_layout/table.rb +210 -66
- data/test/test_text_layout.rb +54 -14
- data/test/test_wrap.rb +17 -0
- metadata +10 -8
data/Manifest.txt
CHANGED
data/README.rdoc
CHANGED
@@ -4,13 +4,14 @@
|
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
7
|
-
Text layout engine for CUI apps.
|
7
|
+
Text layout engine for CUI apps with a pretty table.
|
8
8
|
|
9
9
|
== FEATURES/PROBLEMS:
|
10
10
|
|
11
11
|
* Full-width character support.
|
12
12
|
* Line wrapping.
|
13
13
|
* Table layout with colspan and rowspan.
|
14
|
+
* Table with border.
|
14
15
|
|
15
16
|
== SYNOPSIS:
|
16
17
|
|
@@ -24,21 +25,27 @@ Text layout engine for CUI apps.
|
|
24
25
|
[{:colspan => 2, :value => "37Wh(13\")"}, "40Wh(13\")", {:colspan => 2, :value => "50Wh(13\")"}]
|
25
26
|
]
|
26
27
|
|
27
|
-
puts TextLayout::Table.new(table).layout
|
28
|
+
puts TextLayout::Table.new(table, :border => true).layout
|
28
29
|
|
29
30
|
---
|
30
31
|
|
31
|
-
|
32
|
+
+----------------------------------------------------------------------------------------------------+
|
33
|
+
| Table of models |
|
34
|
+
+------------------+---------------+-----------+-----------+--------------------+--------------------+
|
32
35
|
| Model | Early 2008 | Late 2008 | Mid 2009 | Late 2010 | Mid 2011 |
|
36
|
+
+------------------+---------------+-----------+-----------+--------------------+--------------------+
|
33
37
|
| Model Identifier | MacBookAir1,1 | MacBookAir2,1 | MacBookAir3,1(11") | MacBookAir4,1(11") |
|
34
38
|
| | | | MacBookAir3,2(13") | MacBookAir4,2(13") |
|
39
|
+
+------------------+---------------+-----------+-----------+--------------------+--------------------+
|
35
40
|
| Model number | MB003LL/A | MB543LL/A | MC233LL/A | MC505LL/A | MC968ZP/A |
|
36
41
|
| | | MB940LL/A | MC234LL/A | MC503LL/A | MC969ZP/A |
|
37
42
|
| | | | | | MC965ZP/A |
|
38
43
|
| | | | | | MC966ZP/A |
|
39
|
-
|
44
|
+
+------------------+---------------+-----------+-----------+--------------------+--------------------+
|
45
|
+
| Battery | N/A | 35Wh(11") |
|
46
|
+
| +---------------------------+-----------+-----------------------------------------+
|
40
47
|
| | 37Wh(13") | 40Wh(13") | 50Wh(13") |
|
41
|
-
|
48
|
+
+------------------+---------------------------+-----------+-----------------------------------------+
|
42
49
|
|
43
50
|
== REQUIREMENTS:
|
44
51
|
|
@@ -48,6 +55,13 @@ Text layout engine for CUI apps.
|
|
48
55
|
|
49
56
|
* $ gem install text_layout
|
50
57
|
|
58
|
+
== OTHER CHOICES
|
59
|
+
|
60
|
+
* https://github.com/aptinio/text-table
|
61
|
+
* https://github.com/jwulff/pretty_table
|
62
|
+
* https://github.com/visionmedia/terminal-table
|
63
|
+
* http://rubyworks.github.com/ansi/docs/api/ANSI/Table.html
|
64
|
+
|
51
65
|
== DEVELOPERS:
|
52
66
|
|
53
67
|
After checking out the source, run:
|
@@ -61,7 +75,7 @@ and generate the RDoc.
|
|
61
75
|
|
62
76
|
(The MIT License)
|
63
77
|
|
64
|
-
Copyright (c) 2011
|
78
|
+
Copyright (c) 2011 NANKI Haruo
|
65
79
|
|
66
80
|
Permission is hereby granted, free of charge, to any person obtaining
|
67
81
|
a copy of this software and associated documentation files (the
|
data/lib/text_layout.rb
CHANGED
data/lib/text_layout/table.rb
CHANGED
@@ -1,27 +1,42 @@
|
|
1
1
|
class TextLayout::Table
|
2
|
-
def initialize(
|
3
|
-
@
|
4
|
-
|
2
|
+
def initialize(table, options = {})
|
3
|
+
@table = table
|
4
|
+
@options = {
|
5
|
+
:align => :auto,
|
6
|
+
:col_border => "|",
|
7
|
+
:row_border => "-",
|
8
|
+
:cross => "+",
|
9
|
+
:border => false,
|
10
|
+
:padding => " "
|
11
|
+
}.merge(options)
|
5
12
|
|
6
|
-
|
7
|
-
|
8
|
-
cell = {:value => cell}
|
13
|
+
if @options[:border] == true
|
14
|
+
@options[:border] = [:top, :bottom, :left, :right, :cell].inject({}){|r, i|r[i] = true;r}
|
9
15
|
end
|
16
|
+
end
|
10
17
|
|
11
|
-
|
12
|
-
|
18
|
+
def column_border_width
|
19
|
+
@column_border_width ||= (@options[:padding] + @options[:col_border] + @options[:padding]).display_width
|
20
|
+
end
|
21
|
+
|
22
|
+
def cell_format
|
23
|
+
@cell_format ||= @options[:padding] + "%s" + @options[:padding]
|
24
|
+
end
|
25
|
+
|
26
|
+
def line_format
|
27
|
+
@line_format ||= @options[:col_border] + "%s" + @options[:col_border]
|
13
28
|
end
|
14
29
|
|
15
30
|
class Cell < Struct.new(:col, :row, :attr)
|
16
31
|
def width
|
17
|
-
attr[:value].map(&:display_width).max
|
32
|
+
attr[:value].map(&:display_width).max || 0
|
18
33
|
end
|
19
34
|
|
20
35
|
def height
|
21
|
-
attr[:value].size
|
36
|
+
[attr[:value].size, 1].max
|
22
37
|
end
|
23
38
|
end
|
24
|
-
|
39
|
+
|
25
40
|
class Span < Cell
|
26
41
|
def main?(col, row)
|
27
42
|
self.col == col && self.row == row
|
@@ -29,110 +44,239 @@ class TextLayout::Table
|
|
29
44
|
end
|
30
45
|
|
31
46
|
def layout
|
32
|
-
|
33
|
-
|
47
|
+
unknot
|
48
|
+
calculate_cell_size
|
49
|
+
expand_cell_size
|
50
|
+
build_string.join("\n")
|
51
|
+
end
|
34
52
|
|
35
|
-
|
53
|
+
private
|
54
|
+
def unknot
|
55
|
+
@unknotted = @table.map{[]}
|
56
|
+
@spanss = {:row => Hash.new{[]}, :col => Hash.new{[]}}
|
57
|
+
@border = {:row => [], :col => []}
|
58
|
+
|
59
|
+
@table.each_with_index do |cols, row|
|
36
60
|
cols.each_with_index do |attr, col|
|
37
61
|
attr = normalize(attr)
|
62
|
+
col = @unknotted[row].index(nil) || @unknotted[row].size
|
63
|
+
rowspan, colspan = attr[:rowspan], attr[:colspan]
|
38
64
|
|
39
|
-
|
40
|
-
col =
|
41
|
-
end
|
42
|
-
|
43
|
-
if !attr[:rowspan] && !attr[:colspan]
|
44
|
-
layout[row][col] = Cell.new(col, row, attr)
|
65
|
+
if !rowspan && !colspan
|
66
|
+
@unknotted[row][col] = Cell.new(col, row, attr)
|
45
67
|
else
|
46
68
|
span = Span.new(col, row, attr)
|
47
|
-
spanss[:row][row
|
48
|
-
spanss[:col][col
|
49
|
-
|
50
|
-
(
|
51
|
-
(
|
52
|
-
|
69
|
+
@spanss[:row][[row, rowspan]] <<= span if rowspan
|
70
|
+
@spanss[:col][[col, colspan]] <<= span if colspan
|
71
|
+
|
72
|
+
(rowspan || 1).times do |rr|
|
73
|
+
(colspan || 1).times do |cc|
|
74
|
+
@unknotted[row+rr][col+cc] = span
|
53
75
|
end
|
54
76
|
end
|
55
77
|
end
|
78
|
+
|
79
|
+
@border[:row][row - 1] ||= @unknotted[row][col] != @unknotted[row - 1][col] if row > 0
|
80
|
+
@border[:col][col - 1] ||= @unknotted[row][col] != @unknotted[row][col - 1] if col > 0
|
56
81
|
end
|
57
82
|
end
|
58
83
|
|
59
|
-
|
84
|
+
[:row, :col].each{|dir| @border[dir].map!{|v| v ? 1 : 0 } }
|
85
|
+
@num_rows = @unknotted.size
|
86
|
+
@num_cols = @unknotted.first.size
|
87
|
+
end
|
60
88
|
|
61
|
-
|
89
|
+
def calculate_cell_size
|
90
|
+
@cell_size = {:row => [0] * @num_rows, :col => [0] * @num_cols}
|
91
|
+
|
92
|
+
@unknotted.each_with_index do |cols, row|
|
62
93
|
cols.each_with_index do |cell, col|
|
63
94
|
next if Span === cell && !cell.main?(col, row)
|
64
95
|
|
65
|
-
unless cell.attr[:colspan]
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
unless cell.attr[:rowspan]
|
70
|
-
max[:row][row] = [max[:row][row] || 0, cell.height].max
|
71
|
-
end
|
96
|
+
@cell_size[:col][col] = [@cell_size[:col][col], cell.width ].max unless cell.attr[:colspan]
|
97
|
+
@cell_size[:row][row] = [@cell_size[:row][row], cell.height].max unless cell.attr[:rowspan]
|
72
98
|
end
|
73
99
|
end
|
100
|
+
end
|
74
101
|
|
75
|
-
|
76
|
-
|
77
|
-
|
102
|
+
def expand_cell_size
|
103
|
+
[[:col, column_border_width], [:row, @options[:border] ? 1 : 0]].each do |dir, margin|
|
104
|
+
@spanss[dir].each do |range, spans|
|
105
|
+
rstart, rsize = range
|
78
106
|
spans.each do |span|
|
79
|
-
|
107
|
+
borders = sum(@border[dir][rstart, rsize-1])
|
108
|
+
size = sum(@cell_size[dir][*range]) + margin * borders
|
80
109
|
diff = (dir == :col ? span.width : span.height) - size
|
81
110
|
|
82
111
|
next unless diff > 0
|
83
|
-
|
84
|
-
|
85
|
-
|
112
|
+
|
113
|
+
q, r = diff.divmod rsize
|
114
|
+
rsize.times do |i|
|
115
|
+
@cell_size[dir][rstart + i] += q + (i < r ? 1 : 0)
|
86
116
|
end
|
87
117
|
end
|
88
118
|
end
|
89
119
|
end
|
120
|
+
end
|
90
121
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
122
|
+
def build_string
|
123
|
+
lines = []
|
124
|
+
|
125
|
+
total_lines = sum(@cell_size[:row])
|
126
|
+
|
127
|
+
if @options[:border]
|
128
|
+
total_lines += sum(@border[:row])
|
129
|
+
lines << row_border(-1) if @options[:border][:top]
|
130
|
+
end
|
131
|
+
|
132
|
+
total_lines.times do |display_row|
|
133
|
+
n = display_row
|
134
|
+
row, on_border = @cell_size[:row].each_with_index do |height, i|
|
135
|
+
n -= height
|
136
|
+
break i, false if n < 0
|
137
|
+
|
138
|
+
next unless @options[:border] && @options[:border][:cell]
|
139
|
+
|
140
|
+
n -= @border[:row][i] || 1
|
141
|
+
break i, true if n < 0
|
100
142
|
end
|
101
143
|
|
102
144
|
line = []
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
145
|
+
|
146
|
+
line << cross(-1, row) if on_border
|
147
|
+
|
148
|
+
@unknotted[row].each_with_index do |cell, col|
|
149
|
+
n = display_row - sum(@cell_size[:row][0, cell.row])
|
150
|
+
n -= sum(@border[:row][0, cell.row]) if @options[:border]
|
151
|
+
value = cell.attr[:value][n]
|
152
|
+
|
153
|
+
type =
|
154
|
+
unless on_border
|
155
|
+
:value
|
109
156
|
else
|
110
|
-
|
157
|
+
if row_border_visible?(col, row)
|
158
|
+
:cell_border
|
159
|
+
elsif !value
|
160
|
+
:blank
|
161
|
+
else
|
162
|
+
:value
|
163
|
+
end
|
111
164
|
end
|
112
165
|
|
113
|
-
|
166
|
+
case type
|
167
|
+
when :cell_border
|
168
|
+
line << cell_border(col)
|
169
|
+
when :blank
|
170
|
+
line << " " * cell_width(col)
|
171
|
+
when :value
|
172
|
+
next unless cell.col == col
|
173
|
+
line << cell_format % align(value.to_s, width_with_colspan(cell), cell.attr[:align] || @options[:align])
|
174
|
+
end
|
175
|
+
|
176
|
+
line << cross(col, row) if on_border
|
114
177
|
end
|
115
178
|
|
116
|
-
|
179
|
+
if on_border
|
180
|
+
lines << line.join
|
181
|
+
else
|
182
|
+
lines << line_format % line.join(@options[:col_border])
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
lines << row_border(@num_rows - 1) if @options[:border] && @options[:border][:bottom]
|
187
|
+
|
188
|
+
lines
|
189
|
+
end
|
190
|
+
|
191
|
+
def width_with_colspan(cell)
|
192
|
+
col = cell.col
|
193
|
+
if Span === cell && colspan = cell.attr[:colspan]
|
194
|
+
borders = sum(@border[:col][col, colspan - 1])
|
195
|
+
sum(@cell_size[:col][col, colspan]) + column_border_width * borders
|
196
|
+
else
|
197
|
+
@cell_size[:col][col]
|
117
198
|
end
|
199
|
+
end
|
118
200
|
|
119
|
-
|
201
|
+
def row_border(row)
|
202
|
+
line = ""
|
203
|
+
line << cross(-1, row)
|
204
|
+
@num_cols.times do |col|
|
205
|
+
line << cell_border(col)
|
206
|
+
line << cross(col, row)
|
207
|
+
end
|
208
|
+
line
|
209
|
+
end
|
210
|
+
|
211
|
+
def cell_width(col)
|
212
|
+
@cell_size[:col][col] + @options[:padding].display_width * 2
|
213
|
+
end
|
214
|
+
|
215
|
+
def cell_border(col)
|
216
|
+
@options[:row_border] * cell_width(col)
|
217
|
+
end
|
218
|
+
|
219
|
+
def row_border_visible?(col, row)
|
220
|
+
!@unknotted[row + 1] || @unknotted[row][col] != @unknotted[row + 1][col]
|
221
|
+
end
|
222
|
+
|
223
|
+
def cross(col, row)
|
224
|
+
if @unknotted[row+1]
|
225
|
+
sw = @unknotted[row+1][col]
|
226
|
+
se = @unknotted[row+1][col+1]
|
227
|
+
else
|
228
|
+
sw = se = nil
|
229
|
+
end
|
230
|
+
|
231
|
+
nw = @unknotted[row][col]
|
232
|
+
ne = @unknotted[row][col+1]
|
233
|
+
|
234
|
+
nw = ne = nil if row < 0
|
235
|
+
sw = nw = nil if col < 0
|
236
|
+
|
237
|
+
case
|
238
|
+
when nw == ne && sw == se
|
239
|
+
@options[:row_border]
|
240
|
+
when nw == sw && ne == se
|
241
|
+
@options[:col_border]
|
242
|
+
else
|
243
|
+
@options[:cross]
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def normalize(cell)
|
248
|
+
unless Hash === cell
|
249
|
+
cell = {:value => cell}
|
250
|
+
end
|
251
|
+
|
252
|
+
cell.delete :colspan if cell[:colspan] == 1
|
253
|
+
cell.delete :rowspan if cell[:rowspan] == 1
|
254
|
+
|
255
|
+
cell[:value] = cell[:value].to_s.lines.map(&:strip)
|
256
|
+
|
257
|
+
cell
|
120
258
|
end
|
121
259
|
|
122
260
|
def sum(array)
|
123
|
-
array.inject(0) {|r, i| r + i }
|
261
|
+
array.to_a.inject(0) {|r, i| r + i }
|
124
262
|
end
|
125
263
|
|
126
|
-
def
|
264
|
+
def align(str, width, type=:auto)
|
127
265
|
pad = width - str.display_width
|
128
|
-
pad = 0 if pad < 0
|
266
|
+
pad = 0 if pad < 0
|
129
267
|
case type
|
130
|
-
when :
|
131
|
-
|
268
|
+
when :auto
|
269
|
+
if width * 0.85 < pad
|
270
|
+
align(str, width, :center)
|
271
|
+
else
|
272
|
+
align(str, width, :right)
|
273
|
+
end
|
132
274
|
when :left
|
133
275
|
str + " " * pad
|
134
276
|
when :center
|
135
277
|
" " * (pad / 2) + str + " " * (pad - pad / 2)
|
278
|
+
else # :right
|
279
|
+
" " * pad + str
|
136
280
|
end
|
137
281
|
end
|
138
282
|
end
|
data/test/test_text_layout.rb
CHANGED
@@ -1,28 +1,26 @@
|
|
1
|
+
#!ruby -Ku -I../lib -rubygems
|
1
2
|
# -*- coding: UTF-8 -*-;
|
2
3
|
require "test/unit"
|
3
4
|
require "text_layout"
|
4
5
|
|
5
|
-
$KCODE = 'u'
|
6
|
-
|
7
6
|
class TestTextLayout < Test::Unit::TestCase
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def test_wrap
|
15
|
-
assert_equal (["+"*20] * 4).join("\n"), TextLayout::Wrap.new("+"*80).layout(20)
|
16
|
-
assert_equal "line-\nwrap", TextLayout::Wrap.new("linewrap").layout(5)
|
7
|
+
def test_span_1
|
8
|
+
assert_table [
|
9
|
+
[{:value => 1, :colspan => 1, :rowspan => 1}],
|
10
|
+
], <<-RESULT
|
11
|
+
| 1 |
|
12
|
+
RESULT
|
17
13
|
end
|
18
14
|
|
19
15
|
def test_table_simple
|
20
16
|
assert_table [
|
21
17
|
[1, 2],
|
22
|
-
[3, 4]
|
18
|
+
[3, 4],
|
19
|
+
[5, 6]
|
23
20
|
], <<-RESULT
|
24
21
|
| 1 | 2 |
|
25
22
|
| 3 | 4 |
|
23
|
+
| 5 | 6 |
|
26
24
|
RESULT
|
27
25
|
end
|
28
26
|
|
@@ -57,7 +55,49 @@ class TestTextLayout < Test::Unit::TestCase
|
|
57
55
|
RESULT
|
58
56
|
end
|
59
57
|
|
60
|
-
def
|
61
|
-
|
58
|
+
def test_align
|
59
|
+
assert_table [
|
60
|
+
[{:value => 1, :align => :left}, {:value => 2, :align => :center}, {:value => 3, :align => :right}],
|
61
|
+
[ {:value => "oooooooooooooooooooo", :colspan => 3}]
|
62
|
+
], <<-RESULT
|
63
|
+
| 1 | 2 | 3 |
|
64
|
+
| oooooooooooooooooooo |
|
65
|
+
RESULT
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_successive_colspan
|
69
|
+
assert_table [[{:colspan => 2, :value => "a"}] * 2], <<-RESULT
|
70
|
+
| a | a |
|
71
|
+
RESULT
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_border
|
75
|
+
assert_table [
|
76
|
+
[{:value => "", :colspan => 3}],
|
77
|
+
[1,2,3],
|
78
|
+
[{:value => "a", :rowspan=>2},"a",{:value => "a\na", :rowspan => 2}],
|
79
|
+
["a"]
|
80
|
+
], <<-RESULT, :border => true
|
81
|
+
+-----------+
|
82
|
+
| |
|
83
|
+
+---+---+---+
|
84
|
+
| 1 | 2 | 3 |
|
85
|
+
+---+---+---+
|
86
|
+
| a | a | a |
|
87
|
+
| +---+ a |
|
88
|
+
| | a | |
|
89
|
+
+---+---+---+
|
90
|
+
RESULT
|
91
|
+
end
|
92
|
+
|
93
|
+
def assert_table(array, expected, options={})
|
94
|
+
result = TextLayout::Table.new(array, options).layout
|
95
|
+
|
96
|
+
if expected.rstrip != result
|
97
|
+
puts
|
98
|
+
puts result
|
99
|
+
end
|
100
|
+
|
101
|
+
assert_equal expected.rstrip, result
|
62
102
|
end
|
63
103
|
end
|
data/test/test_wrap.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!ruby -Ku -I../lib -rubygems
|
2
|
+
# -*- coding: UTF-8 -*-;
|
3
|
+
require "test/unit"
|
4
|
+
require "text_layout"
|
5
|
+
|
6
|
+
class TestWrap < Test::Unit::TestCase
|
7
|
+
def test_wrap_private
|
8
|
+
wrap = TextLayout::Wrap.new("")
|
9
|
+
assert_equal %w(linew rap), wrap.send(:split_word, "linewrap", 5)
|
10
|
+
assert_equal %w(あい うえ), wrap.send(:split_word, "あいうえ", 5)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_wrap
|
14
|
+
assert_equal (["+"*20] * 4).join("\n"), TextLayout::Wrap.new("+"*80).layout(20)
|
15
|
+
assert_equal "line-\nwrap", TextLayout::Wrap.new("linewrap").layout(5)
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: text_layout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
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: 2011-09-
|
12
|
+
date: 2011-09-16 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: unicode-display_width
|
16
|
-
requirement: &
|
16
|
+
requirement: &70135698111700 !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: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70135698111700
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: hoe
|
27
|
-
requirement: &
|
27
|
+
requirement: &70135698111120 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,8 +32,8 @@ dependencies:
|
|
32
32
|
version: '2.10'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
36
|
-
description: Text layout engine for CUI apps.
|
35
|
+
version_requirements: *70135698111120
|
36
|
+
description: Text layout engine for CUI apps with a pretty table.
|
37
37
|
email:
|
38
38
|
- nanki@dotswitch.net
|
39
39
|
executables: []
|
@@ -50,6 +50,7 @@ files:
|
|
50
50
|
- Rakefile
|
51
51
|
- README.rdoc
|
52
52
|
- test/test_text_layout.rb
|
53
|
+
- test/test_wrap.rb
|
53
54
|
- .gemtest
|
54
55
|
homepage: http://github.com/nanki/text_layout
|
55
56
|
licenses: []
|
@@ -76,6 +77,7 @@ rubyforge_project: text_layout
|
|
76
77
|
rubygems_version: 1.8.6
|
77
78
|
signing_key:
|
78
79
|
specification_version: 3
|
79
|
-
summary: Text layout engine for CUI apps.
|
80
|
+
summary: Text layout engine for CUI apps with a pretty table.
|
80
81
|
test_files:
|
81
82
|
- test/test_text_layout.rb
|
83
|
+
- test/test_wrap.rb
|