facets 2.7.0 → 2.8.0

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 (130) hide show
  1. data/HISTORY.rdoc +135 -294
  2. data/MANIFEST +40 -91
  3. data/NOTES +1 -1
  4. data/README.rdoc +10 -8
  5. data/Rakefile +11 -34
  6. data/demo/{hook.rd → hook.rdoc} +2 -0
  7. data/demo/{scenario_require.rd → scenario_require.rdoc} +3 -0
  8. data/lib/core/facets-live.rb +7 -5
  9. data/lib/core/facets.rb +379 -359
  10. data/lib/core/facets/array/conjoin.rb +2 -2
  11. data/lib/core/facets/array/pad.rb +1 -1
  12. data/lib/core/facets/array/recursively.rb +2 -2
  13. data/lib/core/facets/array/splice.rb +1 -1
  14. data/lib/core/facets/binding/caller.rb +2 -4
  15. data/lib/core/facets/comparable/comparable.rb +2 -2
  16. data/lib/core/facets/dir/ascend.rb +3 -0
  17. data/lib/core/facets/dir/recurse.rb +4 -0
  18. data/lib/core/facets/duplicable.rb +6 -8
  19. data/lib/core/facets/enumerable/count.rb +22 -13
  20. data/lib/core/facets/enumerable/map_detect.rb +28 -0
  21. data/lib/core/facets/enumerable/mash.rb +13 -5
  22. data/lib/core/facets/enumerable/per.rb +3 -1
  23. data/lib/core/facets/hash/count.rb +14 -0
  24. data/lib/core/facets/hash/data.rb +14 -0
  25. data/lib/core/facets/kernel/__method__.rb +1 -1
  26. data/lib/core/facets/kernel/d.rb +9 -8
  27. data/lib/core/facets/kernel/eigenclass.rb +20 -0
  28. data/lib/core/facets/kernel/extend.rb +10 -0
  29. data/lib/core/facets/kernel/instance_class.rb +1 -0
  30. data/lib/core/facets/kernel/instance_variables.rb +6 -6
  31. data/lib/core/facets/kernel/meta_alias.rb +18 -0
  32. data/lib/core/facets/kernel/meta_class.rb +17 -0
  33. data/lib/core/facets/kernel/meta_def.rb +18 -0
  34. data/lib/core/facets/kernel/meta_eval.rb +18 -0
  35. data/lib/core/facets/kernel/object_hexid.rb +21 -6
  36. data/lib/core/facets/kernel/object_state.rb +4 -2
  37. data/lib/core/facets/kernel/populate.rb +3 -1
  38. data/lib/core/facets/kernel/with.rb +1 -1
  39. data/lib/core/facets/metaid.rb +6 -93
  40. data/lib/core/facets/module/class_def.rb +2 -0
  41. data/lib/core/facets/module/extend.rb +10 -11
  42. data/lib/core/facets/module/is.rb +5 -5
  43. data/lib/core/facets/module/module_def.rb +31 -0
  44. data/lib/core/facets/string/camelcase.rb +14 -12
  45. data/lib/core/facets/string/cleanlines.rb +35 -0
  46. data/lib/core/facets/string/edit_distance.rb +62 -0
  47. data/lib/core/facets/string/indent.rb +86 -4
  48. data/lib/core/facets/string/index_all.rb +24 -0
  49. data/lib/core/facets/string/lines.rb +3 -6
  50. data/lib/core/facets/string/margin.rb +2 -1
  51. data/lib/core/facets/string/newlines.rb +35 -0
  52. data/lib/core/facets/string/op_div.rb +14 -0
  53. data/lib/core/facets/string/range.rb +2 -22
  54. data/lib/core/facets/string/range_all.rb +1 -0
  55. data/lib/core/facets/string/range_of_line.rb +1 -0
  56. data/lib/core/facets/string/similarity.rb +92 -0
  57. data/lib/core/facets/string/start_with.rb +6 -6
  58. data/lib/core/facets/string/titlecase.rb +1 -1
  59. data/lib/more/facets/basicobject.rb +16 -15
  60. data/lib/more/facets/blankslate.rb +8 -0
  61. data/lib/more/facets/class_extend.rb +126 -1
  62. data/lib/more/facets/continuation.rb +53 -54
  63. data/lib/more/facets/dictionary.rb +9 -63
  64. data/lib/more/facets/erb.rb +63 -0
  65. data/lib/more/facets/filelist.rb +5 -5
  66. data/lib/more/facets/hashbuilder.rb +101 -0
  67. data/lib/more/facets/inheritor.rb +36 -45
  68. data/lib/more/facets/ini.rb +267 -0
  69. data/lib/more/facets/instance_eval.rb +4 -4
  70. data/lib/more/facets/ioredirect.rb +7 -60
  71. data/lib/more/facets/linkedlist.rb +195 -0
  72. data/lib/more/facets/matcher.rb +140 -0
  73. data/lib/more/facets/memoizer.rb +64 -0
  74. data/lib/more/facets/methodspace.rb +9 -4
  75. data/lib/more/facets/module/class_extend.rb +2 -121
  76. data/lib/more/facets/ostruct.rb +9 -9
  77. data/lib/more/facets/pathlist.rb +1 -9
  78. data/lib/more/facets/pathname.rb +11 -4
  79. data/lib/more/facets/plugin_manager.rb +50 -0
  80. data/lib/more/facets/random.rb +25 -3
  81. data/lib/more/facets/roman.rb +174 -0
  82. data/lib/more/facets/semaphore.rb +92 -0
  83. data/lib/more/facets/shellwords.rb +21 -48
  84. data/lib/more/facets/succ.rb +1 -1
  85. data/meta/{modified → released} +0 -0
  86. data/meta/repository +1 -0
  87. data/meta/suite +1 -0
  88. data/meta/version +1 -1
  89. data/script/conflicts +63 -0
  90. data/script/methods +49 -0
  91. data/test/core/binding/test_caller.rb +11 -4
  92. data/test/core/enumerable/test_count.rb +19 -10
  93. data/test/core/enumerable/test_map_detect.rb +75 -0
  94. data/test/core/enumerable/test_take.rb +1 -1
  95. data/test/core/kernel/test_object_hexid.rb +2 -1
  96. data/test/core/proc/test_to_method.rb +1 -1
  97. data/test/core/string/test_cleanlines.rb +11 -0
  98. data/test/core/string/test_indent.rb +66 -4
  99. data/test/core/string/test_lines.rb +2 -1
  100. data/test/core/string/test_newlines.rb +13 -0
  101. data/test/core/time/test_change.rb +1 -1
  102. data/test/core/time/test_stamp.rb +4 -7
  103. data/test/core/unboundmethod/test_name.rb +1 -1
  104. data/test/more/test_basicobject.rb +1 -20
  105. data/test/more/test_class_extend.rb +7 -0
  106. data/test/more/test_continuation.rb +8 -6
  107. data/test/more/test_inheritor.rb +12 -6
  108. data/test/more/test_random.rb +19 -10
  109. data/test/more/test_shellwords.rb +33 -0
  110. metadata +60 -31
  111. data/TODO +0 -5
  112. data/doc/README.core +0 -102
  113. data/doc/README.more +0 -61
  114. data/doc/manual/about.rb +0 -47
  115. data/doc/manual/annotations.rdoc +0 -60
  116. data/doc/manual/associations.rdoc +0 -55
  117. data/doc/manual/blockups.rdoc +0 -101
  118. data/doc/manual/capsule.rdoc +0 -34
  119. data/doc/manual/command.rdoc +0 -177
  120. data/doc/manual/core.rdoc +0 -37
  121. data/doc/manual/faq.rdoc +0 -32
  122. data/doc/manual/typecast.html +0 -112
  123. data/lib/more/facets/capsule.rb +0 -258
  124. data/lib/more/facets/coroutine.rb +0 -159
  125. data/lib/more/facets/enumerablepass.rb +0 -3
  126. data/lib/more/facets/fileable.rb +0 -162
  127. data/lib/more/facets/progressbar.rb +0 -253
  128. data/lib/more/facets/recorder.rb +0 -108
  129. data/meta/releases +0 -14
  130. data/test/more/test_coroutine.rb +0 -46
