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.
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
+