epitools 0.5.1 → 0.5.2
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/Guardfile +16 -0
- data/VERSION +1 -1
- data/epitools.gemspec +13 -6
- data/lib/epitools.rb +48 -6
- data/lib/epitools/autoloads.rb +14 -3
- data/lib/epitools/browser.rb +8 -1
- data/lib/epitools/core_ext.rb +207 -0
- data/lib/epitools/core_ext/array.rb +98 -0
- data/lib/epitools/core_ext/enumerable.rb +306 -0
- data/lib/epitools/core_ext/hash.rb +201 -0
- data/lib/epitools/core_ext/numbers.rb +254 -0
- data/lib/epitools/core_ext/object.rb +195 -0
- data/lib/epitools/core_ext/string.rb +338 -0
- data/lib/epitools/core_ext/truthiness.rb +64 -0
- data/lib/epitools/iter.rb +22 -8
- data/lib/epitools/mimemagic.rb +0 -1
- data/lib/epitools/path.rb +149 -36
- data/lib/epitools/rash.rb +49 -37
- data/lib/epitools/term.rb +5 -1
- data/spec/{basetypes_spec.rb → core_ext_spec.rb} +190 -37
- data/spec/iter_spec.rb +9 -27
- data/spec/path_spec.rb +104 -46
- data/spec/permutations_spec.rb +3 -2
- data/spec/rash_spec.rb +21 -7
- data/spec/spec_helper.rb +36 -5
- metadata +34 -12
- data/lib/epitools/basetypes.rb +0 -1135
- data/lib/epitools/string_to_proc.rb +0 -78
data/lib/epitools/rash.rb
CHANGED
@@ -14,6 +14,7 @@ class Rash
|
|
14
14
|
def initialize(initial={})
|
15
15
|
@hash = {}
|
16
16
|
@regexes = []
|
17
|
+
@ranges = []
|
17
18
|
@regex_counts = Hash.new(0)
|
18
19
|
@optimize_every = 500
|
19
20
|
@lookups = 0
|
@@ -21,59 +22,70 @@ class Rash
|
|
21
22
|
update(initial)
|
22
23
|
end
|
23
24
|
|
25
|
+
def update(other)
|
26
|
+
for key, value in other
|
27
|
+
self[key] = value
|
28
|
+
end
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
24
32
|
def []=(key, value)
|
25
|
-
|
33
|
+
case key
|
34
|
+
when Regexp
|
26
35
|
#key = normalize_regex(key) # this used to just do: /#{regexp}/
|
27
36
|
@regexes << key
|
37
|
+
when Range
|
38
|
+
@ranges << key
|
28
39
|
end
|
29
40
|
@hash[key] = value
|
30
41
|
end
|
31
42
|
|
32
|
-
|
33
|
-
|
43
|
+
#
|
44
|
+
# Return the first thing that matches the key.
|
45
|
+
#
|
46
|
+
def [](key)
|
47
|
+
all(key).first
|
34
48
|
end
|
35
49
|
|
36
|
-
|
37
|
-
|
38
|
-
|
50
|
+
#
|
51
|
+
# Return everything that matches the query.
|
52
|
+
#
|
53
|
+
def all(query)
|
54
|
+
return Enumerator.new(self, :all, query) unless block_given?
|
39
55
|
|
40
|
-
|
41
|
-
|
56
|
+
if @hash.include? query
|
57
|
+
yield @hash[query]
|
58
|
+
return
|
59
|
+
end
|
42
60
|
|
43
|
-
case
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
61
|
+
case query
|
62
|
+
when String
|
63
|
+
optimize_if_necessary!
|
64
|
+
@regexes.each do |regex|
|
65
|
+
if match = regex.match(query)
|
66
|
+
@regex_counts[regex] += 1
|
67
|
+
value = @hash[regex]
|
68
|
+
if value.responds_to? :call
|
69
|
+
yield value.call(match)
|
70
|
+
else
|
71
|
+
yield value
|
54
72
|
end
|
55
73
|
end
|
56
|
-
|
57
|
-
when Regexp
|
58
|
-
|
59
|
-
matches = search_strings(key)
|
60
|
-
|
61
|
-
if matches.any?
|
62
|
-
return matches
|
63
|
-
end
|
74
|
+
end
|
64
75
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
76
|
+
when Integer
|
77
|
+
@ranges.each do |range|
|
78
|
+
yield @hash[range] if range.include? query
|
79
|
+
end
|
80
|
+
|
81
|
+
when Regexp
|
82
|
+
# TODO: this doesn't seem very useful. should I ditch it? let me know!
|
83
|
+
@hash.each do |key,val|
|
84
|
+
yield val if key.is_a? String and query =~ key
|
85
|
+
end
|
71
86
|
|
72
|
-
def update(other)
|
73
|
-
for key, value in other
|
74
|
-
self[key] = value
|
75
87
|
end
|
76
|
-
|
88
|
+
|
77
89
|
end
|
78
90
|
|
79
91
|
def method_missing(*args, &block)
|
data/lib/epitools/term.rb
CHANGED
@@ -54,7 +54,7 @@ module Term
|
|
54
54
|
|
55
55
|
def initialize(data, options={})
|
56
56
|
@data = data.map(&:to_s)
|
57
|
-
@strip_color = options[:strip_color] || options[:strip_ansi]
|
57
|
+
@strip_color = options[:ansi] || options[:colorized] || options[:colored] || options[:strip_color] || options[:strip_ansi]
|
58
58
|
|
59
59
|
if strip_color
|
60
60
|
@max_size = @data.map { |e| e.strip_color.size }.max
|
@@ -116,6 +116,10 @@ module Term
|
|
116
116
|
render sliced_into(num_columns)
|
117
117
|
end
|
118
118
|
|
119
|
+
def to_s
|
120
|
+
by_rows
|
121
|
+
end
|
122
|
+
|
119
123
|
def render(rows, options={})
|
120
124
|
num_cols = rows.first.size
|
121
125
|
result = []
|
@@ -17,27 +17,35 @@ describe Object do
|
|
17
17
|
c = Cookie.new; c.size = 10; c.chips = 200
|
18
18
|
w = c.with(:chips=>50)
|
19
19
|
|
20
|
-
w.size.should
|
20
|
+
w.size.should == c.size
|
21
21
|
w.chips.should_not == c.chips
|
22
|
-
w.should_not
|
22
|
+
w.should_not === c
|
23
23
|
end
|
24
24
|
|
25
25
|
it "in?" do
|
26
|
-
5.in?([1,2,3,4,5,6]).should
|
27
|
-
5.in?(1..10).should
|
28
|
-
5.in?(20..30).should
|
26
|
+
5.in?([1,2,3,4,5,6]).should == true
|
27
|
+
5.in?(1..10).should == true
|
28
|
+
5.in?(20..30).should == false
|
29
29
|
"butt".in?("butts!!!").should == true
|
30
30
|
end
|
31
31
|
|
32
|
-
it "
|
32
|
+
it "times" do
|
33
33
|
lambda {
|
34
|
-
|
34
|
+
time("time test") { x = 10 }
|
35
35
|
}.should_not raise_error
|
36
36
|
|
37
37
|
lambda {
|
38
|
-
|
38
|
+
time("time test") { raise "ERROR" }
|
39
39
|
}.should raise_error
|
40
40
|
end
|
41
|
+
|
42
|
+
it "benches" do
|
43
|
+
lambda { bench { rand } }.should_not raise_error
|
44
|
+
lambda { bench(20) { rand } }.should_not raise_error
|
45
|
+
lambda { bench }.should raise_error
|
46
|
+
lambda { bench(:rand => proc { rand }, :notrand => proc { 1 }) }.should_not raise_error
|
47
|
+
lambda { bench(200, :rand => proc { rand }, :notrand => proc { 1 }) }.should_not raise_error
|
48
|
+
end
|
41
49
|
|
42
50
|
it "trys" do
|
43
51
|
s = Struct.new(:a,:b).new
|
@@ -53,21 +61,21 @@ describe Object do
|
|
53
61
|
|
54
62
|
def s.test(a); a; end
|
55
63
|
|
56
|
-
s.test(1).should
|
57
|
-
s.try(:test, 1).should
|
64
|
+
s.test(1).should == 1
|
65
|
+
s.try(:test, 1).should == 1
|
58
66
|
|
59
67
|
lambda { s.test }.should raise_error
|
60
68
|
lambda { s.try(:test) }.should raise_error
|
61
69
|
|
62
70
|
def s.blocky; yield; end
|
63
|
-
|
64
|
-
s.blocky{ 1 }.should
|
65
|
-
s.try(:blocky){ 1 }.should
|
71
|
+
|
72
|
+
s.blocky{ 1 }.should == 1
|
73
|
+
s.try(:blocky){ 1 }.should == 1
|
66
74
|
s.try(:nonexistant){ 1 }.should == nil
|
67
75
|
end
|
68
76
|
|
69
77
|
it "nots" do
|
70
|
-
10.even?.should
|
78
|
+
10.even?.should == true
|
71
79
|
10.not.even?.should == false
|
72
80
|
end
|
73
81
|
|
@@ -123,33 +131,47 @@ end
|
|
123
131
|
describe Numeric do
|
124
132
|
|
125
133
|
it "commatizes" do
|
126
|
-
123.commatize.should
|
127
|
-
1234.commatize.should
|
128
|
-
12983287123.commatize.should
|
129
|
-
-12983287123.commatize.should
|
134
|
+
123.commatize.should == "123"
|
135
|
+
1234.commatize.should == "1,234"
|
136
|
+
12983287123.commatize.should == "12,983,287,123"
|
137
|
+
-12983287123.commatize.should == "-12,983,287,123"
|
130
138
|
-12983287123.4411.commatize.should == "-12,983,287,123.4411"
|
131
139
|
end
|
132
140
|
|
133
141
|
it "does time things" do
|
134
|
-
1.second.should
|
135
|
-
1.minute.should
|
136
|
-
2.minutes.should
|
137
|
-
2.hours.should
|
138
|
-
2.5.days.should
|
139
|
-
|
140
|
-
5.days.ago.to_i.should
|
141
|
-
1.year.ago.year.should
|
142
|
+
1.second.should == 1
|
143
|
+
1.minute.should == 60
|
144
|
+
2.minutes.should == 120
|
145
|
+
2.hours.should == 120*60
|
146
|
+
2.5.days.should == 3600*24*2.5
|
147
|
+
|
148
|
+
5.days.ago.to_i.should == (Time.now - 5.days).to_i
|
149
|
+
1.year.ago.year.should == Time.now.year - 1
|
142
150
|
5.days.from_now.to_i.should == (Time.now + 5.days).to_i
|
143
151
|
end
|
144
152
|
|
145
|
-
|
153
|
+
it "thingses" do
|
154
|
+
10.things.should == [0,1,2,3,4,5,6,7,8,9]
|
155
|
+
4.things {|n| n * 5 }.should == [0,5,10,15]
|
156
|
+
-1.things.should == []
|
157
|
+
end
|
146
158
|
|
159
|
+
it "maths" do
|
160
|
+
10.cos.should == Math.cos(10)
|
161
|
+
20.sin.should == Math.sin(20)
|
162
|
+
1.5.exp.should == Math.exp(1.5)
|
163
|
+
|
164
|
+
253.log(5).should == Math.log(253,5)
|
165
|
+
(2**(4212.log(2))).should == 4212.0
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
147
169
|
|
148
170
|
describe String do
|
149
171
|
|
150
172
|
it "rot13s" do
|
151
173
|
message = "Unbreakable Code"
|
152
|
-
message.rot13.should_not
|
174
|
+
message.rot13.should_not == message
|
153
175
|
message.rot13.rot13.should == message
|
154
176
|
end
|
155
177
|
|
@@ -205,6 +227,14 @@ describe String do
|
|
205
227
|
"blahblahblah".startswith("blah").should == true
|
206
228
|
"blahblahblah".endswith("blah").should == true
|
207
229
|
end
|
230
|
+
|
231
|
+
it "amounts" do
|
232
|
+
"cookie".amount(5).should == "5 cookies"
|
233
|
+
"cookie".amount(0).should == "0 cookies"
|
234
|
+
"shirt".amount(17).should == "17 shirts"
|
235
|
+
"dollar".amount(-10).should == "-10 dollars"
|
236
|
+
"love".amount(1).should == "1 love"
|
237
|
+
end
|
208
238
|
|
209
239
|
end
|
210
240
|
|
@@ -304,6 +334,11 @@ describe Array do
|
|
304
334
|
(b/2).should == [[1,2],[3,4]]
|
305
335
|
end
|
306
336
|
|
337
|
+
it "includes?s" do
|
338
|
+
[:a, :b, :c].includes?(:c).should == true
|
339
|
+
[:a, :b, :c].includes?(5).should == false
|
340
|
+
end
|
341
|
+
|
307
342
|
end
|
308
343
|
|
309
344
|
|
@@ -346,10 +381,17 @@ describe Enumerable do
|
|
346
381
|
[1,1,3,3].average.should == 2.0
|
347
382
|
end
|
348
383
|
|
349
|
-
it "
|
350
|
-
[[1,2],[3,4]].
|
351
|
-
[1,2,3,4].
|
352
|
-
[[],[],1,2,3,4].
|
384
|
+
it "maps deeply" do
|
385
|
+
[[1,2],[3,4]].deep_map {|e| e ** 2}.should == [[1,4],[9,16]]
|
386
|
+
[1,2,3,4].deep_map {|e| e ** 2}.should == [1,4,9,16]
|
387
|
+
[[],[],1,2,3,4].deep_map {|e| e ** 2}.should == [[], [], 1, 4, 9, 16]
|
388
|
+
end
|
389
|
+
|
390
|
+
it "selects deeply" do
|
391
|
+
[[1,2],[3,4]].deep_select {|e| e % 2 == 0 }.should == [2,4]
|
392
|
+
{1=>2, 3=>{4=>5, 6=>7}}.deep_select {|k,v| k == 1 }.should == {1=>2}
|
393
|
+
#[1,2,3,4].deep_select {|e| e ** 2}.should == [1,4,9,16]
|
394
|
+
#[[],[],1,2,3,4].deep_select {|e| e ** 2}.should == [[], [], 1, 4, 9, 16]
|
353
395
|
end
|
354
396
|
|
355
397
|
it "foldl's" do
|
@@ -374,6 +416,12 @@ describe Enumerable do
|
|
374
416
|
result = a.group_neighbours_by { |a,b| b-a <= 1 }
|
375
417
|
result.should == [[1,2],[5,6,7],[10,11],[13]]
|
376
418
|
end
|
419
|
+
|
420
|
+
it "includes?s" do
|
421
|
+
[:a, :b, :c].to_enum.includes?(:c).should == true
|
422
|
+
[:a, :b, :c].to_enum.includes?(5).should == false
|
423
|
+
end
|
424
|
+
|
377
425
|
end
|
378
426
|
|
379
427
|
describe Hash do
|
@@ -384,24 +432,25 @@ describe Hash do
|
|
384
432
|
|
385
433
|
it "maps keys" do
|
386
434
|
h = @h.map_keys{|k| k.upcase}
|
387
|
-
h.keys.should
|
435
|
+
h.keys.should == @h.keys.map{|k| k.upcase}
|
388
436
|
h.values.should == @h.values
|
389
437
|
|
390
438
|
h.map_keys! { 1 }
|
391
|
-
h.keys.should
|
439
|
+
h.keys.should == [1]
|
392
440
|
end
|
393
441
|
|
394
442
|
it "maps values" do
|
395
443
|
h = @h.map_values{|v| v.upcase}
|
444
|
+
|
396
445
|
h.values.should == @h.values.map{|v| v.upcase}
|
397
|
-
h.keys.should
|
398
|
-
h.map_values!{ 1 }
|
446
|
+
h.keys.should == @h.keys
|
447
|
+
h.map_values! { 1 }
|
399
448
|
h.values.should == [1,1]
|
400
449
|
end
|
401
450
|
|
402
451
|
it "mkdir_p's and trees" do
|
403
452
|
h = {}
|
404
|
-
h.mkdir_p(["a", "b", "c"]).should
|
453
|
+
h.mkdir_p(["a", "b", "c"]).should == {"a"=>{"b"=>{"c"=>{}}}}
|
405
454
|
h.mkdir_p(["a", "b", "whoa"]).should == {"a"=>{"b"=>{"c"=>{}, "whoa"=>{}}}}
|
406
455
|
|
407
456
|
lambda {
|
@@ -416,6 +465,63 @@ describe Hash do
|
|
416
465
|
params.to_query.in?(["donkeys=7&stubborn=true", "stubborn=true&donkeys=7"]).should == true
|
417
466
|
end
|
418
467
|
|
468
|
+
it "includes?s and key?s" do
|
469
|
+
@h.key?("key1").should == true
|
470
|
+
@h.includes?("key1").should == true
|
471
|
+
end
|
472
|
+
|
473
|
+
end
|
474
|
+
|
475
|
+
|
476
|
+
describe Time do
|
477
|
+
it "time in words" do
|
478
|
+
Time.now.in_words.should == "just now"
|
479
|
+
1.second.ago.in_words.should == "1 second ago"
|
480
|
+
2.seconds.ago.in_words.should == "2 seconds ago"
|
481
|
+
3.weeks.ago.in_words.should == "3 weeks ago"
|
482
|
+
4.5.weeks.ago.in_words.should == "1 month ago"
|
483
|
+
2.months.ago.in_words.should == "2 months ago"
|
484
|
+
2.years.ago.in_words.should == "2 years ago"
|
485
|
+
2.5.years.ago.in_words.should == "2 years ago"
|
486
|
+
|
487
|
+
2.5.years.from_now.in_words.should == "2 years from now"
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
|
492
|
+
describe Binding do
|
493
|
+
a = 1
|
494
|
+
b = proc { a }
|
495
|
+
|
496
|
+
b.binding.keys.should == [:a, :b]
|
497
|
+
b.binding.keys.should == b.binding.local_variables
|
498
|
+
|
499
|
+
b.binding[:a].should == 1
|
500
|
+
b.binding["a"].should == 1
|
501
|
+
b.binding[:b].should == b
|
502
|
+
|
503
|
+
b.binding[:a] = 5
|
504
|
+
b.binding[:a].should == 5
|
505
|
+
b.call.should == 5
|
506
|
+
end
|
507
|
+
|
508
|
+
describe Proc do
|
509
|
+
|
510
|
+
it "joins procs" do
|
511
|
+
a = proc { 1 } & proc { 2 }
|
512
|
+
a.call.should == [1,2]
|
513
|
+
|
514
|
+
a &= proc { 3 }
|
515
|
+
a.call.should == [[1,2],3]
|
516
|
+
end
|
517
|
+
|
518
|
+
it "chains procs" do
|
519
|
+
b = proc { 1 } | proc { |input| input + 1 }
|
520
|
+
b.call.should == 2
|
521
|
+
b = b.chain( proc { |input| input + 1 } )
|
522
|
+
b.call(1).should == 3
|
523
|
+
end
|
524
|
+
|
419
525
|
end
|
420
526
|
|
421
527
|
|
@@ -427,6 +533,14 @@ describe BasicObject do
|
|
427
533
|
|
428
534
|
end
|
429
535
|
|
536
|
+
describe Range do
|
537
|
+
|
538
|
+
it "generates random numbers" do
|
539
|
+
r = 1..10
|
540
|
+
50.times { r.includes?(r.rand).should == true }
|
541
|
+
end
|
542
|
+
|
543
|
+
end
|
430
544
|
|
431
545
|
describe "truthiness" do
|
432
546
|
|
@@ -449,6 +563,22 @@ describe "truthiness" do
|
|
449
563
|
|
450
564
|
end
|
451
565
|
|
566
|
+
describe "proper grammar" do
|
567
|
+
|
568
|
+
it "responds_to?" do
|
569
|
+
proc{}.responds_to?(:call).should == true
|
570
|
+
end
|
571
|
+
|
572
|
+
it "includes?" do
|
573
|
+
[1,2,3,4,5].includes?(5).should == true
|
574
|
+
end
|
575
|
+
|
576
|
+
it "is_an?" do
|
577
|
+
Object.new.is_an?(Object).should == true
|
578
|
+
end
|
579
|
+
|
580
|
+
end
|
581
|
+
|
452
582
|
|
453
583
|
describe "metaclass" do
|
454
584
|
|
@@ -460,3 +590,26 @@ describe "metaclass" do
|
|
460
590
|
|
461
591
|
end
|
462
592
|
|
593
|
+
|
594
|
+
describe "global methods" do
|
595
|
+
|
596
|
+
it "locals's" do
|
597
|
+
require 'binding_of_caller'
|
598
|
+
|
599
|
+
a = 5
|
600
|
+
b = 10
|
601
|
+
_what_ = :splunge
|
602
|
+
|
603
|
+
locals.should == {:a=>5, :b=>10}
|
604
|
+
end
|
605
|
+
|
606
|
+
end
|
607
|
+
|
608
|
+
describe "to_jsons and to_yamls" do
|
609
|
+
data = {"a"=>"b", "yes"=>true, "hello"=>[1,2,3,4,5]}
|
610
|
+
data.to_json.from_json.should == data
|
611
|
+
|
612
|
+
data = {:a=>"b", 1=>true, "hello"=>[1,2,3,4,5]}
|
613
|
+
data.to_yaml.from_yaml.should == data
|
614
|
+
end
|
615
|
+
|