@@ -0,0 +1,140 @@
1
+ #= Matcher
2
+ #
3
+ # Matcher derives from Ruby Quiz #103, the DictionaryMatcher quiz.
4
+ #
5
+ class Matcher
6
+ attr_reader :word_count
7
+
8
+ #Contains the index matched, and the word matched
9
+ class MatchData < Struct.new(:index,:match)
10
+ def inspect
11
+ "#{match.inspect}@#{index}"
12
+ end
13
+ end
14
+
15
+ def inspect
16
+ to_s
17
+ end
18
+
19
+ #Create a DictionaryMatcher with no words in it
20
+ def initialize
21
+ @trie = {}
22
+ @word_count = 0
23
+ end
24
+
25
+ #Add a word to the DictionaryMatcher
26
+ def add(word)
27
+ @word_count += 1
28
+ container = @trie
29
+ containers=[]
30
+
31
+ i=0
32
+ word.each_byte do |b|
33
+ container[b] = {} unless container.has_key? b
34
+ container[:depth]=i
35
+ containers << container
36
+ container = container[b]
37
+ i+=1
38
+ end
39
+ containers << container
40
+
41
+ container[0] = true # Mark end of word
42
+ container[:depth]=i
43
+
44
+ ff=compute_failure_function word
45
+ ff.zip(containers).each do |pointto,container|
46
+ container[:failure]=containers[pointto] if pointto
47
+ end
48
+
49
+ self
50
+
51
+ end
52
+
53
+ alias << add
54
+
55
+ def compute_failure_function p
56
+ m=p.size
57
+ pi=[nil,0]
58
+ k=0
59
+ 2.upto m do |q|
60
+ k=pi[k] while k>0 and p[k] != p[q-1]
61
+ k=k+1 if p[k]==p[q-1]
62
+ pi[q]=k
63
+ end
64
+ pi
65
+ end
66
+ private :compute_failure_function
67
+
68
+ #Determine whether +string+ was previously <tt>add</tt>ed to the
69
+ #Trie.
70
+ def include?(word)
71
+ container = @trie
72
+ word.each_byte do |b|
73
+ break unless container.has_key? b
74
+ container = container[b]
75
+ end
76
+ container[0]
77
+ end
78
+
79
+ #Determines whether one of the words in the DictionaryMatcher is a
80
+ #substring of
81
+ #+string+. Returns the index of the match if found, +nil+ if not
82
+ #found.
83
+ def =~ text
84
+ internal_match(text){|md| return md.index}
85
+ nil
86
+ end
87
+
88
+ #Determine whether one of the words in the DictionaryMatcher is a
89
+ #substring of
90
+ #+string+. Returns a DictionaryMatcher::MatchData object if found,
91
+ #+nil+ if not #found.
92
+ def match text
93
+ internal_match(text){|md| return md}
94
+ nil
95
+ end
96
+
97
+ def internal_match string
98
+ node=@trie
99
+ pos=0
100
+ string.each_byte do |b|
101
+ advance=false
102
+ until advance
103
+ nextnode=node[b]
104
+ if not nextnode
105
+ if node[:failure]
106
+ node=node[:failure]
107
+ else
108
+ advance=true
109
+ end
110
+ elsif nextnode[0]
111
+ yield MatchData.new(pos, string[pos+1-nextnode[:depth],nextnode[:depth]])
112
+ advance=true
113
+ node=@trie
114
+ else
115
+ advance=true
116
+ node=nextnode
117
+ end
118
+ pos+=1
119
+ end
120
+ end
121
+ end
122
+ private :internal_match
123
+
124
+ #Scans +string+ for all occurrances of strings in the
125
+ #DictionaryMatcher.
126
+ #Overlapping matches are skipped (only the first one is yielded), and
127
+ #when some strings in the
128
+ #DictionaryMatcher are substrings of others, only the shortest match
129
+ #at a given position is found.
130
+ def scan(text, &block)
131
+ matches=[]
132
+ block= lambda{ |md| matches << md } unless block
133
+ internal_match(text,&block)
134
+ matches
135
+ end
136
+
137
+ #Case equality. Similar to =~.
138
+ alias_method :===, :=~
139
+ end
140
+
@@ -0,0 +1,64 @@
1
+ # Memoizer
2
+ #
3
+ # Copyright (c) 2006 Erik Veenstra
4
+ #
5
+ # See http://javathink.blogspot.com/2008/09/what-is-memoizer-and-why-should-you.html
6
+
7
+ # Memoizer wraps objects to provide cached method calls.
8
+ #
9
+ # class X
10
+ # def initialize ; @tick = 0 ; end
11
+ # def tick; @tick + 1; end
12
+ # def memo; @memo ||= Memoizer.new(self) ; end
13
+ # end
14
+ #
15
+ # x = X.new
16
+ # x.tick #=> 1
17
+ # x.memo.tick #=> 2
18
+ # x.tick #=> 3
19
+ # x.memo.tick #=> 2
20
+ # x.tick #=> 4
21
+ # x.memo.tick #=> 2
22
+ #
23
+ # You can also use to cache collections of objects to gain code speed ups.
24
+ #
25
+ # points = points.collect{|point| Memoizer.cache(point)}
26
+ #
27
+ # After our algorithm has finished using points, we want to get rid of
28
+ # these Memoizer objects. That's easy:
29
+ #
30
+ # points = points.collect{|point| point.__self__ }
31
+ #
32
+ # Or if you prefer (it is ever so slightly safer):
33
+ #
34
+ # points = points.collect{|point| Memoizer.uncache(point)}
35
+ #
36
+ class Memoizer
37
+
38
+ #private :class, :clone, :display, :type, :method, :to_a, :to_s
39
+ private *instance_methods(true).select{ |m| m.to_s !~ /^__/ }
40
+
41
+ def initialize(object)
42
+ @self = object
43
+ @cache = {}
44
+ end
45
+
46
+ def __self__ ; @self ; end
47
+
48
+ # Not thread-safe! Speed is important in caches... ;]
49
+ def method_missing(method_name, *args, &block)
50
+ @cache[[method_name, args, block]] ||= @self.__send__(method_name, *args, &block)
51
+ end
52
+
53
+ #def self; @self; end
54
+
55
+ def self.cache(object)
56
+ new(object)
57
+ end
58
+
59
+ def self.uncache(cached_object)
60
+ cached_object.instance_variable_get('@self')
61
+ end
62
+
63
+ end
64
+
@@ -70,11 +70,16 @@ class Module
70
70
  methods = {}
