facets 2.8.2 → 2.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/AUTHORS +13 -11
  2. data/HISTORY.rdoc +58 -0
  3. data/lib/core/facets/array/recursive.rb +91 -0
  4. data/lib/core/facets/array/recursively.rb +2 -2
  5. data/lib/core/facets/array/traverse.rb +23 -6
  6. data/lib/core/facets/enumerable/collisions.rb +1 -0
  7. data/lib/core/facets/enumerable/commonality.rb +4 -2
  8. data/lib/core/facets/enumerable/graph.rb +37 -1
  9. data/lib/core/facets/enumerable/mash.rb +1 -39
  10. data/lib/core/facets/enumerable/recursive.rb +75 -0
  11. data/lib/core/facets/enumerable/visit.rb +30 -0
  12. data/lib/core/facets/file/ext.rb +36 -0
  13. data/lib/core/facets/hash/graph.rb +18 -0
  14. data/lib/core/facets/hash/mash.rb +1 -18
  15. data/lib/core/facets/hash/recursive.rb +180 -0
  16. data/lib/core/facets/hash/recursive_merge.rb +6 -0
  17. data/lib/core/facets/hash/recursively.rb +2 -2
  18. data/lib/core/facets/hash/to_module.rb +26 -0
  19. data/lib/core/facets/hash/to_proc.rb +2 -2
  20. data/lib/core/facets/hash/traverse.rb +19 -13
  21. data/lib/core/facets/kernel/assign.rb +63 -0
  22. data/lib/core/facets/kernel/assign_from.rb +45 -0
  23. data/lib/core/facets/kernel/dup.rb +63 -0
  24. data/lib/core/facets/kernel/instance.rb +156 -0
  25. data/lib/core/facets/kernel/instance_assign.rb +1 -22
  26. data/lib/core/facets/kernel/meta_def.rb +4 -0
  27. data/lib/core/facets/kernel/populate.rb +1 -74
  28. data/lib/core/facets/kernel/set_from.rb +2 -0
  29. data/lib/core/facets/kernel/try_dup.rb +1 -0
  30. data/lib/core/facets/module/set.rb +36 -0
  31. data/lib/core/facets/objectspace/reflect.rb +45 -0
  32. data/lib/core/facets/struct/attributes.rb +6 -2
  33. data/lib/core/facets/symbol/op_div.rb +19 -0
  34. data/lib/core/facets/to_hash.rb +12 -0
  35. data/lib/more/facets/casting_hash.rb +172 -0
  36. data/lib/more/facets/pathname.rb +36 -0
  37. data/lib/more/facets/prepend.rb +57 -0
  38. data/lib/more/facets/random.rb +19 -3
  39. data/lib/more/facets/roman.rb +46 -153
  40. data/lib/more/facets/stash.rb +148 -33
  41. data/meta/released +1 -1
  42. data/meta/version +1 -1
  43. data/test/core/array/test_recursive.rb +18 -0
  44. data/test/core/enumerable/test_recursive.rb +18 -0
  45. data/test/core/file/test_ext.rb +31 -0
  46. data/test/core/hash/test_recursive.rb +23 -0
  47. data/test/core/hash/test_to_module.rb +21 -0
  48. data/test/core/kernel/test_assign.rb +57 -0
  49. data/test/core/kernel/test_assign_from.rb +20 -0
  50. data/test/more/test_prepend.rb +28 -0
  51. data/test/more/test_random.rb +40 -4
  52. metadata +39 -10
  53. data/lib/core/facets/kernel/instance_variables.rb +0 -97
  54. data/lib/more/facets/instance_eval.rb +0 -50
  55. data/lib/more/facets/ioredirect.rb +0 -77
  56. data/lib/more/facets/plugin_manager.rb +0 -50
  57. data/test/core/kernel/test_populate.rb +0 -46
