tabularize 0.2.0 → 0.2.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/CHANGELOG.md +5 -0
- data/Gemfile.lock +1 -1
- data/README.md +25 -9
- data/lib/tabularize.rb +67 -27
- data/lib/tabularize/version.rb +1 -1
- data/test/readme.rb +4 -3
- data/test/test_tabularize.rb +38 -0
- metadata +2 -2
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,8 @@ tabularize
|
|
2
2
|
==========
|
3
3
|
|
4
4
|
Formatting tabular data with paddings.
|
5
|
-
|
5
|
+
[tabularize](https://github.com/junegunn/tabularize) correctly handles
|
6
|
+
CJK (Chinese, Japanese and Korean) wide characters and ANSI codes.
|
6
7
|
|
7
8
|
Inspired by tabular.vim (https://github.com/godlygeek/tabular)
|
8
9
|
|
@@ -49,17 +50,19 @@ puts table
|
|
49
50
|
* `:vborder` Character for vertical border
|
50
51
|
* `:iborder` Character for intersection point
|
51
52
|
* Alignment
|
52
|
-
* `:align`
|
53
|
+
* `:align` Horizontal alignment. `:left`, `:center`, `:right`, or Array of the three options
|
54
|
+
* `:valign` Vertical alignment. `:top`, `:middle`, `:bottom`, or Array of the three options
|
53
55
|
|
54
56
|
```ruby
|
55
|
-
table = Tabularize.new :pad
|
57
|
+
table = Tabularize.new :pad => '.', :pad_left => 2, :pad_right => 0,
|
56
58
|
:hborder => '~', :vborder => 'I', :iborder => '#',
|
57
|
-
:align
|
59
|
+
:align => [:left, :center, :right],
|
60
|
+
:valign => [:top, :bottom, :middle, :middle]
|
58
61
|
table << %w[Name Dept Location Phone]
|
59
62
|
table.separator!
|
60
|
-
table << ['John Doe', 'Finance', 'Los Angeles CA 90089',
|
63
|
+
table << ['John Doe', 'Finance', 'Los Angeles CA 90089', "555-1555"]
|
61
64
|
table << ['Average Joe', 'Engineering', 'Somewhere over the rainbow', 'N/A']
|
62
|
-
table << ['홍길동', '탁상 3부',
|
65
|
+
table << ['홍길동', '탁상 3부', "서울역 3번 출구 김씨 옆자리\n\n맞습니다", 'N/A']
|
63
66
|
puts table
|
64
67
|
```
|
65
68
|
|
@@ -69,7 +72,9 @@ I..Name.......I.....Dept....I.....................LocationI.....PhoneI
|
|
69
72
|
#~~~~~~~~~~~~~#~~~~~~~~~~~~~#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#~~~~~~~~~~#
|
70
73
|
I..John Doe...I....Finance..I.........Los Angeles CA 90089I..555-1555I
|
71
74
|
I..Average JoeI..EngineeringI...Somewhere over the rainbowI.......N/AI
|
72
|
-
I..홍길동.....I
|
75
|
+
I..홍길동.....I.............I..서울역 3번 출구 김씨 옆자리I..........I
|
76
|
+
I.............I.............I.............................I.......N/AI
|
77
|
+
I.............I...탁상 3부..I.....................맞습니다I..........I
|
73
78
|
#~~~~~~~~~~~~~#~~~~~~~~~~~~~#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#~~~~~~~~~~#
|
74
79
|
```
|
75
80
|
|
@@ -178,14 +183,25 @@ Hong Gildong | HR_________ | Nowhere___________________ | 555-5555
|
|
178
183
|
|
179
184
|
ANSI codes and CJK wide characters
|
180
185
|
----------------------------------
|
181
|
-
|
186
|
+
[tabularize](https://github.com/junegunn/tabularize) correctly calculates each cell width even in the presence of ANSI codes and CJK wide characters.
|
182
187
|
If your data doesn't have any of them, unset `:unicode` and `:ansi` options
|
183
|
-
so that
|
188
|
+
so that [tabularize](https://github.com/junegunn/tabularize) can process data more efficiently.
|
184
189
|
|
185
190
|
```ruby
|
186
191
|
table = Tabularize.new :unicode => false, :ansi => false
|
187
192
|
```
|
188
193
|
|
194
|
+
Related work
|
195
|
+
------------
|
196
|
+
I wasn't aware of [terminal-table](https://github.com/visionmedia/terminal-table)
|
197
|
+
when I blindly started building [tabularize](https://github.com/junegunn/tabularize).
|
198
|
+
It has more features and clearly is more mature than [tabularize](https://github.com/junegunn/tabularize),
|
199
|
+
you should definitely check it out.
|
200
|
+
|
201
|
+
There are a couple of things, however, [tabularize](https://github.com/junegunn/tabularize) does better:
|
202
|
+
- It correctly formats cells containing CJK wide characters.
|
203
|
+
- Vertical alignment for multi-line cells
|
204
|
+
|
189
205
|
Copyright
|
190
206
|
---------
|
191
207
|
|
data/lib/tabularize.rb
CHANGED
@@ -5,6 +5,7 @@ require 'unicode/display_width'
|
|
5
5
|
class Tabularize
|
6
6
|
DEFAULT_OPTIONS = {
|
7
7
|
:align => :left,
|
8
|
+
:valign => :top,
|
8
9
|
:pad => ' ',
|
9
10
|
:pad_left => 0,
|
10
11
|
:pad_right => 0,
|
@@ -63,11 +64,22 @@ class Tabularize
|
|
63
64
|
output = StringIO.new
|
64
65
|
output.puts separator
|
65
66
|
rows.each_with_index do |row, idx|
|
67
|
+
row = row.map { |val| val.lines.to_a.map(&:chomp) }
|
68
|
+
height = row[0] ? row[0].count : 1
|
66
69
|
@seps[idx].times do
|
67
70
|
output.puts separator
|
68
71
|
end
|
69
|
-
|
72
|
+
(0...height).each do |line|
|
73
|
+
output.puts v + row.map { |lines|
|
74
|
+
lines[line] || @options[:pad] * Tabularize.cell_width(lines[0], u, a)
|
75
|
+
}.join(v) + v
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
@seps[rows.length].times do
|
80
|
+
output.puts separator
|
70
81
|
end
|
82
|
+
|
71
83
|
output.puts separator
|
72
84
|
output.string
|
73
85
|
end
|
@@ -97,7 +109,8 @@ class Tabularize
|
|
97
109
|
pad = options[:pad].to_s
|
98
110
|
padl = options[:pad_left]
|
99
111
|
padr = options[:pad_right]
|
100
|
-
align = [options[:align]]
|
112
|
+
align = [*options[:align]]
|
113
|
+
valign = [*options[:valign]]
|
101
114
|
unicode = options[:unicode]
|
102
115
|
ansi = options[:ansi]
|
103
116
|
|
@@ -113,42 +126,69 @@ class Tabularize
|
|
113
126
|
unless align.all? { |a| [:left, :right, :center].include?(a) }
|
114
127
|
raise ArgumentError.new("Invalid alignment")
|
115
128
|
end
|
129
|
+
unless valign.all? { |a| [:top, :bottom, :middle].include?(a) }
|
130
|
+
raise ArgumentError.new("Invalid vertical alignment")
|
131
|
+
end
|
116
132
|
|
117
|
-
rows
|
118
|
-
max_widths
|
119
|
-
|
120
|
-
|
133
|
+
rows = []
|
134
|
+
max_widths = []
|
135
|
+
max_heights = []
|
136
|
+
table_data.each_with_index do |row, ridx|
|
137
|
+
rows << row = [*row].map(&:to_s)
|
121
138
|
|
122
139
|
row.each_with_index do |cell, idx|
|
123
|
-
|
140
|
+
nlines = 0
|
141
|
+
cell.lines do |c|
|
142
|
+
max_widths[idx] = [ Tabularize.cell_width(c.chomp, unicode, ansi), max_widths[idx] || 0 ].max
|
143
|
+
nlines += 1
|
144
|
+
end
|
145
|
+
max_heights[ridx] = [ nlines, max_heights[ridx] || 1 ].max
|
124
146
|
end
|
125
147
|
end
|
126
148
|
|
149
|
+
ridx = -1
|
127
150
|
rows.map { |row|
|
151
|
+
ridx += 1
|
128
152
|
idx = -1
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
153
|
+
max_height = max_heights[ridx]
|
154
|
+
row.map { |cell|
|
155
|
+
idx += 1
|
156
|
+
lines = cell.lines.to_a
|
157
|
+
offset =
|
158
|
+
case valign[idx] || valign.last
|
159
|
+
when :top
|
135
160
|
0
|
161
|
+
when :bottom
|
162
|
+
max_height - lines.length
|
163
|
+
when :middle
|
164
|
+
(max_height - lines.length) / 2
|
136
165
|
end
|
137
|
-
slen = str.length - alen
|
138
166
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
167
|
+
(0...max_height).map { |ln|
|
168
|
+
ln -= offset
|
169
|
+
str = (ln >= 0 && lines[ln]) ? lines[ln].chomp : (pad * max_widths[idx])
|
170
|
+
alen =
|
171
|
+
if ansi
|
172
|
+
Tabularize.cell_width(str, false, false) -
|
173
|
+
Tabularize.cell_width(str, false, true)
|
174
|
+
else
|
175
|
+
0
|
176
|
+
end
|
177
|
+
slen = str.length - alen
|
178
|
+
|
179
|
+
w = max_widths[idx]
|
180
|
+
w += str.length - str.display_width if unicode
|
181
|
+
pad * padl +
|
182
|
+
case align[idx] || align.last
|
183
|
+
when :left
|
184
|
+
str.ljust(w + alen, pad)
|
185
|
+
when :right
|
186
|
+
str.rjust(w + alen, pad)
|
187
|
+
when :center
|
188
|
+
str.rjust((w - slen) / 2 + slen + alen, pad).ljust(w + alen, pad)
|
189
|
+
end +
|
190
|
+
pad * padr
|
191
|
+
}.join($/)
|
152
192
|
}
|
153
193
|
}
|
154
194
|
end
|
data/lib/tabularize/version.rb
CHANGED
data/test/readme.rb
CHANGED
@@ -8,12 +8,13 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
8
8
|
require 'tabularize'
|
9
9
|
|
10
10
|
table = Tabularize.new
|
11
|
-
table = Tabularize.new :pad
|
11
|
+
table = Tabularize.new :pad => '.', :pad_left => 2, :pad_right => 0,
|
12
12
|
:hborder => '~', :vborder => 'I', :iborder => '#',
|
13
|
-
:align
|
13
|
+
:align => [:left, :center, :right],
|
14
|
+
:valign => [:top, :bottom, :middle, :middle]
|
14
15
|
table << %w[Name Dept Location Phone]
|
15
16
|
table.separator!
|
16
17
|
table << ['John Doe', 'Finance', 'Los Angeles CA 90089', '555-1555']
|
17
18
|
table << ['Average Joe', 'Engineering', 'Somewhere over the rainbow', 'N/A']
|
18
|
-
table << ['홍길동', '탁상 3부',
|
19
|
+
table << ['홍길동', '탁상 3부', "서울역 3번 출구 김씨 옆자리\n\n맞습니다", 'N/A']
|
19
20
|
puts table
|
data/test/test_tabularize.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require 'rubygems'
|
2
3
|
require 'bundler'
|
3
4
|
Bundler.setup(:default, :development)
|
@@ -131,7 +132,9 @@ class TestTabularize < Test::Unit::TestCase
|
|
131
132
|
assert_raise(ArgumentError) { Tabularize.it(5) }
|
132
133
|
assert_raise(ArgumentError) { Tabularize.it("hello") }
|
133
134
|
assert_raise(ArgumentError) { Tabularize.it([1, 2, 3], :align => :noidea) }
|
135
|
+
assert_raise(ArgumentError) { Tabularize.it([1, 2, 3], :valign => :noidea) }
|
134
136
|
assert_raise(ArgumentError) { Tabularize.it([1, 2, 3], :align => [:center, :top]) }
|
137
|
+
assert_raise(ArgumentError) { Tabularize.it([1, 2, 3], :valign => [:left, :right]) }
|
135
138
|
assert_raise(ArgumentError) { Tabularize.it([1, 2, 3], :pad => 'long') }
|
136
139
|
assert_raise(ArgumentError) { Tabularize.it([1, 2, 3], :pad => ' ', :pad_left => -1) }
|
137
140
|
assert_raise(ArgumentError) { Tabularize.it([1, 2, 3], :pad => ' ', :pad_left => '') }
|
@@ -154,4 +157,39 @@ class TestTabularize < Test::Unit::TestCase
|
|
154
157
|
|
155
158
|
puts table.to_s
|
156
159
|
end
|
160
|
+
|
161
|
+
def test_table_complex
|
162
|
+
output = "
|
163
|
+
#~~~~~~~~~~~~~#~~~~~~~~~~~~~#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#~~~~~~~~~~#
|
164
|
+
I..Name.......I.....Dept....I.....................LocationI.....PhoneI
|
165
|
+
#~~~~~~~~~~~~~#~~~~~~~~~~~~~#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#~~~~~~~~~~#
|
166
|
+
I..John Doe...I....Finance..I.........Los Angeles CA 90089I..555-1555I
|
167
|
+
I..Average JoeI..EngineeringI...Somewhere over the rainbowI.......N/AI
|
168
|
+
I..1..........I
|
169
|
+
#~~~~~~~~~~~~~#~~~~~~~~~~~~~#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#~~~~~~~~~~#
|
170
|
+
#~~~~~~~~~~~~~#~~~~~~~~~~~~~#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#~~~~~~~~~~#
|
171
|
+
I..홍길동.....I.............I..서울역 3번 출구 김씨 옆자리I..........I
|
172
|
+
I.............I.............I.............................I.......N/AI
|
173
|
+
I.............I...탁상 3부..I.....................맞습니다I..........I
|
174
|
+
#~~~~~~~~~~~~~#~~~~~~~~~~~~~#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#~~~~~~~~~~#
|
175
|
+
#~~~~~~~~~~~~~#~~~~~~~~~~~~~#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#~~~~~~~~~~#
|
176
|
+
#~~~~~~~~~~~~~#~~~~~~~~~~~~~#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#~~~~~~~~~~#
|
177
|
+
".strip
|
178
|
+
|
179
|
+
table = Tabularize.new :pad => '.', :pad_left => 2, :pad_right => 0,
|
180
|
+
:hborder => '~', :vborder => 'I', :iborder => '#',
|
181
|
+
:align => [:left, :center, :right],
|
182
|
+
:valign => [:top, :bottom, :middle, :middle]
|
183
|
+
table << %w[Name Dept Location Phone]
|
184
|
+
table.separator!
|
185
|
+
table << ['John Doe', 'Finance', 'Los Angeles CA 90089', '555-1555']
|
186
|
+
table << ['Average Joe', 'Engineering', 'Somewhere over the rainbow', 'N/A']
|
187
|
+
table << [1]
|
188
|
+
table.separator!
|
189
|
+
table.separator!
|
190
|
+
table << ['홍길동', '탁상 3부', "서울역 3번 출구 김씨 옆자리\n\n맞습니다", 'N/A']
|
191
|
+
table.separator!
|
192
|
+
table.separator!
|
193
|
+
assert_equal output, table.to_s.strip
|
194
|
+
end
|
157
195
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tabularize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: awesome_print
|