cldwalker-hirb 0.1.2 → 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/CHANGELOG.rdoc +7 -0
- data/README.rdoc +27 -105
- data/Rakefile +3 -2
- data/VERSION.yml +2 -2
- data/lib/hirb/console.rb +31 -5
- data/lib/hirb/formatter.rb +199 -0
- data/lib/hirb/helpers/active_record_table.rb +2 -3
- data/lib/hirb/helpers/auto_table.rb +2 -2
- data/lib/hirb/helpers/object_table.rb +4 -4
- data/lib/hirb/helpers/table.rb +72 -19
- data/lib/hirb/menu.rb +47 -0
- data/lib/hirb/pager.rb +94 -0
- data/lib/hirb/util.rb +53 -2
- data/lib/hirb/view.rb +116 -140
- data/lib/hirb.rb +28 -3
- data/test/console_test.rb +12 -0
- data/test/formatter_test.rb +172 -0
- data/test/menu_test.rb +94 -0
- data/test/pager_test.rb +164 -0
- data/test/table_test.rb +100 -21
- data/test/test_helper.rb +30 -0
- data/test/util_test.rb +53 -18
- data/test/view_test.rb +98 -151
- metadata +28 -15
data/test/pager_test.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
module Hirb
|
4
|
+
class PagerTest < Test::Unit::TestCase
|
5
|
+
def pager; View.pager; end
|
6
|
+
|
7
|
+
def create_pageable_string(inspect_mode=false, size={})
|
8
|
+
size = {:width=>pager.width, :height=>pager.height}.merge(size)
|
9
|
+
seed = inspect_mode ? "a" : "a\n"
|
10
|
+
if inspect_mode
|
11
|
+
seed * (size[:width] * size[:height] + 1)
|
12
|
+
else
|
13
|
+
seed * (size[:height] + 1)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
test "command_pager sets pager_command when command exists" do
|
18
|
+
Util.expects(:command_exists?).returns(true)
|
19
|
+
Pager.expects(:basic_pager)
|
20
|
+
Pager.command_pager 'blah', :pager_command=>'less'
|
21
|
+
end
|
22
|
+
|
23
|
+
test "command_pager doesn't set pager_command when command doesn't exist" do
|
24
|
+
Util.expects(:command_exists?).returns(false)
|
25
|
+
Pager.expects(:basic_pager).never
|
26
|
+
Pager.command_pager 'blah', :pager_command=>'moreless'
|
27
|
+
end
|
28
|
+
|
29
|
+
context "default_pager" do
|
30
|
+
before(:all) { reset_config; Hirb.enable {|c| c.pager = true}}
|
31
|
+
before(:each) { View.pager = nil; Pager.stubs(:pager_command).returns(nil) }
|
32
|
+
after(:all) { Hirb.disable }
|
33
|
+
|
34
|
+
test "pages once in normal mode" do
|
35
|
+
$stdin.expects(:gets).returns("\n")
|
36
|
+
output = capture_stdout { pager.page(create_pageable_string, false) }
|
37
|
+
output.include?('quit').should be(true)
|
38
|
+
output.include?('finished').should be(true)
|
39
|
+
end
|
40
|
+
|
41
|
+
test "doesn't page in normal mode" do
|
42
|
+
$stdin.expects(:gets).never
|
43
|
+
output = capture_stdout { pager.page("a\n", false) }
|
44
|
+
output.include?("a\n=== Pager finished. ===\n").should be(true)
|
45
|
+
end
|
46
|
+
|
47
|
+
test "pages once in inspect mode" do
|
48
|
+
$stdin.expects(:gets).returns("\n")
|
49
|
+
output = capture_stdout { pager.page(create_pageable_string(true), true) }
|
50
|
+
output.include?('quit').should be(true)
|
51
|
+
output.include?('finished').should be(true)
|
52
|
+
end
|
53
|
+
|
54
|
+
test "doesn't page in inspect mode" do
|
55
|
+
$stdin.expects(:gets).never
|
56
|
+
output = capture_stdout { pager.page("a", true) }
|
57
|
+
output.include?("a\n=== Pager finished. ===\n").should be(true)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "pager" do
|
62
|
+
before(:all) { reset_config; Hirb.enable }
|
63
|
+
before(:each) { View.pager = nil; View.formatter = nil }
|
64
|
+
after(:all) { Hirb.disable }
|
65
|
+
|
66
|
+
def irb_eval(string)
|
67
|
+
context_stub = stub(:last_value=>string)
|
68
|
+
::IRB::Irb.new(context_stub).output_value
|
69
|
+
end
|
70
|
+
|
71
|
+
# this mode is called within @irb.output_value
|
72
|
+
context "in inspect_mode" do
|
73
|
+
test "activates when output is wide enough" do
|
74
|
+
output = create_pageable_string(true)
|
75
|
+
pager.expects(:page).with(output.inspect, true)
|
76
|
+
View.expects(:render_output).returns(false)
|
77
|
+
irb_eval output
|
78
|
+
end
|
79
|
+
|
80
|
+
test "doesn't activate when output isn't wide enough" do
|
81
|
+
pager.expects(:page).never
|
82
|
+
View.expects(:render_output).returns(false)
|
83
|
+
irb_eval("a")
|
84
|
+
end
|
85
|
+
|
86
|
+
test "activates with an explicit width" do
|
87
|
+
View.config[:width] = 10
|
88
|
+
output = create_pageable_string true, :width=>10
|
89
|
+
pager.expects(:page).with(output.inspect, true)
|
90
|
+
View.expects(:render_output).returns(false)
|
91
|
+
irb_eval output
|
92
|
+
end
|
93
|
+
|
94
|
+
test "activates default_pager when pager command is invalid" do
|
95
|
+
Pager.expects(:pager_command).returns(nil)
|
96
|
+
output = create_pageable_string(true)
|
97
|
+
Pager.expects(:default_pager).with(output.inspect, anything)
|
98
|
+
View.expects(:render_output).returns(false)
|
99
|
+
capture_stdout { irb_eval output }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# this mode is called within Hirb::View.render_output
|
104
|
+
context "in normal mode" do
|
105
|
+
test "activates when output is long enough" do
|
106
|
+
output = create_pageable_string
|
107
|
+
View.formatter.expects(:format_output).returns(output)
|
108
|
+
pager.expects(:page).with(output, false)
|
109
|
+
irb_eval(output)
|
110
|
+
end
|
111
|
+
|
112
|
+
test "doesn't activate when output isn't long enough" do
|
113
|
+
output = "a\n"
|
114
|
+
View.formatter.expects(:format_output).returns(output)
|
115
|
+
pager.expects(:page).never
|
116
|
+
capture_stdout { irb_eval(output) }
|
117
|
+
end
|
118
|
+
|
119
|
+
test "activates with an explicit height" do
|
120
|
+
View.config[:height] = 100
|
121
|
+
output = create_pageable_string false, :height=>100
|
122
|
+
View.formatter.expects(:format_output).returns(output)
|
123
|
+
pager.expects(:page).with(output, false)
|
124
|
+
irb_eval(output)
|
125
|
+
end
|
126
|
+
|
127
|
+
test "activates default_pager when pager_command is invalid" do
|
128
|
+
Pager.expects(:pager_command).returns(nil)
|
129
|
+
output = create_pageable_string
|
130
|
+
Pager.expects(:default_pager).with(output, anything)
|
131
|
+
View.formatter.expects(:format_output).returns(output)
|
132
|
+
capture_stdout { irb_eval output }
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
test "activates pager_command with valid pager_command option" do
|
137
|
+
View.config[:pager_command] = "less"
|
138
|
+
View.expects(:render_output).returns(false)
|
139
|
+
Util.expects(:command_exists?).returns(true)
|
140
|
+
Pager.expects(:command_pager)
|
141
|
+
irb_eval create_pageable_string(true)
|
142
|
+
View.config[:pager_command] = nil
|
143
|
+
end
|
144
|
+
|
145
|
+
test "activates pager_command with pager_command option that has command options" do
|
146
|
+
View.config[:pager_command] = "less -r"
|
147
|
+
View.expects(:render_output).returns(false)
|
148
|
+
Util.expects(:command_exists?).with('less').returns(true)
|
149
|
+
Pager.expects(:command_pager)
|
150
|
+
irb_eval create_pageable_string(true)
|
151
|
+
View.config[:pager_command] = nil
|
152
|
+
end
|
153
|
+
|
154
|
+
test "doesn't activate pager_command with invalid pager_command option" do
|
155
|
+
View.config[:pager_command] = "moreless"
|
156
|
+
View.expects(:render_output).returns(false)
|
157
|
+
Util.expects(:command_exists?).returns(false)
|
158
|
+
Pager.expects(:default_pager)
|
159
|
+
irb_eval create_pageable_string(true)
|
160
|
+
View.config[:pager_command] = nil
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
data/test/table_test.rb
CHANGED
@@ -4,6 +4,7 @@ class Hirb::Helpers::TableTest < Test::Unit::TestCase
|
|
4
4
|
def table(*args)
|
5
5
|
Hirb::Helpers::Table.render(*args)
|
6
6
|
end
|
7
|
+
before(:all) { reset_config }
|
7
8
|
|
8
9
|
context "basic table" do
|
9
10
|
test "renders" do
|
@@ -89,6 +90,12 @@ class Hirb::Helpers::TableTest < Test::Unit::TestCase
|
|
89
90
|
TABLE
|
90
91
|
table([[1,2,3]], :fields=>[0,2]).should == expected_table
|
91
92
|
end
|
93
|
+
|
94
|
+
test "fields and number options copies fields option and does not modify it" do
|
95
|
+
options = {:fields=>[:f1], :number=>true}
|
96
|
+
table({:f1=>1, :f2=>2}, options)
|
97
|
+
options[:fields].should == [:f1]
|
98
|
+
end
|
92
99
|
|
93
100
|
test "invalid fields option renders empty columns" do
|
94
101
|
expected_table = <<-TABLE.unindent
|
@@ -141,11 +148,11 @@ class Hirb::Helpers::TableTest < Test::Unit::TestCase
|
|
141
148
|
|
142
149
|
test "max_width option renders" do
|
143
150
|
expected_table = <<-TABLE.unindent
|
144
|
-
|
145
|
-
| a
|
146
|
-
|
147
|
-
|
|
148
|
-
|
151
|
+
+-----------+---+-----------+
|
152
|
+
| a | b | c |
|
153
|
+
+-----------+---+-----------+
|
154
|
+
| AAAAAA... | 2 | CCCCCC... |
|
155
|
+
+-----------+---+-----------+
|
149
156
|
1 row in set
|
150
157
|
TABLE
|
151
158
|
table([{:a=> "A" * 50, :b=>2, :c=>"C"*10}], :max_width=>30).should == expected_table
|
@@ -163,18 +170,19 @@ class Hirb::Helpers::TableTest < Test::Unit::TestCase
|
|
163
170
|
table([{:a=> "A" * 50, :b=>2, :c=>"C"*10}], :max_width=>nil).should == expected_table
|
164
171
|
end
|
165
172
|
|
166
|
-
test "global
|
173
|
+
test "global width renders" do
|
167
174
|
expected_table = <<-TABLE.unindent
|
168
|
-
|
169
|
-
| a
|
170
|
-
|
171
|
-
|
|
172
|
-
|
175
|
+
+-----------+---+-----------+
|
176
|
+
| a | b | c |
|
177
|
+
+-----------+---+-----------+
|
178
|
+
| AAAAAA... | 2 | CCCCCC... |
|
179
|
+
+-----------+---+-----------+
|
173
180
|
1 row in set
|
174
181
|
TABLE
|
175
|
-
Hirb::
|
182
|
+
Hirb::View.load_config
|
183
|
+
Hirb::View.resize(30)
|
176
184
|
table([{:a=> "A" * 50, :b=>2, :c=>"C"*10}]).should == expected_table
|
177
|
-
|
185
|
+
reset_config
|
178
186
|
end
|
179
187
|
|
180
188
|
test "headers option and headers longer than fields renders" do
|
@@ -201,7 +209,7 @@ class Hirb::Helpers::TableTest < Test::Unit::TestCase
|
|
201
209
|
table([{:a=> "A", :b=>2}], :headers=>{:a=>"field A"}, :field_lengths=>{:a=>5}).should == expected_table
|
202
210
|
end
|
203
211
|
|
204
|
-
test "
|
212
|
+
test "headers option as an array renders" do
|
205
213
|
expected_table = <<-TABLE.unindent
|
206
214
|
+---+---+
|
207
215
|
| A | B |
|
@@ -214,11 +222,37 @@ class Hirb::Helpers::TableTest < Test::Unit::TestCase
|
|
214
222
|
table([[1,2], [3,4]], :headers=>['A', 'B']).should == expected_table
|
215
223
|
end
|
216
224
|
|
225
|
+
test "filters option renders" do
|
226
|
+
expected_table = <<-TABLE.unindent
|
227
|
+
+-----------+---+
|
228
|
+
| 0 | 1 |
|
229
|
+
+-----------+---+
|
230
|
+
| s,o,m,e | 2 |
|
231
|
+
| t,h,i,n,g | 1 |
|
232
|
+
+-----------+---+
|
233
|
+
2 rows in set
|
234
|
+
TABLE
|
235
|
+
table([['some', {:num=>2}], ['thing', {:num=>1}]], :filters=>{0=>lambda {|e| e.split("").join(",")},
|
236
|
+
1=>[:[], :num]}).should == expected_table
|
237
|
+
end
|
238
|
+
|
239
|
+
test "number option renders" do
|
240
|
+
expected_table = <<-TABLE.unindent
|
241
|
+
+--------+---+---+
|
242
|
+
| number | 0 | 1 |
|
243
|
+
+--------+---+---+
|
244
|
+
| 1 | a | b |
|
245
|
+
| 2 | c | d |
|
246
|
+
+--------+---+---+
|
247
|
+
2 rows in set
|
248
|
+
TABLE
|
249
|
+
table([['a','b'], ['c', 'd']], :number=>true).should == expected_table
|
250
|
+
end
|
217
251
|
end
|
218
252
|
|
219
253
|
context "object table" do
|
220
254
|
before(:all) {
|
221
|
-
@pets = [stub(:name=>'rufus', :age=>7), stub(:name=>'alf', :age=>101)]
|
255
|
+
@pets = [stub(:name=>'rufus', :age=>7, :to_s=>'rufus'), stub(:name=>'alf', :age=>101, :to_s=>'alf')]
|
222
256
|
}
|
223
257
|
test "renders" do
|
224
258
|
expected_table = <<-TABLE.unindent
|
@@ -233,14 +267,38 @@ class Hirb::Helpers::TableTest < Test::Unit::TestCase
|
|
233
267
|
Hirb::Helpers::ObjectTable.render(@pets, :fields=>[:name, :age]).should == expected_table
|
234
268
|
end
|
235
269
|
|
236
|
-
test "with no options
|
237
|
-
|
270
|
+
test "with no options defaults to to_s field" do
|
271
|
+
expected_table = <<-TABLE.unindent
|
272
|
+
+-------+
|
273
|
+
| value |
|
274
|
+
+-------+
|
275
|
+
| rufus |
|
276
|
+
| alf |
|
277
|
+
+-------+
|
278
|
+
2 rows in set
|
279
|
+
TABLE
|
280
|
+
Hirb::Helpers::ObjectTable.render(@pets).should == expected_table
|
281
|
+
end
|
282
|
+
|
283
|
+
test "renders simple arrays" do
|
284
|
+
expected_table = <<-TABLE.unindent
|
285
|
+
+-------+
|
286
|
+
| value |
|
287
|
+
+-------+
|
288
|
+
| 1 |
|
289
|
+
| 2 |
|
290
|
+
| 3 |
|
291
|
+
| 4 |
|
292
|
+
+-------+
|
293
|
+
4 rows in set
|
294
|
+
TABLE
|
295
|
+
Hirb::Helpers::ObjectTable.render([1,2,3,4]).should == expected_table
|
238
296
|
end
|
239
297
|
end
|
240
298
|
|
241
299
|
context "activerecord table" do
|
242
300
|
before(:all) {
|
243
|
-
@pets = [stub(:name=>'rufus', :age=>7, :
|
301
|
+
@pets = [stub(:name=>'rufus', :age=>7, :class=>mock(:column_names=>[:age, :name])), stub(:name=>'alf', :age=>101)]
|
244
302
|
}
|
245
303
|
test "renders" do
|
246
304
|
expected_table = <<-TABLE.unindent
|
@@ -255,9 +313,30 @@ class Hirb::Helpers::TableTest < Test::Unit::TestCase
|
|
255
313
|
Hirb::Helpers::ActiveRecordTable.render(@pets).should == expected_table
|
256
314
|
end
|
257
315
|
end
|
258
|
-
|
259
|
-
test "restrict_field_lengths
|
316
|
+
|
317
|
+
test "restrict_field_lengths ensures columns total doesn't exceed max width" do
|
318
|
+
@table = Hirb::Helpers::Table.new([{:f1=>'f1', :f2=>'2', :f3=>'3', :f4=>'4'}])
|
319
|
+
field_lengths = {:f1=>135, :f2=>45, :f3=>4, :f4=>55}
|
320
|
+
width = 195
|
321
|
+
@table.restrict_field_lengths(field_lengths, width)
|
322
|
+
field_lengths.values.inject {|a,e| a+=e}.should <= width
|
323
|
+
end
|
324
|
+
|
325
|
+
test "restrict_field_lengths sets columns by relative lengths" do
|
326
|
+
@table = Hirb::Helpers::Table.new([{:a=>'a', :b=>'b', :c=>'c'}])
|
327
|
+
field_lengths = {:a=>30, :b=>30, :c=>40}
|
328
|
+
width = 60
|
329
|
+
@table.restrict_field_lengths(field_lengths, width)
|
330
|
+
field_lengths.values.inject {|a,e| a+=e}.should <= width
|
331
|
+
field_lengths.values.uniq.size.should_not == 1
|
332
|
+
end
|
333
|
+
|
334
|
+
test "restrict_field_lengths sets all columns equal when no long_field and relative methods don't work" do
|
260
335
|
@table = Hirb::Helpers::Table.new([{:field1=>'f1', :field2=>'f2', :field3=>'f3'}])
|
261
|
-
|
336
|
+
field_lengths = {:field1=>10, :field2=>15, :field3=>100}
|
337
|
+
width = 20
|
338
|
+
@table.restrict_field_lengths(field_lengths, width)
|
339
|
+
field_lengths.values.inject {|a,e| a+=e}.should <= width
|
340
|
+
field_lengths.values.uniq.size.should == 1
|
262
341
|
end
|
263
342
|
end
|
data/test/test_helper.rb
CHANGED
@@ -7,6 +7,26 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
7
7
|
require 'hirb'
|
8
8
|
|
9
9
|
class Test::Unit::TestCase
|
10
|
+
# set these to avoid invoking stty multiple times which doubles test suite running time
|
11
|
+
ENV["LINES"] = ENV["COLUMNS"] = "20"
|
12
|
+
def reset_terminal_size
|
13
|
+
ENV["LINES"] = ENV["COLUMNS"] = "20"
|
14
|
+
end
|
15
|
+
|
16
|
+
def capture_stdout(&block)
|
17
|
+
original_stdout = $stdout
|
18
|
+
$stdout = fake = StringIO.new
|
19
|
+
begin
|
20
|
+
yield
|
21
|
+
ensure
|
22
|
+
$stdout = original_stdout
|
23
|
+
end
|
24
|
+
fake.string
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset_config
|
28
|
+
Hirb::View.instance_eval "@config = nil"
|
29
|
+
end
|
10
30
|
end
|
11
31
|
|
12
32
|
class String
|
@@ -14,4 +34,14 @@ class String
|
|
14
34
|
regex = num ? /^\s{#{num}}/ : /^\s*/
|
15
35
|
gsub(regex, '').chomp
|
16
36
|
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# mocks IRB for View + Pager
|
40
|
+
module ::IRB
|
41
|
+
class Irb
|
42
|
+
def initialize(context)
|
43
|
+
@context = context
|
44
|
+
end
|
45
|
+
def output_value; end
|
46
|
+
end
|
17
47
|
end
|
data/test/util_test.rb
CHANGED
@@ -1,21 +1,56 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
{:output=>{:
|
3
|
+
module Hirb
|
4
|
+
class UtilTest < Test::Unit::TestCase
|
5
|
+
test "any_const_get returns nested class" do
|
6
|
+
Util.any_const_get("Test::Unit").should == ::Test::Unit
|
7
|
+
end
|
8
|
+
|
9
|
+
test "any_const_get returns nil for invalid class" do
|
10
|
+
Util.any_const_get("Basdfr").should == nil
|
11
|
+
end
|
12
|
+
|
13
|
+
test "any_const_get returns class when given class" do
|
14
|
+
Util.any_const_get(String).should == String
|
15
|
+
end
|
16
|
+
|
17
|
+
test "recursive_hash_merge merges" do
|
18
|
+
expected_hash = {:output=>{:fields=>["f1", "f2"], :method=>"blah"}, :key1=>"hash1", :key2=>"hash2"}
|
19
|
+
Util.recursive_hash_merge({:output=>{:fields=>%w{f1 f2}}, :key1=>'hash1'},
|
20
|
+
{:output=>{:method=>'blah'}, :key2=>'hash2'}).should == expected_hash
|
21
|
+
end
|
22
|
+
|
23
|
+
test "choose_from_array specifies range with -" do
|
24
|
+
Util.choose_from_array([1,2,3,4], '1-2,4').should == [1,2,4]
|
25
|
+
end
|
26
|
+
|
27
|
+
test "choose_from_array specifies range with .." do
|
28
|
+
Util.choose_from_array([1,2,3,4], '1 .. 2,4').should == [1,2,4]
|
29
|
+
end
|
30
|
+
|
31
|
+
test "choose_from_array chooses all with *" do
|
32
|
+
Util.choose_from_array([1,2,3,4], '*').should == [1,2,3,4]
|
33
|
+
end
|
34
|
+
|
35
|
+
test "choose_from_array ignores non-numerical input" do
|
36
|
+
Util.choose_from_array([1,2,3,4], 'a,2').should == [2]
|
37
|
+
end
|
38
|
+
|
39
|
+
test "choose_from_array ignores 0" do
|
40
|
+
Util.choose_from_array([1,2,3,4], '0,2').should == [2]
|
41
|
+
end
|
42
|
+
|
43
|
+
test "choose_from_array returns empty when empty input" do
|
44
|
+
Util.choose_from_array([1,2,3,4], "\n").should == []
|
45
|
+
end
|
46
|
+
|
47
|
+
test "choose_from_array returns empty with an invalid range" do
|
48
|
+
Util.choose_from_array([1,2,3,4], "5").should == []
|
49
|
+
end
|
50
|
+
|
51
|
+
test "capture_stdout" do
|
52
|
+
string = "sweetness man"
|
53
|
+
Util.capture_stdout { puts string }.should == string + "\n"
|
54
|
+
end
|
20
55
|
end
|
21
|
-
end
|
56
|
+
end
|