ruby-nuggets 0.5.2 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  == VERSION
4
4
 
5
- This documentation refers to ruby-nuggets version 0.5.2
5
+ This documentation refers to ruby-nuggets version 0.5.4
6
6
 
7
7
 
8
8
  == DESCRIPTION
@@ -1,407 +1,6 @@
1
- #--
2
- ###############################################################################
3
- # #
4
- # A component of ruby-nuggets, some extensions to the Ruby programming #
5
- # language. #
6
- # #
7
- # Copyright (C) 2007-2008 Jens Wille #
8
- # #
9
- # Authors: #
10
- # Jens Wille <jens.wille@uni-koeln.de> #
11
- # #
12
- # ruby-nuggets is free software; you can redistribute it and/or modify it #
13
- # under the terms of the GNU General Public License as published by the Free #
14
- # Software Foundation; either version 3 of the License, or (at your option) #
15
- # any later version. #
16
- # #
17
- # ruby-nuggets is distributed in the hope that it will be useful, but WITHOUT #
18
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
19
- # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
20
- # more details. #
21
- # #
22
- # You should have received a copy of the GNU General Public License along #
23
- # with ruby-nuggets. If not, see <http://www.gnu.org/licenses/>. #
24
- # #
25
- ###############################################################################
26
- #++
27
-
28
- begin
29
- require 'ruby2ruby'
30
- rescue LoadError
31
- end
1
+ # backwards compatibility
2
+ require 'added_methods'
32
3
 
33
4
  module Util