71
71
  mod.instance_methods(false).each do |m|
72
72
  methods[m.to_sym] = mod.instance_method(m)
73
- mod.instance_eval do
74
- define_method(m) do
75
- super
73
+ mod.module_eval %{
74
+ def #{m}(*a,&b)
75
+ super(*a,&b)
76
76
  end
77
- end
77
+ }
78
+ #mod.instance_eval do
79
+ #define_method(m)
80
+ # super
81
+ #end
82
+ #end
78
83
  end
79
84
 
80
85
  # Add a method for the namespace that delegates
@@ -1,122 +1,3 @@
1
- # = Class Extension
2
- #
3
- # Normally when including modules, class/module methods are not
4
- # extended. To achieve this behavior requires some clever
5
- # Ruby Karate. Instead class_extension provides an easy to use
6
- # and clean solution. Simply place the extending class methods
7
- # in a block of the special module method #class_extension.
8
- #
9
- # module Mix
10
- # def inst_meth
11
- # puts 'inst_meth'
12
- # end
13
- #
14
- # class_extend do
15
- # def class_meth
16
- # "Class Method!"
17
- # end
18
- # end
19
- # end
20
- #
21
- # class X
22
- # include Mix
23
- # end
24
- #
25
- # X.class_meth #=> "Class Method!"
26
- #
27
- # == History
28
- #
29
- # Thanks to Trans, Nobu and Ulysses for their original on this concept.
30
- #
31
- # == Authors
32
- #
33
- # * Daniel Schierbeck
34
- # * Thomas Sawyer
35
- # * Nobu Nakada
36
- # * Ulysses
37
- #
38
- # == Copying
39
- #
40
- # Copyright (c) 2006 Daniel Schierbeck
41
- #
42
- # Ruby License
43
- #
44
- # This module is free software. You may use, modify, and/or redistribute this
45
- # software under the same terms as Ruby.
46
- #
47
- # This program is distributed in the hope that it will be useful, but WITHOUT
48
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
49
- # FOR A PARTICULAR PURPOSE.
50
-
51
- #
52
- class Module
53
-
54
- alias_method :append_features_without_class_extension, :append_features
55
-
56
- # Normally when including modules, class/module methods are not
57
- # extended. To achieve this behavior requires some clever
58
- # Ruby Karate. Instead class_extension provides an easy to use
59
- # and clean solution. Simply place the extending class methods
60
- # in a block of the special module method #class_extension.
61
- #
62
- # module Mix
63
- # def inst_meth
64
- # puts 'inst_meth'
65
- # end
66
- #
67
- # class_extend do
68
- # def class_meth
69
- # "Class Method!"
70
- # end
71
- # end
72
- # end
73
- #
74
- # class X
75
- # include Mix
76
- # end
77
- #
78
- # X.class_meth #=> "Class Method!"
79
- #
80
- # NOTE: This old #class_extension version of this method
81
- # did not extend the containing class automatically --it had
82
- # to be done by hand. With #class_extend, that is no longer
83
- # the case.
84
- #
85
- def class_extend(*mods, &block)
86
- @class_extension ||= Module.new do
87
- def self.append_features(mod)
88
- append_features_without_class_extension(mod)
89
- end
90
- end
91
- @class_extension.__send__(:include, *mods)
92
- @class_extension.module_eval(&block) if block_given?
93
- extend(@class_extension) # extend this module too
94
- @class_extension
95
- end
96
-
97
- # TODO: DEPRECATE
98
- alias_method :class_extension, :class_extend
99
-
100
- #private :class_extend
101
-
102
- # Override +append_features+ to handle class-inheritable extensions.
103
- def append_features(mod)
104
- append_features_without_class_extension(mod)
105
- mod.extend(class_extend)
106
- if mod.instance_of? Module
107
- mod.__send__(:class_extend).__send__(:include, class_extend)
108
- end
109
- end
110
-
111
- end
112
-
113
- class Class
114
- # For Class, #class_extend is the same as class_eval.
115
- # The alternative is to "undef_method :class_extend",
116
- # but this seems uneccessarily limited.
117
- #
118
- def class_extend(&blk)
119
- class_eval(&blk)
120
- end
121
- end
1
+ warn "use 'facets/class_extend' for future versions"
2
+ require 'facets/class_extend'
122
3
 
