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
@@ -1,11 +1,15 @@
1
1
  class Struct
2
2
 
3
- # Returns a hash containing the names and values for all instance variables in the Struct.
3
+ # Returns a hash containing the names and values
4
+ # for all instance settings in the Struct.
5
+ #
6
+ # This will eventually be deprecated in favor of #to_h.
7
+
4
8
  def attributes
5
9
  h = {}
6
10
  each_pair { |k,v| h[k] = v }
7
11
  h
8
12
  end
9
13
 
10
- end # class Struct
14
+ end
11
15
 
@@ -0,0 +1,19 @@
1
+ class Symbol
2
+
3
+ # Join with _path_ as a file path.
4
+ #
5
+ # :merb / "core_ext" #=> "merb/core_ext"
6
+ # :merb / :core_ext / :string #=> "merb/core_ext/string"
7
+ #
8
+ # @param [#to_s] path The path component(s) to append.
9
+ #
10
+ # @return [String] The receiver (as path string), concatenated with _path_.
11
+ #
12
+ # @api public
13
+
14
+ def /(path)
15
+ File.join(to_s, path.to_s)
16
+ end
17
+
18
+ end
19
+
@@ -318,3 +318,15 @@ class Enumerator
318
318
 
319
319
  end
320
320
 
321
+ class Struct
322
+
323
+ # Returns a hash containing the names and values
324
+ # for all instance settings in the Struct.
325
+ def to_h
326
+ h = {}
327
+ each_pair{ |k,v| h[k] = v }
328
+ h
329
+ end
330
+
331
+ end
332
+
@@ -0,0 +1,172 @@
1
+ # CastingHash is just like Hash, except that all keys and values
2
+ # are passed through casting procedures.
3
+ #--
4
+ # TODO: Handle default_proc.
5
+ #++
6
+ class CastingHash < Hash
7
+
8
+ # Default key conversion procedure.
9
+ KEY_PROC = lambda{ |x| x } #.to_s }
10
+
11
+ # Default value conversion procedure.
12
+ VAL_PROC = lambda{ |x| x }
13
+
14
+ #
15
+ def self.[](hash)
16
+ s = new
17
+ hash.each{ |k,v| s[k] = v }
18
+ s
19
+ end
20
+
21
+ #
22
+ def initialize(hash, value_cast=nil, &key_cast)
23
+ @key_proc = key_cast || KEY_PROC
24
+ @value_proc = value_cast.to_proc || VAL_PROC
25
+ hash.each{ |k,v| self[k] = v }
26
+ end
27
+
28
+ #
29
+ def key_proc
30
+ @key_proc
31
+ end
32
+
33
+ #
34
+ def key_proc=(proc)
35
+ @key_proc = proc.to_proc
36
+ end
37
+
38
+ #
39
+ def value_proc
40
+ @value_proc
41
+ end
42
+
43
+ #
44
+ def value_proc=(proc)
45
+ @value_proc = proc.to_proc
46
+ end
47
+
48
+ #
49
+ def [](k)
50
+ super(key_proc[k])
51
+ end
52
+
53
+ #
54
+ def []=(k,v)
55
+ super(key_proc[k], value_proc[v])
56
+ end
57
+
58
+ #
59
+ def <<(other)
60
+ case other
61
+ when Hash
62
+ super(cast(other))
63
+ when Array
64
+ self[other[0]] = other[1]
65
+ else
66
+ raise ArgumentError
67
+ end
68
+ end
69
+
70
+ def fetch(k)
71
+ super(key_proc[k])
72
+ end
73
+
74
+ #
75
+ def store(k, v)
76
+ super(key_proc[k], value_proc[v])
77
+ end
78
+
79
+ #
80
+ def key?(k)
81
+ super(key_proc[k])
82
+ end
83
+
84
+ #
85
+ def has_key?(k)
86
+ super(key_proc[k])
87
+ end
88
+
89
+ # Synonym for Hash#rekey, but modifies the receiver in place (and returns it).
90
+ #
91
+ # foo = { :name=>'Gavin', :wife=>:Lisa }.to_stash
92
+ # foo.rekey!{ |k| k.upcase } #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
93
+ # foo.inspect #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
94
+ #
95
+ def rekey!(*args, &block)
96
+ # for backward comptability (DEPRECATE?).
97
+ block = args.pop.to_sym.to_proc if args.size == 1
98
+ if args.empty?
99
+ block = lambda{|k| k} unless block
100
+ keys.each do |k|
101
+ nk = block[k]
102
+ self[nk] = delete(k) #if nk
103
+ end
104
+ else
105
+ raise ArgumentError, "3 for 2" if block
106
+ to, from = *args
107
+ self[to] = delete(from) if has_key?(from)
108
+ end
109
+ self
110
+ end
111
+
112
+ #
113
+ def rekey(*args, &block)
114
+ dup.rekey!(*args, &block)
115
+ end
116
+
117
+ #
118
+ def delete(k)
119
+ super(key_proc[k])
120
+ end
121
+
122
+ #
123
+ def update(other)
124
+ super(cast(other))
125
+ end
126
+
127
+ # Same as #update.
128
+ def merge!(other)
129
+ super(cast(other))
130
+ end
131
+
132
+ #
133
+ def replace(other)
134
+ super(cast(other))
135
+ end
136
+
137
+ #
138
+ def values_at(*keys)
139
+ super(keys.map(&key_proc))
140
+ end
141
+
142
+ #
143
+ def to_hash
144
+ h = {}; each{ |k,v| h[k] = v }; h
145
+ end
146
+
147
+ #
148
+ alias_method :to_h, :to_hash
149
+
150
+ private
151
+
152
+ #
153
+ def cast(hash)
154
+ h
155
+ hash.each do |k,v|
156
+ h[key_proc[k]] = value_proc[v]
157
+ end
158
+ h
159
+ end
160
+
161
+ end
162
+
163
+
164
+ class Hash
165
+
166
+ # Convert a Hash to a Stash object.
167
+ def to_casting_hash(value_cast=nil, &key_cast)
168
+ CastingHash.new(self, value_cast, &key_cast)
169
+ end
170
+
171
+ end
172
+
@@ -25,6 +25,10 @@ require 'facets/file/rootname'
25
25
 