34
-
35
- # Watch for added methods and record them. Inspired by unroller,
36
- # <http://unroller.rubyforge.org/classes/Unroller.html#M000034>.
37
- #
38
- # Example:
39
- #
40
- # require 'rubygems'
41
- # require 'nuggets/util/added_methods/init'
42
- #
43
- # require 'some/library/or/whatever'
44
- #
45
- # matches = Util::AddedMethods.find(
46
- # :name => 'method_name',
47
- # :class => SomeClass # optional
48
- # )
49
- #
50
- # # get the class(es) where matching method(s) were defined
51
- # matches.each { |am| puts am.klass # also am[:klass] or am[:class] }
52
- #
53
- # # assume the first one is the one we're looking for
54
- # am = matches.first
55
- #
56
- # # is it a singleton method?
57
- # puts am.singleton?
58
- #
59
- # # where exactly has it been defined?
60
- # puts "#{am.file}, line #{am.line}"
61
- #
62
- # # now get its source
63
- # puts am # implies #to_s, you can also call #extract_source directly
64
- #
65
- # TODO:
66
- # - multi-line statements in irb w/o ruby2ruby? (=> extract_source)
67
- # - polishing!
68
-
69
- module AddedMethods
70
-
71
- extend self
72
-
73
- HISTFILENAME = '(Readline::HISTORY)'.freeze unless const_defined?(:HISTFILENAME)
74
-
75
- class AddedMethod
76
-
77
- attr_accessor :base, :klass, :name, :singleton, :file, :line, :def
78
-
79
- def initialize(args = {})
80
- args.each { |key, value|
81
- send("#{key}=", value)
82
- }
83
- end
84
-
85
- alias_method 'class=', 'klass='
86
- alias_method :singleton?, :singleton
87
-
88
- def [](key)
89
- send(key.to_sym == :class ? :klass : key)
90
- end
91
-
92
- def source
93
- @source ||= extract_source
94
- end
95
-
96
- def extract_source(num_lines = nil)
97
- lines = extract_source_from_script_lines(num_lines)
98
-
99
- # try to make sure we correctly extracted the method
100
- # definition, otherwise try to get it from Ruby2Ruby
101
- lines.first =~ /\b#{name}\b/ ? lines : extract_source_from_r2r || lines
102
- end
103
-
104
- def to_s
105
- str = "# File #{file}, line #{line}"
106
-
107
- case lines = source
108
- when Array
109
- num = line - 1
110
- width = (num + lines.size).to_s.length
111
-
112
- lines.map! { |l| "%0#{width}d: %s" % [num += 1, l] }
113
-
114
- "#{' ' * width} #{str}\n#{lines}"
115
- when String
116
- "#{str}#{lines}"
117
- else
118
- str
119
- end
120
- end
121
-
122
- private
123
-
124
- def extract_source_from_script_lines(num_lines = nil)
125
- return unless Object.const_defined?(:SCRIPT_LINES__)
126
- return unless script_lines = SCRIPT_LINES__[file]
127
-
128
- start, from, to = line - 1, line, script_lines.size - 1
129
-
130
- # suppose we're already in a block
131
- in_block = 1
132
-
133
- num_lines ||= case definition = script_lines[start]
134
- # def ... end, or do ... end style block
135
- when /\b(?:def|do)\b/
136
- definition =~ /\bend\b/ ? 1 : begin
137
- from.upto(to) { |i|
138
- case line = script_lines[i]
139
- when /[^;\s]\s+(?:if|unless)\b/
140
- # probably postfix conditional, ignore
141
- when /\b(?:if|unless|while|until|def|do)\b/
142
- in_block += 1
143
- when /\bend\b/
144
- in_block -= 1
145
- end
146
-
147
- break i - start + 1 if in_block.zero?
148
- }
149
- end
150
- # { ... } style block
151
- when /\bdefine_method\b/
152
- from.upto(to) { |i|
153
- line = script_lines[i]
154
-
155
- in_block += line.count('{')
156
- in_block -= line.count('}')
157
-
158
- break i - start + 1 if in_block.zero?
159
- }
160
- else
161
- 1
162
- end
163
-
164
- script_lines[start, num_lines]
165
- end
166
-
167
- # Use Ruby2Ruby as a last resort. But note that it only
168
- # ever finds the *latest*, i.e. currently active, method
169
- # definition, not necessarily the one we're looking for.
170
- def extract_source_from_r2r
171
- if Object.const_defined?(:Ruby2Ruby)
172
- " [R2R]\n#{Ruby2Ruby.translate(klass, name)}"
173
- end
174
- end
175
-
176
- end
177
-
178
- def init(regexp = nil, klasses = [], &block)
179
- init_script_lines
180
- patch_readline_history
181
-
182
- define_callback(:__init, regexp, klasses, &block) if regexp
183
- install_callbacks
184
- end
185
-
186
- def callbacks
187
- init_callbacks
188
- CALLBACKS
189
- end
190
-
191
- def callback(*args, &inner_block)
192
- callback_args = [identify_added_method(*args << caller), caller, inner_block]
193
- callbacks.each { |name, callback| callback[*callback_args] }
194
- end
195
-
196
- def define_callback(name, regexp = //, klasses = [], &outer_block)
197
- raise TypeError, "wrong argument type #{name.class} (expected Symbol)" unless name.is_a?(Symbol)
198
- raise "callback with name #{name} already exists" if callbacks.assoc(name)
199
-
200
- raise TypeError, "wrong argument type #{regexp.class} (expected Regexp)" unless regexp.is_a?(Regexp)
201
- raise TypeError, "wrong argument type #{klasses.class} (expected container object)" unless klasses.respond_to?(:empty?) && klasses.respond_to?(:include?)
202
-
203
- callbacks << [name, lambda { |am, callstack, inner_block|
204
- method, klass = am.name, am.klass
205
-
206
- return if %w[method_added singleton_method_added].include?(method)
207
-
208
- return unless klasses.empty? || klasses.include?(klass.to_s)
209
- return unless method =~ regexp
210
-
211
- if outer_block || inner_block
212
- outer_block[am] if outer_block
213
- inner_block[am] if inner_block
214
- else
215
- msg = "[#{am.base}] Adding #{'singleton ' if am.singleton?}method #{klass}##{method}"
216
-
217
- msg << if irb?(callstack)
218
- " in (irb:#{IRB.conf[:MAIN_CONTEXT].instance_variable_get(:@line_no)})"
219
- else
220
- " at #{where(callstack)}"
221
- end
222
-
223
- puts msg
224
- end
225
- }]
226
- end
227
-
228
- def remove_callback(name)
229
- callbacks.delete_if { |n, _| n == name }
230
- end
231
-
232
- def replace_callback(name, regexp = nil, klasses = [], &outer_block)
233
- remove_callback(name)
234
- define_callback(name, regexp, klasses, &outer_block)
235
- end
236
-
237
- def install_callbacks(bases = [Object, Class, Module, Kernel])
238
- bases.each { |base|
239
- [base, singleton_class(base)].each { |b|
240
- b.send(:define_method, :method_added) { |id| AddedMethods.callback(b, self, id, false) }
241
- b.send(:define_method, :singleton_method_added) { |id| AddedMethods.callback(b, self, id, true) }
242
- }
243
- }
244
- end
245
-
246
- def all_methods
247
- init_all_methods
248
- ALL_METHODS
249
- end
250
-
251
- def find(conditions = {})
252
- conditions = conditions.dup
253
-
254
- class_condition = conditions.delete(:class)
255
- file_condition = conditions.delete(:file)
256
-
257
- results = []
258
-
259
- all_methods.each { |klass, files|
260
- if class_condition
261
- next unless class_condition.is_a?(Array) ? class_condition.include?(klass) : klass == class_condition
262
- end
263
-
264
- files.each { |file, entries|
265
- if file_condition
266
- next unless file_condition.is_a?(Regexp) ? file =~ file_condition : file == file_condition
267
- end
268
-
269
- entries.each { |am|
270
- results << am if conditions.all? { |key, value|
271
- case value
272
- when Array, Range then value.include?(am[key])
273
- when Regexp then value =~ am[key].to_s
274
- else value == am[key]
275
- end
276
- }
277
- }
278
- }
279
- }
280
-
281
- results
282
- end
283
-
284
- def find_by_class(*classes)
285
- conditions = classes.last.is_a?(Hash) ? classes.pop : {}
286
- find(conditions.merge(:class => classes))
287
- end
288
-
289
- def find_by_name(*names)
290
- conditions = names.last.is_a?(Hash) ? names.pop : {}
291
- find(conditions.merge(:name => names.map { |m| m.to_s }))
292
- end
293
-
294
- def find_one_by_name_or_class(name_or_class, conditions = {})
295
- (name_or_class.is_a?(Class) ?
296
- find_by_class(name_or_class) :
297
- find_by_name(name_or_class)
298
- ).last
299
- end
300
-
301
- alias_method :[], :find_one_by_name_or_class
302
-
303
- private
304
-
305
- def singleton_class(klass = self)
306
- class << klass; self; end
307
- end
308
-
309
- def init_script_lines
310
- unless Object.const_defined?(:SCRIPT_LINES__)
311
- Object.const_set(:SCRIPT_LINES__, {})
312
- end
313
- end
314
-
315
- def init_callbacks
316
- unless const_defined?(:CALLBACKS)
317
- const_set(:CALLBACKS, [])
318
- define_callback(:__default, //, [], &added_method_callback)
319
- end
320
- end
321
-
322
- def init_all_methods
323
- unless const_defined?(:ALL_METHODS)
324
- const_set(:ALL_METHODS, Hash.new { |h, k|
325
- h[k] = Hash.new { |i, j| i[j] = [] }
326
- })
327
- end
328
- end
329
-
330
- def patch_readline_history
331
- return unless have_readline_history?
332
- return if Readline::HISTORY.respond_to?(:_added_methods_original_push)
333
-
334
- class << Readline::HISTORY
335
- alias_method :_added_methods_original_push, :push
336
-
337
- def push(l)
338
- (SCRIPT_LINES__[HISTFILENAME] ||= Readline::HISTORY.to_a) << l
339
- _added_methods_original_push(l)
340
- end
341
-
342
- alias_method :<<, :push
343
- end
344
- end
345
-
346
- def have_readline_history?
347
- Object.const_defined?(:Readline) && Readline.const_defined?(:HISTORY)
348
- end
349
-
350
- def defined_in_irb?(callstack)
351
- callstack = callstack.dup
352
-
353
- callstack.shift # ignore immediate caller
354
- callstack.reject! { |c| c =~ /\(irb\):|:in `irb_binding'/ }
355
- callstack.pop if callstack.last =~ %r{/irb/workspace\.rb:}
356
-
357
- callstack.empty?
358
- end
359
-
360
- def irb?(callstack)
361
- have_readline_history? && defined_in_irb?(callstack)
362
- end
363
-
364
- def where(callstack, default = '(none):0')
365
- callstack.find { |i| i !~ /:in `.*'/ } || callstack[1] || default
366
- end
367
-
368
- def added_method_callback
369
- lambda { |am| add_method(am) }
370
- end
371
-
372
- def add_method(am)
373
- am = AddedMethod.new(am) unless am.is_a?(AddedMethod)
374
- all_methods[am.klass][am.file] << am
375
- end
376
-
377
- def identify_added_method(base, klass, id, singleton, callstack)
378
- am = {
379
- :base => base,
380
- :class => klass,
381
- :name => id.id2name,
382
- :singleton => singleton
383
- }
384
-
385
- if irb?(callstack)
386
- am.update(
387
- :file => HISTFILENAME,
388
- :line => Readline::HISTORY.size,
389
- :def => begin Readline::HISTORY[-1] rescue IndexError end
390
- )
391
- else
392
- file, line, _ = where(callstack).split(':')
393
- line = line.to_i
394
-
395
- am.update(
396
- :file => file,
397
- :line => line,
398
- :def => (SCRIPT_LINES__[file] || [])[line - 1]
399
- )
400
- end
401
-
402
- AddedMethod.new(am)
403
- end
404
-
405
- end
406
-
5
+ AddedMethods = ::AddedMethods
407
6
  end
@@ -4,7 +4,7 @@ module Nuggets
4
4
 
5
5
  MAJOR = 0
6
6
  MINOR = 5
7
- TINY = 2
7
+ TINY = 4
8
8
 
9
9
  class << self
10
10
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-nuggets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jens Wille
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-12 00:00:00 +01:00
12
+ date: 2009-03-27 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -106,15 +106,15 @@ has_rdoc: true
106
106
  homepage: http://prometheus.rubyforge.org/ruby-nuggets
107
107
  post_install_message:
108
108
  rdoc_options:
109
- - --main
110
- - README
111
- - --line-numbers
112
109
  - --inline-source
113
110
  - --title
114
111
  - ruby-nuggets Application documentation
115
- - --all
116
112
  - --charset
117
113
  - UTF-8
114
+ - --main
115
+ - README
116
+ - --all
117
+ - --line-numbers
118
118
  require_paths:
119
119
  - lib
120
120
  required_ruby_version: !ruby/object:Gem::Requirement