@@ -0,0 +1,36 @@
1
+ class File
2
+
3
+ # Takes a file name string and returns or changes its extension.
4
+ #
5
+ # Without a new extension argument, returns the extension of the
6
+ # file name. In this respect #ext is like #extname, but unlike
7
+ # #extname it does not include the dot prefix.
8
+ #
9
+ # With a new extension argument, changes the exension of the file
10
+ # name to the new extension and returns it.
11
+ #
12
+ # Examples:
13
+ #
14
+ # File.ext('file.rb') => 'rb'
15
+ # File.ext('file.rb', 'txt') => 'file.txt'
16
+ # File.ext('file.rb', '.txt') => 'file.txt'
17
+ # File.ext('file.rb', '') => 'file'
18
+ #
19
+ # This method can be used with String#file for more object-oriented notation.
20
+ #
21
+ # 'file.rb'.file.ext('txt') => 'file.txt'
22
+ #
23
+ # CREDIT: Lavir the Whiolet
24
+
25
+ def self.ext(filename, new_ext=nil)
26
+ old_ext = extname(filename)
27
+ if new_ext == nil
28
+ old_ext.sub(/^\./, '')
29
+ else
30
+ new_ext = '.' + new_ext unless (new_ext.empty? || new_ext[0,1] == '.')
31
+ filename.chomp(old_ext) + new_ext
32
+ end
33
+ end
34
+
35
+ end
36
+
@@ -0,0 +1,18 @@
1
+ require 'facets/enumerable/mash'
2
+
3
+ class Hash
4
+
5
+ # In place version of #graph.
6
+ #
7
+ # NOTE: Hash#graph! is only useful for Hash.
8
+ # It is not generally applicable to Enumerable.
9
+
10
+ def graph!(&yld)
11
+ replace(graph(&yld))
12
+ end
13
+
14
+ # Alias for #graph! as an alliteration for "map hash".
15
+ alias_method :mash!, :graph!
16
+
17
+ end
18
+
@@ -1,18 +1 @@
1
- require 'facets/enumerable/mash'
2
-
3
- class Hash
4
-
5
- # In place version of #mash.
6
- #
7
- # NOTE: Hash#mash! is only useful for Hash. It is not generally
8
- # applicable to Enumerable.
9
-
10
- def mash!(&yld)
11
- replace(mash(&yld))
12
- end
13
-
14
- # Alias for #mash!. This is the original name for this method.
15
- alias_method :graph!, :mash!
16
-
17
- end
18
-
1
+ require 'facets/hash/graph'
@@ -0,0 +1,180 @@
1
+ class Hash
2
+
3
+ # Apply a block to hash, and recursively apply that block
4
+ # to each subhash.
5
+ #
6
+ # h = {:a=>1, :b=>{:b1=>1, :b2=>2}}
7
+ # h.recursively{|h| h.rekey(&:to_s) }
8
+ # => {"a"=>1, "b"=>{"b1"=>1, "b2"=>2}}
9
+ #
10
+ def recursive(opts={}, &block)
11
+ if block
12
+ h = inject({}) do |hash, (key, value)|
13
+ if value.is_a?(Hash)
14
+ hash[key] = value.recursive(&block)
15
+ else
16
+ hash[key] = value
17
+ end
18
+ hash
19
+ end
20
+ yield h
21
+ else
22
+ Recursor.new(self, opts)
23
+ end
24
+ end
25
+
26
+ #
27
+
28
+ def recursive!(&block)
29
+ r = recursive(&block)
30
+ raise TypeError unless Hash === r
31
+ replace(r)
32
+ end
33
+
34
+ #
35
+ class Recursor
36
+
37
+ #
38
+ def initialize(enum, opts)
39
+ @enum = enum
40
+ @opts = opts
41
+ end
42
+
43
+ # Returns a new hash created by traversing the hash and its subhashes,
44
+ # executing the given block on the key and value. The block should
45
+ # return a 2-element array of the form +[key, value]+.
46
+ #
47
+ # h = { "A"=>"A", "B"=>"B", { "X"=>"X" } }
48
+ #
49
+ # h.recursive_each{ |k,v| p [k.downcase, v] }
50
+ #
51
+ # produces
52
+ #
53
+ # ["a", "A"]
54
+ # ["b", "B"]
55
+ # ["x", "X"]
56
+ #
57
+ # CREDIT: Trans
58
+
59
+ def each(&block)
60
+ @enum.each do |k,v|
61
+ if Hash === v
62
+ v = v.recursive.each(&block)
63
+ elsif v.respond_to?(:to_hash)
64
+ v = v.to_hash.recursive.each(&block)
65
+ end
66
+ block.call(k,v)
67
+ end
68
+ #@enum.each do |k,v|
69
+ # if Hash === v
70
+ # v.recursive.each(&block)
71
+ # else
72
+ # block.call(k,v)
73
+ # end
74
+ #end
75
+ end
76
+
77
+ # Returns a new hash created by traversing the hash and its subhashes,
78
+ # executing the given block on the key and value. The block should
79
+ # return a 2-element array of the form +[key, value]+.
80
+ #
81
+ # h = { "A"=>"A", "B"=>"B", { "X"=>"X" } }
82
+ #
83
+ # g = h.recursive_map{ |k,v| [k.downcase, v] }
84
+ #
85
+ # g #=> [["a", "A"], ["b", "B"], [["x", "X"]]]
86
+ #
87
+ # CREDIT: Trans
88
+
89
+ def map(&block)
90
+ @enum.inject([]) do |a,(k,v)|
91
+ if Hash === v
92
+ v = v.recursive.map(&block)
93
+ elsif v.respond_to?(:to_hash)
94
+ v = v.to_hash.recursive.map(&block)
95
+ end
96
+ nk, nv = block.call(k,v)
97
+ a << [nk, nv]
98
+ a
99
+ end
100
+ end
101
+
102
+ # In-place rendition of #recursive_map.
103
+
104
+ def map!(&b)
105
+ @enum.replace(map(&b))
106
+ end
107
+
108
+ # Returns a new hash created by traversing the hash and its subhashes,
109
+ # executing the given block on the key and value. The block should
110
+ # return a 2-element array of the form +[key, value]+.
111
+ #
112
+ # h = {"A"=>"A", "B"=>"B", {"X"=>"X"}}
113
+ #
114
+ # g = h.recursive_graph{ |k,v| [k.downcase, v] }
115
+ #
116
+ # g #=> {"a"=>"A", "b"=>"B", {"x"=>"X"}}
117
+ #
118
+ # CREDIT: Trans
119
+
120
+ def graph(&block)
121
+ @enum.inject({}) do |h,(k,v)|
122
+ if Hash === v
123
+ v = v.recursive.graph(&block)
124
+ elsif v.respond_to?(:to_hash)
125
+ v = v.to_hash.recursive.graph(&block)
126
+ end
127
+ nk, nv = block.call(k,v)
128
+ h[nk] = nv
129
+ h
130
+ end
131
+ end
132
+
133
+ # In place version of traverse, which traverses the hash and its
134
+ # subhashes, executing the given block on the key and value.
135
+ #
136
+ # h = { "A"=>"A", "B"=>"B" }
137
+ #
138
+ # h.traverse! { |k,v| [k.downcase, v] }
139
+ #
140
+ # h #=> { "a"=>"A", "b"=>"B" }
141
+ #
142
+ # CREDIT: Trans
143
+
144
+ def graph!(&block)
145
+ @enum.replace(graph(&block))
146
+ end
147
+
148
+ # Same as Hash#merge but recursively merges sub-hashes.
149
+
150
+ def merge(other)
151
+ hash = @enum.dup
152
+ other.each do |key, value|
153
+ myval = @enum[key]
154
+ if value.is_a?(Hash) && myval.is_a?(Hash)
155
+ hash[key] = myval.recursive.merge(value)
156
+ else
157
+ hash[key] = value
158
+ end
159
+ end
160
+ hash
161
+ end
162
+
163
+ # Same as Hash#merge! but recursively merges sub-hashes.
164
+
165
+ def merge!(other)
166
+ other.each do |key, value|
167
+ myval = @enum[key]
168
+ if value.is_a?(Hash) && myval.is_a?(Hash)
169
+ myval.recursive.merge!(value)
170
+ else
171
+ @enum[key] = value
172
+ end
173
+ end
174
+ @enum
175
+ end
176
+
177
+ end
178
+
179
+ end
180
+
@@ -1,6 +1,9 @@
1
1
  class Hash
