facets 2.8.2 → 2.8.3
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/AUTHORS +13 -11
- data/HISTORY.rdoc +58 -0
- data/lib/core/facets/array/recursive.rb +91 -0
- data/lib/core/facets/array/recursively.rb +2 -2
- data/lib/core/facets/array/traverse.rb +23 -6
- data/lib/core/facets/enumerable/collisions.rb +1 -0
- data/lib/core/facets/enumerable/commonality.rb +4 -2
- data/lib/core/facets/enumerable/graph.rb +37 -1
- data/lib/core/facets/enumerable/mash.rb +1 -39
- data/lib/core/facets/enumerable/recursive.rb +75 -0
- data/lib/core/facets/enumerable/visit.rb +30 -0
- data/lib/core/facets/file/ext.rb +36 -0
- data/lib/core/facets/hash/graph.rb +18 -0
- data/lib/core/facets/hash/mash.rb +1 -18
- data/lib/core/facets/hash/recursive.rb +180 -0
- data/lib/core/facets/hash/recursive_merge.rb +6 -0
- data/lib/core/facets/hash/recursively.rb +2 -2
- data/lib/core/facets/hash/to_module.rb +26 -0
- data/lib/core/facets/hash/to_proc.rb +2 -2
- data/lib/core/facets/hash/traverse.rb +19 -13
- data/lib/core/facets/kernel/assign.rb +63 -0
- data/lib/core/facets/kernel/assign_from.rb +45 -0
- data/lib/core/facets/kernel/dup.rb +63 -0
- data/lib/core/facets/kernel/instance.rb +156 -0
- data/lib/core/facets/kernel/instance_assign.rb +1 -22
- data/lib/core/facets/kernel/meta_def.rb +4 -0
- data/lib/core/facets/kernel/populate.rb +1 -74
- data/lib/core/facets/kernel/set_from.rb +2 -0
- data/lib/core/facets/kernel/try_dup.rb +1 -0
- data/lib/core/facets/module/set.rb +36 -0
- data/lib/core/facets/objectspace/reflect.rb +45 -0
- data/lib/core/facets/struct/attributes.rb +6 -2
- data/lib/core/facets/symbol/op_div.rb +19 -0
- data/lib/core/facets/to_hash.rb +12 -0
- data/lib/more/facets/casting_hash.rb +172 -0
- data/lib/more/facets/pathname.rb +36 -0
- data/lib/more/facets/prepend.rb +57 -0
- data/lib/more/facets/random.rb +19 -3
- data/lib/more/facets/roman.rb +46 -153
- data/lib/more/facets/stash.rb +148 -33
- data/meta/released +1 -1
- data/meta/version +1 -1
- data/test/core/array/test_recursive.rb +18 -0
- data/test/core/enumerable/test_recursive.rb +18 -0
- data/test/core/file/test_ext.rb +31 -0
- data/test/core/hash/test_recursive.rb +23 -0
- data/test/core/hash/test_to_module.rb +21 -0
- data/test/core/kernel/test_assign.rb +57 -0
- data/test/core/kernel/test_assign_from.rb +20 -0
- data/test/more/test_prepend.rb +28 -0
- data/test/more/test_random.rb +40 -4
- metadata +39 -10
- data/lib/core/facets/kernel/instance_variables.rb +0 -97
- data/lib/more/facets/instance_eval.rb +0 -50
- data/lib/more/facets/ioredirect.rb +0 -77
- data/lib/more/facets/plugin_manager.rb +0 -50
- data/test/core/kernel/test_populate.rb +0 -46
data/AUTHORS
CHANGED
@@ -9,17 +9,19 @@
|
|
9
9
|
The following developers have recently contributed to the development of Facets.
|
10
10
|
They are held in the highest regard for their efforts.
|
11
11
|
|
12
|
-
*
|
13
|
-
*
|
14
|
-
*
|
15
|
-
*
|
16
|
-
*
|
17
|
-
*
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
12
|
+
* Lavir the Whiolet Improved Range#at_rand and added File#ext.
|
13
|
+
* Jean-Denis Vauguet Added Pathname#visit.
|
14
|
+
* Roger Pack Added generational depth to Class#descendants.
|
15
|
+
* Marco Otte-Witte Fixed return value of Kernel#extend.
|
16
|
+
* Mauro Tortonesi Fixed issues with duration.rb and date.rb.
|
17
|
+
* Sandor Szücs Fixes for String#align_right and #align_left.
|
18
|
+
* Tyler Rick Fixed bug in Time#hence and #ago.
|
19
|
+
* Brian Candler Provided Enumerator::Filter.
|
20
|
+
* Jeena Paradies Provided INI implementation.
|
21
|
+
* Robert Klemme Fix for Enumerable#mode.
|
22
|
+
* Daniel Schierbeck Speed imporvements to odd? and even?
|
23
|
+
* Ken Bloom For DictionaryMatcher class (class might be renamed in future).
|
24
|
+
* Matthew Harris Incorporated very useful Duration class.
|
23
25
|
|
24
26
|
== Recent Bug Reports
|
25
27
|
|
data/HISTORY.rdoc
CHANGED
@@ -1,5 +1,63 @@
|
|
1
1
|
= Facets Release History
|
2
2
|
|
3
|
+
== 2.8.3 / 2009-04-10
|
4
|
+
|
5
|
+
New release which makes a few adjustments in Kernel core extensions,
|
6
|
+
adds a few new extensions and additions, plus other small improvements.
|
7
|
+
The biggest change is the addition of Recusor, which is created via
|
8
|
+
Enumerable#recursive. This class is somewhat like Enumerator and
|
9
|
+
provides a number of recursive methods.
|
10
|
+
|
11
|
+
Changes:
|
12
|
+
|
13
|
+
* 9 New Core Extensions
|
14
|
+
|
15
|
+
* Enumerable#recursive provides a number of other recursive methods.
|
16
|
+
* Enumerable#visit can be used to recursively iterate any Enumerable.
|
17
|
+
* Module#set has been added (from Sinatra).
|
18
|
+
* Symbol#/ is added to be like String#/.
|
19
|
+
* Struct#to_h is added and will ultimately replace Struct#attributes.
|
20
|
+
* ObjectSpace#reflect routes method calls to Kernel context.
|
21
|
+
* Hash#to_module converts a hash to mixin module (Jay Fields).
|
22
|
+
* Kernel#dup! is same as #try_dup from extlib.
|
23
|
+
* Add File#ext which is a useful variation of #extname (Lavir the Whiolet).
|
24
|
+
|
25
|
+
* 3 Core Extensions Renamed
|
26
|
+
|
27
|
+
* renamed #set_from to #assign_from (alias remains until Kernel#set is considerd).
|
28
|
+
* rename #populate to #assign and improve.
|
29
|
+
* Kernel#instance_vars is now Kernel#instance and also more useful.
|
30
|
+
|
31
|
+
* 1 Core Deprecation
|
32
|
+
|
33
|
+
* Removed #instance_eval hack.
|
34
|
+
|
35
|
+
* 2 Core Bug Fixes
|
36
|
+
|
37
|
+
* #map_with_index now uses #each_with_index.
|
38
|
+
* #to_proc_with_response spelling correction.
|
39
|
+
|
40
|
+
* 1 Core Adjustment
|
41
|
+
|
42
|
+
* Aliased #metadef to #meta_def.
|
43
|
+
|
44
|
+
* 3 New More Libraries
|
45
|
+
|
46
|
+
* casting_hash.rb provides CastingHash class, a hash with flexible keys and values.
|
47
|
+
* prepend.rb allows for AOP-like inclusion of modules.
|
48
|
+
* roman.rb provides simple roman numeral extensions to String and Integer.
|
49
|
+
|
50
|
+
* 5 More Improvements
|
51
|
+
|
52
|
+
* Pathname#visit for iterating all entries beneath a path (chikamichi).
|
53
|
+
* Pathname#to_str, b/c Pathname is basically a type of String (from extlib).
|
54
|
+
* Range#at_rand in random.rb handles Float ranges (Lavir the Whiolet).
|
55
|
+
* FileUtils#cp_rx provides controlled copies.
|
56
|
+
* Stash class in stash.rb is improved and is now available as a stand-alone library.
|
57
|
+
* ioredirect.rb has been removed as IORedirect no longer worked.
|
58
|
+
* plugin_manager.rb has been removed. Use 'plugin' gem instead.
|
59
|
+
|
60
|
+
|
3
61
|
== 2.8.2 / 2009-02-22
|
4
62
|
|
5
63
|
This release fixes a bug by removing Numeric#size. Turns out that was a
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'facets/enumerable/recursive'
|
2
|
+
|
3
|
+
class Array
|
4
|
+
|
5
|
+
# Apply a block to array, and recursively apply that block
|
6
|
+
# to each subarray.
|
7
|
+
#
|
8
|
+
# arr = ["a", ["b", "c", nil], nil]
|
9
|
+
# arr.recursively{|a| a.compact! }
|
10
|
+
# => ["a", ["b", "c"]]
|
11
|
+
#
|
12
|
+
def recursive(opts={}, &block)
|
13
|
+
if block
|
14
|
+
a = inject([]) do |array, value|
|
15
|
+
if value.is_a?(Array)
|
16
|
+
array << value.recursive(&block)
|
17
|
+
else
|
18
|
+
array << value
|
19
|
+
end
|
20
|
+
array
|
21
|
+
end
|
22
|
+
yield a
|
23
|
+
else
|
24
|
+
Recursor.new(self, opts)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# In place form of #recursive.
|
29
|
+
|
30
|
+
def recursive!(&block)
|
31
|
+
r = recursive(&block)
|
32
|
+
raise TypeError unless Array === r
|
33
|
+
replace(r)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
#
|
38
|
+
class Recursor < ::Enumerable::Recursor
|
39
|
+
|
40
|
+
# Recursively iterate over the Array's elements.
|
41
|
+
# If an element is an Array or responds to #to_ary
|
42
|
+
# then it will be itereated over as well.
|
43
|
+
#
|
44
|
+
def each(&block)
|
45
|
+
if block_given?
|
46
|
+
@enum.each do |e|
|
47
|
+
if Array === e || e.respond_to?(:to_ary)
|
48
|
+
e.to_ary.recursive.each(&block)
|
49
|
+
else
|
50
|
+
block.call(e)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
else
|
54
|
+
to_enum(:each)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns a new array created by traversing the array and its
|
59
|
+
# sub-arrays, executing the given block on the elements.
|
60
|
+
#
|
61
|
+
# h = ["A", "B", ["X", "Y"]]
|
62
|
+
#
|
63
|
+
# g = h.recursive.map{ |e| e.downcase }
|
64
|
+
#
|
65
|
+
# g = ["a", "b", ["x", "y"]]
|
66
|
+
#
|
67
|
+
# CREDIT: Trans
|
68
|
+
|
69
|
+
def map(&block)
|
70
|
+
if block_given?
|
71
|
+
@enum.map do |e|
|
72
|
+
if Array === e || e.respond_to?(:to_ary)
|
73
|
+
e.to_ary.recursive.map(&block)
|
74
|
+
else
|
75
|
+
block.call(e)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
else
|
79
|
+
to_enum(:map)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Like #map, but will change the array in place.
|
84
|
+
|
85
|
+
def map!(&block)
|
86
|
+
replace(map(&block))
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -7,9 +7,8 @@ class Array
|
|
7
7
|
# arr.recursively{|a| a.compact! }
|
8
8
|
# => ["a", ["b", "c"]]
|
9
9
|
#
|
10
|
-
# TODO: Can this be generalized in Enumerbale?
|
11
|
-
|
12
10
|
def recursively(&block)
|
11
|
+
warn "Use #recusive instead of #recursively for future versions"
|
13
12
|
a = inject([]) do |array, value|
|
14
13
|
if value.is_a?(Array)
|
15
14
|
array << value.recursively(&block)
|
@@ -28,3 +27,4 @@ class Array
|
|
28
27
|
end
|
29
28
|
|
30
29
|
end
|
30
|
+
|
@@ -1,18 +1,35 @@
|
|
1
1
|
class Array
|
2
2
|
|
3
|
+
# Returns a new array created by traversing the array and its
|
4
|
+
# sub-arrays, executing the given block on the elements.
|
3
5
|
#
|
6
|
+
# h = ["A", "B", ["X", "Y"]]
|
7
|
+
#
|
8
|
+
# g = h.traverse{ |e| e.downcase }
|
9
|
+
#
|
10
|
+
# g = ["a", "b", ["x", "y"]]
|
11
|
+
#
|
12
|
+
# This is the same as <code>recursive.map</code> and will
|
13
|
+
# likely be deprecated in the future because of it.
|
14
|
+
#
|
15
|
+
# CREDIT: Trans
|
4
16
|
|
5
17
|
def traverse(&block)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
18
|
+
if block_given?
|
19
|
+
map do |e|
|
20
|
+
if e.respond_to?(:to_ary)
|
21
|
+
e.to_ary.traverse(&block)
|
22
|
+
else
|
23
|
+
block.call(e)
|
24
|
+
end
|
11
25
|
end
|
26
|
+
else
|
27
|
+
to_enum(:traverse)
|
12
28
|
end
|
13
29
|
end
|
14
30
|
|
15
|
-
#
|
31
|
+
# Like #recursive_map, but will change the
|
32
|
+
# array in place.
|
16
33
|
|
17
34
|
def traverse!(&block)
|
18
35
|
replace(traverse(&block))
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'facets/enumerable/commonality'
|
@@ -4,7 +4,7 @@ module Enumerable
|
|
4
4
|
# If no block is given objects are considered to be equal if they
|
5
5
|
# return the same value for Object#hash and if obj1 == obj2.
|
6
6
|
#
|
7
|
-
# [1, 2, 2, 3, 4, 4].commonality # => { 2 => [2], 4 => [4] }
|
7
|
+
# [1, 2, 2, 3, 4, 4].commonality # => { 2 => [2, 2], 4 => [4, 4] }
|
8
8
|
#
|
9
9
|
# ["foo", "bar", "a"].commonality { |str| str.length }
|
10
10
|
# # => { 3 => ["foo, "bar"] }
|
@@ -14,7 +14,7 @@ module Enumerable
|
|
14
14
|
#
|
15
15
|
# CREDIT: Florian Gross
|
16
16
|
|
17
|
-
def commonality(
|
17
|
+
def commonality(&block)
|
18
18
|
had_no_block = !block
|
19
19
|
block ||= lambda { |item| item }
|
20
20
|
result = Hash.new { |hash, key| hash[key] = Array.new }
|
@@ -29,5 +29,7 @@ module Enumerable
|
|
29
29
|
return result
|
30
30
|
end
|
31
31
|
|
32
|
+
alias_method :collisions, :commonality
|
33
|
+
|
32
34
|
end
|
33
35
|
|
@@ -1 +1,37 @@
|
|
1
|
-
|
1
|
+
module Enumerable
|
2
|
+
|
3
|
+
# Like <tt>#map</tt>/<tt>#collect</tt>, but generates a Hash. The block
|
4
|
+
# is expected to return two values: the key and the value for the new hash.
|
5
|
+
#
|
6
|
+
# numbers = (1..3)
|
7
|
+
# squares = numbers.graph{ |n| [n, n*n] } # { 1=>1, 2=>4, 3=>9 }
|
8
|
+
# sq_roots = numbers.graph{ |n| [n*n, n] } # { 1=>1, 4=>2, 9=>3 }
|
9
|
+
#
|
10
|
+
# CREDIT: Andrew Dudzik (adudzik), Trans
|
11
|
+
|
12
|
+
def graph(&yld)
|
13
|
+
if yld
|
14
|
+
h = {}
|
15
|
+
each do |*kv|
|
16
|
+
r = yld[*kv]
|
17
|
+
case r
|
18
|
+
when Hash
|
19
|
+
nk, nv = *r.to_a[0]
|
20
|
+
when Range
|
21
|
+
nk, nv = r.first, r.last
|
22
|
+
else
|
23
|
+
nk, nv = *r
|
24
|
+
end
|
25
|
+
h[nk] = nv
|
26
|
+
end
|
27
|
+
h
|
28
|
+
else
|
29
|
+
Enumerator.new(self,:graph)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Alias for #graph, which stands for "map hash".
|
34
|
+
alias_method :mash, :graph
|
35
|
+
|
36
|
+
end
|
37
|
+
|
@@ -1,39 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# Like <tt>#map</tt>/<tt>#collect</tt>, but generates a Hash. The block
|
4
|
-
# is expected to return two values: the key and the value for the new hash.
|
5
|
-
#
|
6
|
-
# numbers = (1..3)
|
7
|
-
# squares = numbers.mash { |n| [n, n*n] } # { 1=>1, 2=>4, 3=>9 }
|
8
|
-
# sq_roots = numbers.mash { |n| [n*n, n] } # { 1=>1, 4=>2, 9=>3 }
|
9
|
-
#
|
10
|
-
# The name "mash" stands for "map hash".
|
11
|
-
#
|
12
|
-
# CREDIT: Andrew Dudzik (adudzik), Trans
|
13
|
-
|
14
|
-
def mash(&yld)
|
15
|
-
if yld
|
16
|
-
h = {}
|
17
|
-
each do |*kv|
|
18
|
-
r = yld[*kv]
|
19
|
-
case r
|
20
|
-
when Hash
|
21
|
-
nk, nv = *r.to_a[0]
|
22
|
-
when Range
|
23
|
-
nk, nv = r.first, r.last
|
24
|
-
else
|
25
|
-
nk, nv = *r
|
26
|
-
end
|
27
|
-
h[nk] = nv
|
28
|
-
end
|
29
|
-
h
|
30
|
-
else
|
31
|
-
Enumerator.new(self,:mash)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# Alias for #mash. This is the original name of this method.
|
36
|
-
alias_method :graph, :mash
|
37
|
-
|
38
|
-
end
|
39
|
-
|
1
|
+
require 'facets/enumerable/graph'
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Enumerable
|
2
|
+
|
3
|
+
def recursive(opts={})
|
4
|
+
Recursor.new(self, opts)
|
5
|
+
end
|
6
|
+
|
7
|
+
# Recursor "functor".
|
8
|
+
#
|
9
|
+
# NOTE: THIS IS A WORK IN PROGRESS!
|
10
|
+
#
|
11
|
+
class Recursor
|
12
|
+
|
13
|
+
def initialize(enum, opts)
|
14
|
+
@enum = enum
|
15
|
+
@opts = opts
|
16
|
+
end
|
17
|
+
|
18
|
+
# Recursive iteration over enumerables.
|
19
|
+
#
|
20
|
+
# [1, 2, [3, 4]].recursive.each{ |e| p e }
|
21
|
+
#
|
22
|
+
# produces
|
23
|
+
#
|
24
|
+
# 1
|
25
|
+
# 2
|
26
|
+
# 3
|
27
|
+
# 4
|
28
|
+
#
|
29
|
+
# NOTE: Technically this should check for the proper conversion
|
30
|
+
# method if applicable, eg. #to_ary for Array, rather than
|
31
|
+
# just checking the class type. In the future this may be
|
32
|
+
# generally supported if Facets ever adds a "class know-thy-self"
|
33
|
+
# library. In the meantime override in classes are required to
|
34
|
+
# incorporate this.
|
35
|
+
|
36
|
+
def each(&b)
|
37
|
+
@enum.each{ |*v| process(:each, *v, &b) }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Recursive map.
|
41
|
+
#
|
42
|
+
# [1, 2, ['a', 'b']].recursive.map{ |e| e.succ }
|
43
|
+
# #=> [1, 2, ['b', 'c']]
|
44
|
+
#
|
45
|
+
def map(&b)
|
46
|
+
@enum.map{ |*v| process(:map, *v, &b) }
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
#def graph(&b)
|
51
|
+
# @enum.graph{ |*v| process(:graph, *v, &b) }
|
52
|
+
#end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
#
|
57
|
+
def process(op, v, &b)
|
58
|
+
case v
|
59
|
+
when String # b/c of 1.8
|
60
|
+
b.call(v)
|
61
|
+
when @enum.class
|
62
|
+
v.recursive(@opts).send(op,&b)
|
63
|
+
else
|
64
|
+
#if @opts[:skip] && Enumerable === v
|
65
|
+
# v
|
66
|
+
#else
|
67
|
+
b.call(v)
|
68
|
+
#end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Enumerable
|
2
|
+
|
3
|
+
# Recursively iterate over all Enumerable elements, or
|
4
|
+
# subset given <code>:type=>[type1, type2, ...]</code>.
|
5
|
+
#
|
6
|
+
# [1, 2, 8..9].visit{ |x| x.succ }
|
7
|
+
# # => [2, 3, [9, 10]]
|
8
|
+
#
|
9
|
+
def visit(opts={}, &block)
|
10
|
+
type = opts[:type] ? [opts[:type]].flatten : [Enumerable]
|
11
|
+
skip = opts[:skip]
|
12
|
+
|
13
|
+
map do |v|
|
14
|
+
case v
|
15
|
+
when String # b/c of 1.8
|
16
|
+
b.call(v)
|
17
|
+
when *type
|
18
|
+
v.recursive(opts).send(op,&b)
|
19
|
+
else
|
20
|
+
if skip && Enumerable === v
|
21
|
+
v
|
22
|
+
else
|
23
|
+
b.call(v)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|