@@ -34,13 +34,13 @@ class OpenStruct
34
34
  # o.name = 'John Smith'
35
35
  # o.gender = :M
36
36
  # o.age = 71
37
- # end
37
+ # end
38
38
  #
39
39
  # You can still provide a hash for initialization purposes, and even combine
40
40
  # the two approaches if you wish.
41
41
  #
42
42
  # person = OpenStruct.new(:name => 'John Smith', :age => 31) do |p|
43
- # p.gender = :M
43
+ # p.gender = :M
44
44
  # end
45
45
  #
46
46
  # Alternatively you can provide a default block:
@@ -201,13 +201,6 @@ class Hash
201
201
  OpenStruct.new(self)
202
202
  end
203
203
 
204
- # CREDIT Alison Rowland, Jamie Macey, Mat Schaffer
205
-
206
- #--
207
- # Special thanks to Alison Rowland, Jamie Macey and Mat Schaffer
208
- # for inspiring recursive improvements.
209
- #++
210
-
211
204
  # Like to_ostruct but recusively objectifies all hash elements as well.
212
205
  #
213
206
  # o = { 'a' => { 'b' => 1 } }.to_ostruct_recurse
@@ -223,6 +216,8 @@ class Hash
223
216
  # o = h.to_ostruct_recurse( { h['a'] => h['a'] } )