2
2
 
3
3
  # Same as Hash#merge but recursively merges sub-hashes.
4
+ #
5
+ # DEPRECATE: This method will be deprecated in favor of
6
+ # <code>recursive.merge</code>.
4
7
 
5
8
  def recursive_merge(other)
6
9
  hash = self.dup
@@ -16,6 +19,9 @@ class Hash
16
19
  end
17
20
 
18
21
  # Same as Hash#merge! but recursively merges sub-hashes.
22
+ #
23
+ # DEPRECATE: This method will be deprecated in favor of
24
+ # <code>recursive.merge!</code>.
19
25
 
20
26
  def recursive_merge!(other)
21
27
  other.each do |key, value|
@@ -8,6 +8,7 @@ class Hash
8
8
  # => {"a"=>1, "b"=>{"b1"=>1, "b2"=>2}}
9
9
  #
10
10
  def recursively(&block)
11
+ warn "Use #recusive instead of #recursively for future versions"
11
12
  h = inject({}) do |hash, (key, value)|
12
13
  if value.is_a?(Hash)
13
14
  hash[key] = value.recursively(&block)
@@ -19,11 +20,10 @@ class Hash
19
20
  yield h
20
21
  end
21
22
 
22
- #
23
+ # In place form of #recursively.
23
24
 