26
26
  class Pathname
27
27
 
28
+ # Alias #to_s to #to_str when #to_str is not defined.
29
+ #
30
+ alias_method(:to_str, :to_s) unless method_defined?(:to_str)
31
+
28
32
  # Alternate to Pathname#new.
29
33
  #
30
34
  # Pathname['/usr/share']
@@ -148,6 +152,38 @@ class Pathname
148
152
  ::FileUtils.outofdate?(to_s, sources.flatten)
149
153
  end
150
154
 
155
+ # Recursively visit a directory located by its path, yielding each resource
156
+ # as its full matching pathname object. If called on a file, yield the file.
157
+ #
158
+ # call-seq:
159
+ # visit => yield each file
160
+ # visit(all: true) => yield visited directories as well
161
+ # visit(hidden: true) => yield hidden files and directories as well
162
+ #
163
+ # Example use case:
164
+ #
165
+ # # get rid of any file but *.haml within app/**/*
166
+ # Pathname.new("app").visit do |f|
167
+ # FileUtils.rm_f(f) unless f.to_s =~ /\.haml$/
168
+ # puts "!!! deleting #{f}"
169
+ # end
170
+ #
171
+ # CREDIT: Jean-Denis Vauguet
172
+ def visit(options = {:all => false, :hidden => false})
173
+ if self.directory?
174
+ children.each do |entry|
175
+ next if entry.basename.to_s[0] == "." && !options[:hidden]
176
+ yield(entry) unless entry.directory? && !options[:all]
177
+ #entry.visit(:all => options[:all]) { |sub_entry| yield sub_entry } if entry.directory?
178
+ entry.visit(:all => options[:all], :hidden => options[:hidden]) do |sub_entry|
179
+ yield(sub_entry)
180
+ end if entry.directory?
181
+ end
182
+ else
183
+ yield self
184
+ end
185
+ end
186
+
151
187
  # # Already included in 1.8.4+ version of Ruby (except for inclusion flag)
152
188
  # if not instance_methods.include?(:ascend)
153
189
  #