224
217
  # o.a['b'] #=> 1
225
218
  #
219
+ # CREDIT: Alison Rowland, Jamie Macey, Mat Schaffer
220
+
226
221
  def to_ostruct_recurse(exclude={})
227
222
  return exclude[self] if exclude.key?( self )
228
223
  o = exclude[self] = OpenStruct.new
@@ -233,5 +228,10 @@ class Hash
233
228
  o.__update__(h)
234
229
  end
235
230
 
231
+ #--
232
+ # Special thanks to Alison Rowland, Jamie Macey and Mat Schaffer
233
+ # for inspiring recursive improvements.
234
+ #++
235
+
236
236
  end
237
237
 
@@ -89,16 +89,8 @@ $:.find_ext = 'rb'
89
89
  # Doesn't work
90
90
  #ENV['PATH'] = PathList.new(ENV['PATH'])
91
91
 
92
- #++
93
92
 
94
-
95
- # _____ _
96
- # |_ _|__ ___| |_
97
- # | |/ _ \/ __| __|
98
- # | | __/\__ \ |_
99
- # |_|\___||___/\__|
100
- #
101
- =begin #testing
93
+ =begin test
102
94
 
103
95
  require 'test/unit'
104
96
 
@@ -129,7 +129,7 @@ class Pathname
129
129
  flags = 0
130
130
  opts.each do |opt|
131
131
  case opt when Symbol, String
132
- flags += File.const_get("FNM_#{opt}".upcase)
132
+ flags += ::File.const_get("FNM_#{opt}".upcase)
133
133
  else
134
134
  flags += opt
135
135
  end
@@ -156,10 +156,17 @@ class Pathname
156
156
  Dir.glob(::File.join(self.to_s, '*')).empty?
157
157
  end
158
158
 
159
- end
159
+ #
160
+ def uptodate?(*sources)
161
+ ::FileUtils.uptodate?(to_s, sources.flatten)
162
+ end
160
163
 
161
- # Constant alias of Pathname (short is better!)
162
- Path = Pathname
164
+ #
165
+ def outofdate?(*sources)
166
+ ::FileUtils.outofdate?(to_s, sources.flatten)
167
+ end
168
+
169
+ end
163
170
 
164
171
  class NilClass
165
172
  # Provide platform dependent null path.