24
25
  def recursively!(&block)
25
26
  replace(recursively(&block))
26
27
  end
27
28
 
28
29
  end
29
-
@@ -0,0 +1,26 @@
1
+ class Hash
2
+
3
+ # Convert a hash into a mixin.
4
+ #
5
+ # CREDIT: Jay Fields
6
+ #
7
+ #--
8
+ # TODO: Consider #to_object option.
9
+ #++
10
+
11
+ def to_module
12
+ hash = self
13
+ Module.new do
14
+ hash.each do |key, value|
15
+ define_method key do
16
+ value #.to_object
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ #def to_object
23
+ # Object.new.extend(to_module)
24
+ #end
25
+ end
26
+
@@ -24,11 +24,11 @@ class Hash
24
24
  # A fault-tolerent version of #to_proc.
25
25
  #
26
26
  # It works just like #to_proc, but the block will make
27
- # sure# the object responds to the assignment.
27
+ # sure the object responds to the assignment.
28
28
  #
29
29
  # CREDIT: Trans
30
30
 
31
- def to_proc_with_reponse
31
+ def to_proc_with_response
32
32
  lambda do |o|
33
33
  self.each do |k,v|
34
34
  ke = "#{k}="
@@ -4,22 +4,26 @@ class Hash
4
4
  # executing the given block on the key and value. The block should
5
5
  # return a 2-element array of the form +[key, value]+.
6
6
  #
7
- # h = { "A"=>"A", "B"=>"B" }
8
- # g = h.traverse { |k,v| [k.downcase, v] }
9
- # g #=> { "a"=>"A", "b"=>"B" }
7
+ # h = {"A"=>"A", "B"=>"B", {"X"=>"X"}}
8
+ #
9
+ # g = h.traverse{ |k,v| [k.downcase, v] }
10
10
  #