@@ -0,0 +1,57 @@
1
+ # :title: Prepend
2
+ # :copyright: Copyright (c) 2005 Thomas Sawyer
3
+ # :license: Ruby License
4
+ # :description: Prepend a module to another module, or to a class.
5
+
6
+ # = Prepend
7
+ #
8
+ # This is a module prepend system, which provides an elegant
9
+ # way to prepend code to the class hierarchy rather then append
10
+ # it (a la #include).
11
+ #
12
+ # class C
13
+ # def f
14
+ # "f"
15
+ # end
16
+ # end
17
+ #
18
+ # module M
19
+ # def f
20
+ # '{' + super + '}'
21
+ # end
22
+ # end
23
+ #
24
+ # class C
25
+ # prepend M
26
+ # end
27
+ #
28
+ # c = C.new
29
+ # c.f #=> "{f}"
30
+ #
31
+ # This works by overriding Class#new so that all prepended modules
32
+ # extend new instances of the class upon instantiation.
33
+ #
34
+ # If needed the original #new method has been aliased as #init.
35
+
36
+ class Class
37
+
38
+ #
39
+ def prepend(*mods)
40
+ @prepend ||= []
41
+ @prepend.concat(mods)
42
+ @prepend
43
+ end
44
+
45
+ alias_method :init, :new
46
+
47
+ def new(*args, &blk)
48
+ o = allocate
49
+ prepend.each do |mod|
50
+ o.extend(mod)
51
+ end
52
+ o.__send__(:initialize, *args, &blk) #if private_method_defined?(:initialize)
53
+ o
54
+ end
55
+
56
+ end
57
+
@@ -53,7 +53,7 @@ require 'facets/string/shatter'
53
53
  module Random
54
54
 
55
55
  class << self
56
- # alias to Kernel method #rand.
56
+ # Alias for Kernel#rand.
57
57
  alias_method :number, :rand
58
58
  public :number
59
59
  end
@@ -79,6 +79,8 @@ module Random
79
79
  end
80
80
  end
81
81
 
82
+ #
83
+
82
84
  module Object
83
85
 
84
86
  # Random generator that returns true or false.
@@ -106,9 +108,23 @@ module Random
106
108
  # (1..4).at_rand #=> 2
107
109
  # (1..4).at_rand #=> 4
108
110
  #
111
+ # (1.5..2.5).at_rand #=> 2.06309842754533
112
+ # (1.5..2.5).at_rand #=> 1.74976944931541
113
+ #
114
+ # ('a'..'z').at_rand #=> 'q'
115
+ # ('a'..'z').at_rand #=> 'f'
116
+ #
117
+ # CREDIT: Lavir the Whiolet
118
+
109
119
  def at_rand
110
- array = to_a
111
- array.at(Random.number(array.size))
120
+ if first.respond_to?(:succ)
121
+ to_a.at_rand
122
+ elsif Numeric===first && Numeric===last
123
+ number = (last - first) * Random.number + first
124
+ (number == last && exclude_end?) ? first : number
125
+ else
126
+ nil
127
+ end
112
128
  end
113
129
 
114
130
  end
