module AddedMethods
TODO:
-
multi-line statements in irb w/o ruby2ruby? (=> extract_source)
-
polishing!
Constants
- HISTFILENAME
- VERSION
Public Instance Methods
all_methods()
click to toggle source
# File lib/added_methods.rb 113 def all_methods 114 init_all_methods 115 ALL_METHODS 116 end
callback(*args, &inner_block)
click to toggle source
# File lib/added_methods.rb 58 def callback(*args, &inner_block) 59 callback_args = [identify_added_method(*args << caller), caller, inner_block] 60 callbacks.each { |name, callback| callback[*callback_args] } 61 end
callbacks()
click to toggle source
# File lib/added_methods.rb 53 def callbacks 54 init_callbacks 55 CALLBACKS 56 end
define_callback(name, regexp = //, klasses = [], &outer_block)
click to toggle source
# File lib/added_methods.rb 63 def define_callback(name, regexp = //, klasses = [], &outer_block) 64 raise TypeError, "wrong argument type #{name.class} (expected Symbol)" unless name.is_a?(Symbol) 65 raise "callback with name #{name} already exists" if callbacks.assoc(name) 66 67 raise TypeError, "wrong argument type #{regexp.class} (expected Regexp)" unless regexp.is_a?(Regexp) 68 raise TypeError, "wrong argument type #{klasses.class} (expected container object)" unless klasses.respond_to?(:empty?) && klasses.respond_to?(:include?) 69 70 callbacks << [name, lambda { |am, callstack, inner_block| 71 method, klass = am.name, am.klass 72 73 return if %w[method_added singleton_method_added].include?(method) 74 75 return unless klasses.empty? || klasses.include?(klass.to_s) 76 return unless method =~ regexp 77 78 if outer_block || inner_block 79 outer_block[am] if outer_block 80 inner_block[am] if inner_block 81 else 82 msg = "[#{am.base}] Adding #{'singleton ' if am.singleton?}method #{klass}##{method}" 83 84 msg << if irb?(callstack) 85 " in (irb:#{IRB.conf[:MAIN_CONTEXT].instance_variable_get(:@line_no)})" 86 else 87 " at #{where(callstack)}" 88 end 89 90 puts msg 91 end 92 }] 93 end
find(conditions = {})
click to toggle source
# File lib/added_methods.rb 118 def find(conditions = {}) 119 conditions = conditions.dup 120 121 class_condition = conditions.delete(:class) 122 file_condition = conditions.delete(:file) 123 124 results = [] 125 126 all_methods.each { |klass, files| 127 if class_condition 128 next unless class_condition.is_a?(Array) ? class_condition.include?(klass) : klass == class_condition 129 end 130 131 files.each { |file, entries| 132 if file_condition 133 next unless file_condition.is_a?(Regexp) ? file =~ file_condition : file == file_condition 134 end 135 136 entries.each { |am| 137 results << am if conditions.all? { |key, value| 138 case value 139 when Array, Range then value.include?(am[key]) 140 when Regexp then value =~ am[key].to_s 141 else value == am[key] 142 end 143 } 144 } 145 } 146 } 147 148 results 149 end
find_by_class(*classes)
click to toggle source
# File lib/added_methods.rb 151 def find_by_class(*classes) 152 conditions = classes.last.is_a?(Hash) ? classes.pop : {} 153 find(conditions.merge(:class => classes)) 154 end
find_by_name(*names)
click to toggle source
# File lib/added_methods.rb 156 def find_by_name(*names) 157 conditions = names.last.is_a?(Hash) ? names.pop : {} 158 find(conditions.merge(:name => names.map { |m| m.to_s })) 159 end
find_one_by_name_or_class(name_or_class, conditions = {})
click to toggle source
# File lib/added_methods.rb 161 def find_one_by_name_or_class(name_or_class, conditions = {}) 162 (name_or_class.is_a?(Class) ? 163 find_by_class(name_or_class) : 164 find_by_name(name_or_class) 165 ).last 166 end
Also aliased as: []
init(regexp = nil, klasses = [], &block)
click to toggle source
# File lib/added_methods.rb 45 def init(regexp = nil, klasses = [], &block) 46 init_script_lines 47 patch_readline_history 48 49 define_callback(:__init, regexp, klasses, &block) if regexp 50 install_callbacks 51 end
install_callbacks(bases = [Object, Class, Module, Kernel])
click to toggle source
# File lib/added_methods.rb 104 def install_callbacks(bases = [Object, Class, Module, Kernel]) 105 bases.each { |base| 106 [base, singleton_class(base)].each { |b| 107 b.send(:define_method, :method_added) { |id| AddedMethods.callback(b, self, id, false) } 108 b.send(:define_method, :singleton_method_added) { |id| AddedMethods.callback(b, self, id, true) } 109 } 110 } 111 end
remove_callback(name)
click to toggle source
# File lib/added_methods.rb 95 def remove_callback(name) 96 callbacks.delete_if { |n, _| n == name } 97 end
replace_callback(name, regexp = nil, klasses = [], &outer_block)
click to toggle source
# File lib/added_methods.rb 99 def replace_callback(name, regexp = nil, klasses = [], &outer_block) 100 remove_callback(name) 101 define_callback(name, regexp, klasses, &outer_block) 102 end
Private Instance Methods
add_method(am)
click to toggle source
# File lib/added_methods.rb 239 def add_method(am) 240 am = AddedMethod.new(am) unless am.is_a?(AddedMethod) 241 all_methods[am.klass][am.file] << am 242 end
added_method_callback()
click to toggle source
# File lib/added_methods.rb 235 def added_method_callback 236 lambda { |am| add_method(am) } 237 end
defined_in_irb?(callstack)
click to toggle source
# File lib/added_methods.rb 217 def defined_in_irb?(callstack) 218 callstack = callstack.dup 219 220 callstack.shift # ignore immediate caller 221 callstack.reject! { |c| c =~ /\(irb\):|:in `irb_binding'/ } 222 callstack.pop if callstack.last =~ %r{/irb/workspace\.rb:} 223 224 callstack.empty? 225 end
have_readline_history?()
click to toggle source
# File lib/added_methods.rb 213 def have_readline_history? 214 Object.const_defined?(:Readline) && Readline.const_defined?(:HISTORY) 215 end
identify_added_method(base, klass, id, singleton, callstack)
click to toggle source
# File lib/added_methods.rb 244 def identify_added_method(base, klass, id, singleton, callstack) 245 am = { 246 :base => base, 247 :class => klass, 248 :name => id.id2name, 249 :singleton => singleton 250 } 251 252 if irb?(callstack) 253 am.update( 254 :file => HISTFILENAME, 255 :line => Readline::HISTORY.size, 256 :def => begin Readline::HISTORY[-1] rescue IndexError end 257 ) 258 else 259 file, line, _ = where(callstack).split(':') 260 line = line.to_i 261 262 am.update( 263 :file => file, 264 :line => line, 265 :def => (SCRIPT_LINES__[file] || [])[line - 1] 266 ) 267 end 268 269 AddedMethod.new(am) 270 end 271 272 end
init_all_methods()
click to toggle source
# File lib/added_methods.rb 189 def init_all_methods 190 unless const_defined?(:ALL_METHODS) 191 const_set(:ALL_METHODS, Hash.new { |h, k| 192 h[k] = Hash.new { |i, j| i[j] = [] } 193 }) 194 end 195 end
init_callbacks()
click to toggle source
# File lib/added_methods.rb 182 def init_callbacks 183 unless const_defined?(:CALLBACKS) 184 const_set(:CALLBACKS, []) 185 define_callback(:__default, //, [], &added_method_callback) 186 end 187 end
init_script_lines()
click to toggle source
# File lib/added_methods.rb 176 def init_script_lines 177 unless Object.const_defined?(:SCRIPT_LINES__) 178 Object.const_set(:SCRIPT_LINES__, {}) 179 end 180 end
irb?(callstack)
click to toggle source
# File lib/added_methods.rb 227 def irb?(callstack) 228 have_readline_history? && defined_in_irb?(callstack) 229 end
patch_readline_history()
click to toggle source
# File lib/added_methods.rb 197 def patch_readline_history 198 return unless have_readline_history? 199 return if Readline::HISTORY.respond_to?(:_added_methods_original_push) 200 201 class << Readline::HISTORY 202 alias_method :_added_methods_original_push, :push 203 204 def push(l) 205 (SCRIPT_LINES__[HISTFILENAME] ||= Readline::HISTORY.to_a) << l 206 _added_methods_original_push(l) 207 end 208 209 alias_method :<<, :push 210 end 211 end
singleton_class(klass = self)
click to toggle source
# File lib/added_methods.rb 172 def singleton_class(klass = self) 173 class << klass; self; end 174 end
where(callstack, default = '(none):0')
click to toggle source
# File lib/added_methods.rb 231 def where(callstack, default = '(none):0') 232 callstack.find { |i| i !~ /:in `.*'/ } || callstack[1] || default 233 end