11
- # TODO: Contrast these to recursibely --we may not need both.
11
+ # g #=> {"a"=>"A", "b"=>"B", {"x"=>"X"}}
12
12
  #
13
- # TODO: Testing value to see if it is a Hash also catches subclasses of Hash.
14
- # This is probably not the right thing to do and should catch Hashes only (?)
13
+ # NOTE: Hash#traverse is the same as <code>recursive.graph</code> and
14
+ # will likely be deprecated in the future because of it.
15
15
  #
16
16
  # CREDIT: Trans
17
17
 
18
- def traverse(&b)
18
+ def traverse(&block)
19
19
  inject({}) do |h,(k,v)|
20
- v = ( Hash === v ? v.traverse(&b) : v )
21
- nk, nv = b[k,v]
22
- h[nk] = nv #( Hash === v ? v.traverse(base,&b) : nv )
20
+ if Hash === v
21
+ v = v.traverse(&block)
22
+ elsif v.respond_to?(:to_hash)
23
+ v = v.to_hash.traverse(&block)
24
+ end
25
+ nk, nv = block.call(k,v)
26
+ h[nk] = nv
23
27
  h
24
28
  end
25
29
  end
@@ -28,13 +32,15 @@ class Hash
28
32
  # subhashes, executing the given block on the key and value.
29
33
  #
30
34
  # h = { "A"=>"A", "B"=>"B" }
31
- # h.traverse! { |k,v| [k.downcase, v] }
35
+ #
36
+ # h.traverse!{ |k,v| [k.downcase, v] }
37
+ #
32
38
  # h #=> { "a"=>"A", "b"=>"B" }
33
39
  #
34
40
  # CREDIT: Trans
35
41
 
36
- def traverse!(&b)
37
- self.replace( self.traverse(&b) )
42
+ def traverse!(&block)
43
+ replace(traverse(&block))
38
44
  end
39
45
 
40
46
  end
@@ -0,0 +1,63 @@
1
+ module Kernel
2
+
3
+ # Assign via writer using a arguments, hash or
4
+ # associative array, and son on, or assign via
5
+ # a block.
6
+ #
7
+ # Using name-value arguments:
8
+ #
9
+ # object.assign(:a, 1)
10
+ # object.assign(:b, 2)
11
+ #
12
+ # Using a hash:
13
+ #
14
+ # object.assign( :a => 1, :b => 2 )
15
+ #
16
+ # Use an associative array:
17
+ #
18
+ # object.assign( [[:a, 1], [:b, 2]] )
19
+ #
20
+ # Using a block:
21
+ #
22
+ # object.assign do |s|
23
+ # s.a = 1
24
+ # s.b = 2
25
+ # end
26
+ #
27
+ # These are all equivalent to:
28
+ #
29
+ # object.a = 1
30
+ # object.b = 2
31
+ #
32
+ # Unless assigned via a block, undefined setters will not
33
+ # raise an error if they do not exist. They will simply be
34
+ # skipped.
35
+ #
36
+ # Using an associative array instead of hash guarentees
37
+ # order of assignemnt for older versions of Ruby (< 1.8.7).
38
+ #
39
+ # TODO: Should this be called #set instead? Consider
40
+ # Module#set in this question, and also #set_from as
41
+ # the alias of #assign_from.
42
+
43
+ def assign(data=nil, value=Exception) #:yield:
44
+ if data
45
+ if value==Exception
46
+ data.each do |(k,v)|
47
+ __send__("#{k}=", v) if respond_to?("#{k}=")
48
+ end
49
+ else
50
+ __send__("#{data}=", value) if respond_to?("#{data}=")
51
+ end
52
+ end
53
+ yield(self) if block_given?
54
+ self
55
+ end
56
+
57
+ # DEPRECATE: Use #assign instead.
58
+ def populate(*a,&b)
59
+ warn 'use #assign instead of #populate for future versions'
60
+ assign(*a,&b)
61
+ end
62
+ end
63
+