@@ -1,174 +1,67 @@
1
- # = TITLE:
2
- # Roman Numerals
3
- #
4
- # = SYNOPSIS:
5
- # Generates roman numerals from integers and vice-versa.
6
- #
7
- # = NOTES:
8
- # A response to Ruby Quiz of the Week #22 - Roman Numerals [ruby-talk:132925]
9
- #
10
- # = AUTHORS:
11
- # - Dave Burt <dave at burt.id.au>
12
- # - Trans
13
-
14
- module English #:nodoc:
15
-
16
- # Contains methods to convert integers to roman numeral strings and vice-versa.
17
-
18
- module RomanNumerals
19
-
20
- # The largest integer representable as a roman
21
- # numerable by this module.
22
-
23
- MAX = 3999
24
-
25
- # Stolen from O'Reilly's Perl Cookbook 6.23. Regular Expression Grabbag.
26
-
27
- REGEXP = /^M*(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$/i
28
-
29
- #
30
-
31
- SYMBOLS = [ "M", "D", "C", "L", "X", "V", "I" ]
32
- NUMBERS = [ 1000, 500, 100, 50, 10, 5, 1 ]
33
-
34
-
35
- # Maps roman numeral digits to their integer values.
36
- # {
37
- # 'I' => 1,
38
- # 'V' => 5,
39
- # 'X' => 10,
40
- # 'L' => 50,
41
- # 'C' => 100,
42
- # 'D' => 500,
43
- # 'M' => 1000,
44
- # }
45
-
46
- TABLE = Hash[*SYMBOLS.zip(NUMBERS).flatten]
1
+ class Integer
47
2
 
48
3
  #
49
-
50
- PAIR_SYMBOLS = [ "CM", "CD", "XC", "XL", "IX", "IV", "I" ]
51
- PAIR_NUMBERS = [ 900, 400, 90, 40, 9, 4, 1 ]
52
-
53
- # {
54
- # 'CM' => 900,
55
- # 'CD' => 400,
56
- # 'XC' => 90,
57
- # 'XL' => 40,
58
- # 'IX' => 9,
59
- # 'IV' => 4
60
- # }
61
-
62
- PAIR_TABLE = Hash[*PAIR_SYMBOLS.zip(PAIR_NUMBERS).flatten]
4
+ ROMAN_MAX = 3999
63
5
 
64
6
  #
7
+ ROMAN_VALUES = [
8
+ ["M", 1000],
9
+ ["CM", 900],
10
+ ["D", 500],
11
+ ["CD", 400],
12
+ ["C", 100],
13
+ ["XC", 90],
14
+ ["L", 50],
15
+ ["XL", 40],
16
+ ["X", 10],
17
+ ["IX", 9],
18
+ ["V", 5],
19
+ ["IV", 4],
20
+ ["I", 1]
21
+ ]
65
22
 
66
- LOOKUP = TABLE.invert.merge(PAIR_TABLE.invert)
67
-
68
-
69
- class << self
70
-
71
- # Converts +integer+ to a roman numeral.
72
-
73
- def from_integer(integer)
74
- return nil if integer < 0 || integer > MAX
75
-
76
- r = integer # remainder
77
- y = '' # result
78
-
79
- NUMBERS.each do |n|
80
- while r >= n
81
- r -= n
82
- y += LOOKUP[n]
83
- end
84
- break if r <= 0
85
- end
86
-
87
- return y
88
- end
89
-
90
- alias_method :roman, :from_integer
91
-
92
- # Converts +roman_string+, a roman numeral, to an integer
93
-
94
- def to_integer(roman_string)
95
- return nil unless roman_string.is_roman_numeral?
96
-
97
- l = nil # last
98
- i = 0 # integer result
99
-
100
- c = roman_string.to_s.upcase.split(//).reverse
101
-
102
- c.each do |d|
103
- if v = TABLE[d]
104
- if l && l > v
105
- i -= v
106
- else
107
- i += v
108
- end
109
- l = v
110
- end
23
+ # Converts this integer to a roman numeral.
24
+ def roman
25
+ int = self
26
+ #return nil if integer > ROMAN_MAX
27
+ return "-#{(-int).roman}" if int < 0
28
+ return "" if int == 0
29
+ ROMAN_VALUES.each do |(i, v)|
30
+ return(i + (int-v).roman) if v <= int
111
31
  end
112
-
113
- return i
114
- end
115
-
116
- alias_method :arabic, :to_integer
117
-
118
- # Returns true iif +string+ is a roman numeral.
119
-
120
- def is_roman_numeral?(string)
121
- REGEXP =~ string
122
- end
123
-
124
32
  end
125
33
 
126
34
  end
127
35
 
128
- end # module English
129
-
130
36
 
131
- class Integer
132
-
133
- def roman
134
- English::RomanNumerals.roman(self) || ''
135
- end
136
-
137
- # Converts this integer to a roman numeral.
138
-
139
- def to_s_roman
140
- English::RomanNumerals.from_integer(self) || ''
141
- end
142
-
143
- end
37
+ class String
144
38
 
39
+ # Taken from O'Reilly's Perl Cookbook 6.23. Regular Expression Grabbag.
40
+ ROMAN = /^M*(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$/i
145
41
 
146
- class String
42
+ #
43
+ ROMAN_VALUES = Integer::ROMAN_VALUES.inject({}){ |h,(r,a)| h[r] = a; h }
147
44
 
148
- # Considers string a roman numeral numeral,
45
+ # Considers string a Roman numeral numeral,
149
46
  # and converts it to the corresponding integer.
150
-
151
- def to_i_roman
152
- English::RomanNumerals.to_integer(self)
47
+ def roman
48
+ roman = self
49
+ raise unless roman?
50
+ last = roman[-1,1]
51
+ roman.reverse.split('').inject(0) do |result, c|
52
+ if ROMAN_VALUES[c] < ROMAN_VALUES[last]
53
+ result -= ROMAN_VALUES[c]
54
+ else
55
+ last = c
56
+ result += ROMAN_VALUES[c]
57
+ end
58
+ end
153
59
  end
154
60
 
155
- # Returns true iif the subject is a roman numeral.
156
-
157
- def is_roman_numeral?
158
- English::RomanNumerals.is_roman_numeral?(self)
61
+ # Returns true iif the subject is a valid Roman numeral.
62
+ def roman?
63
+ ROMAN =~ self
159
64
  end
160
65
 
161
66
  end
162
67
 
163
-
164
- # # Quiz solution: filter that swaps roman and arabic numbers
165
- # if __FILE__ == $0
166
- # ARGF.each do |line|
167
- # line.chomp!
168
- # if line.is_roman_numeral?
169
- # puts line.to_i_roman
170
- # else
171
- # puts line.to_i.to_s_roman
172
- # end
173
- # end
174
- # end