pry 0.9.12.6 → 0.10.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +702 -0
  3. data/LICENSE +2 -2
  4. data/{README.markdown → README.md} +37 -31
  5. data/lib/pry.rb +38 -151
  6. data/lib/pry/cli.rb +35 -17
  7. data/lib/pry/code.rb +24 -63
  8. data/lib/pry/code/code_file.rb +103 -0
  9. data/lib/pry/code/code_range.rb +2 -1
  10. data/lib/pry/code/loc.rb +2 -2
  11. data/lib/pry/code_object.rb +40 -21
  12. data/lib/pry/color_printer.rb +55 -0
  13. data/lib/pry/command.rb +12 -9
  14. data/lib/pry/command_set.rb +81 -38
  15. data/lib/pry/commands.rb +1 -1
  16. data/lib/pry/commands/amend_line.rb +2 -2
  17. data/lib/pry/commands/bang.rb +1 -1
  18. data/lib/pry/commands/cat.rb +11 -2
  19. data/lib/pry/commands/cat/exception_formatter.rb +5 -6
  20. data/lib/pry/commands/cat/file_formatter.rb +15 -32
  21. data/lib/pry/commands/cd.rb +14 -3
  22. data/lib/pry/commands/change_inspector.rb +27 -0
  23. data/lib/pry/commands/change_prompt.rb +26 -0
  24. data/lib/pry/commands/code_collector.rb +4 -4
  25. data/lib/pry/commands/easter_eggs.rb +3 -3
  26. data/lib/pry/commands/edit.rb +10 -22
  27. data/lib/pry/commands/edit/exception_patcher.rb +2 -2
  28. data/lib/pry/commands/edit/file_and_line_locator.rb +0 -2
  29. data/lib/pry/commands/exit_program.rb +0 -1
  30. data/lib/pry/commands/find_method.rb +16 -22
  31. data/lib/pry/commands/gem_install.rb +5 -2
  32. data/lib/pry/commands/gem_open.rb +1 -1
  33. data/lib/pry/commands/gist.rb +10 -11
  34. data/lib/pry/commands/help.rb +14 -14
  35. data/lib/pry/commands/hist.rb +27 -8
  36. data/lib/pry/commands/install_command.rb +14 -12
  37. data/lib/pry/commands/list_inspectors.rb +35 -0
  38. data/lib/pry/commands/list_prompts.rb +35 -0
  39. data/lib/pry/commands/ls.rb +72 -296
  40. data/lib/pry/commands/ls/constants.rb +47 -0
  41. data/lib/pry/commands/ls/formatter.rb +49 -0
  42. data/lib/pry/commands/ls/globals.rb +48 -0
  43. data/lib/pry/commands/ls/grep.rb +21 -0
  44. data/lib/pry/commands/ls/instance_vars.rb +39 -0
  45. data/lib/pry/commands/ls/interrogatable.rb +18 -0
  46. data/lib/pry/commands/ls/jruby_hacks.rb +49 -0
  47. data/lib/pry/commands/ls/local_names.rb +35 -0
  48. data/lib/pry/commands/ls/local_vars.rb +39 -0
  49. data/lib/pry/commands/ls/ls_entity.rb +70 -0
  50. data/lib/pry/commands/ls/methods.rb +57 -0
  51. data/lib/pry/commands/ls/methods_helper.rb +46 -0
  52. data/lib/pry/commands/ls/self_methods.rb +32 -0
  53. data/lib/pry/commands/play.rb +44 -10
  54. data/lib/pry/commands/pry_backtrace.rb +1 -2
  55. data/lib/pry/commands/raise_up.rb +2 -2
  56. data/lib/pry/commands/reload_code.rb +16 -19
  57. data/lib/pry/commands/ri.rb +7 -3
  58. data/lib/pry/commands/shell_command.rb +18 -13
  59. data/lib/pry/commands/shell_mode.rb +2 -4
  60. data/lib/pry/commands/show_doc.rb +5 -0
  61. data/lib/pry/commands/show_info.rb +8 -13
  62. data/lib/pry/commands/show_source.rb +15 -3
  63. data/lib/pry/commands/simple_prompt.rb +1 -1
  64. data/lib/pry/commands/toggle_color.rb +8 -4
  65. data/lib/pry/commands/watch_expression.rb +105 -0
  66. data/lib/pry/commands/watch_expression/expression.rb +38 -0
  67. data/lib/pry/commands/whereami.rb +18 -10
  68. data/lib/pry/commands/wtf.rb +3 -3
  69. data/lib/pry/config.rb +20 -254
  70. data/lib/pry/config/behavior.rb +139 -0
  71. data/lib/pry/config/convenience.rb +26 -0
  72. data/lib/pry/config/default.rb +165 -0
  73. data/lib/pry/core_extensions.rb +31 -21
  74. data/lib/pry/editor.rb +107 -103
  75. data/lib/pry/exceptions.rb +77 -0
  76. data/lib/pry/helpers/base_helpers.rb +22 -109
  77. data/lib/pry/helpers/command_helpers.rb +10 -8
  78. data/lib/pry/helpers/documentation_helpers.rb +1 -2
  79. data/lib/pry/helpers/text.rb +4 -5
  80. data/lib/pry/history.rb +46 -45
  81. data/lib/pry/history_array.rb +6 -1
  82. data/lib/pry/hooks.rb +9 -29
  83. data/lib/pry/indent.rb +6 -6
  84. data/lib/pry/input_completer.rb +242 -0
  85. data/lib/pry/input_lock.rb +132 -0
  86. data/lib/pry/inspector.rb +27 -0
  87. data/lib/pry/last_exception.rb +61 -0
  88. data/lib/pry/method.rb +82 -87
  89. data/lib/pry/{commands/edit/method_patcher.rb → method/patcher.rb} +41 -38
  90. data/lib/pry/module_candidate.rb +4 -14
  91. data/lib/pry/object_path.rb +82 -0
  92. data/lib/pry/output.rb +50 -0
  93. data/lib/pry/pager.rb +191 -47
  94. data/lib/pry/plugins.rb +1 -1
  95. data/lib/pry/prompt.rb +26 -0
  96. data/lib/pry/pry_class.rb +149 -230
  97. data/lib/pry/pry_instance.rb +302 -413
  98. data/lib/pry/rbx_path.rb +1 -1
  99. data/lib/pry/repl.rb +202 -0
  100. data/lib/pry/repl_file_loader.rb +20 -26
  101. data/lib/pry/rubygem.rb +13 -5
  102. data/lib/pry/terminal.rb +2 -1
  103. data/lib/pry/test/helper.rb +26 -41
  104. data/lib/pry/version.rb +1 -1
  105. data/lib/pry/wrapped_module.rb +45 -59
  106. metadata +61 -224
  107. data/.document +0 -2
  108. data/.gitignore +0 -16
  109. data/.travis.yml +0 -25
  110. data/.yardopts +0 -1
  111. data/CHANGELOG +0 -534
  112. data/CONTRIBUTORS +0 -55
  113. data/Gemfile +0 -12
  114. data/Rakefile +0 -140
  115. data/TODO +0 -117
  116. data/lib/pry/completion.rb +0 -321
  117. data/lib/pry/custom_completions.rb +0 -6
  118. data/lib/pry/rbx_method.rb +0 -13
  119. data/man/pry.1 +0 -195
  120. data/man/pry.1.html +0 -204
  121. data/man/pry.1.ronn +0 -141
  122. data/pry.gemspec +0 -29
  123. data/spec/Procfile +0 -3
  124. data/spec/cli_spec.rb +0 -78
  125. data/spec/code_object_spec.rb +0 -277
  126. data/spec/code_spec.rb +0 -219
  127. data/spec/command_helpers_spec.rb +0 -29
  128. data/spec/command_integration_spec.rb +0 -644
  129. data/spec/command_set_spec.rb +0 -627
  130. data/spec/command_spec.rb +0 -821
  131. data/spec/commands/amend_line_spec.rb +0 -247
  132. data/spec/commands/bang_spec.rb +0 -19
  133. data/spec/commands/cat_spec.rb +0 -164
  134. data/spec/commands/cd_spec.rb +0 -250
  135. data/spec/commands/disable_pry_spec.rb +0 -25
  136. data/spec/commands/edit_spec.rb +0 -727
  137. data/spec/commands/exit_all_spec.rb +0 -34
  138. data/spec/commands/exit_program_spec.rb +0 -19
  139. data/spec/commands/exit_spec.rb +0 -34
  140. data/spec/commands/find_method_spec.rb +0 -70
  141. data/spec/commands/gem_list_spec.rb +0 -26
  142. data/spec/commands/gist_spec.rb +0 -79
  143. data/spec/commands/help_spec.rb +0 -56
  144. data/spec/commands/hist_spec.rb +0 -181
  145. data/spec/commands/jump_to_spec.rb +0 -15
  146. data/spec/commands/ls_spec.rb +0 -181
  147. data/spec/commands/play_spec.rb +0 -140
  148. data/spec/commands/raise_up_spec.rb +0 -56
  149. data/spec/commands/save_file_spec.rb +0 -177
  150. data/spec/commands/show_doc_spec.rb +0 -510
  151. data/spec/commands/show_input_spec.rb +0 -17
  152. data/spec/commands/show_source_spec.rb +0 -782
  153. data/spec/commands/whereami_spec.rb +0 -203
  154. data/spec/completion_spec.rb +0 -241
  155. data/spec/control_d_handler_spec.rb +0 -58
  156. data/spec/documentation_helper_spec.rb +0 -73
  157. data/spec/editor_spec.rb +0 -79
  158. data/spec/exception_whitelist_spec.rb +0 -21
  159. data/spec/fixtures/candidate_helper1.rb +0 -11
  160. data/spec/fixtures/candidate_helper2.rb +0 -8
  161. data/spec/fixtures/example.erb +0 -5
  162. data/spec/fixtures/example_nesting.rb +0 -33
  163. data/spec/fixtures/show_source_doc_examples.rb +0 -15
  164. data/spec/fixtures/testrc +0 -2
  165. data/spec/fixtures/testrcbad +0 -2
  166. data/spec/fixtures/whereami_helper.rb +0 -6
  167. data/spec/helper.rb +0 -34
  168. data/spec/helpers/bacon.rb +0 -86
  169. data/spec/helpers/mock_pry.rb +0 -43
  170. data/spec/helpers/table_spec.rb +0 -105
  171. data/spec/history_array_spec.rb +0 -67
  172. data/spec/hooks_spec.rb +0 -522
  173. data/spec/indent_spec.rb +0 -301
  174. data/spec/input_stack_spec.rb +0 -90
  175. data/spec/method_spec.rb +0 -482
  176. data/spec/prompt_spec.rb +0 -60
  177. data/spec/pry_defaults_spec.rb +0 -419
  178. data/spec/pry_history_spec.rb +0 -99
  179. data/spec/pry_output_spec.rb +0 -95
  180. data/spec/pry_spec.rb +0 -515
  181. data/spec/run_command_spec.rb +0 -25
  182. data/spec/sticky_locals_spec.rb +0 -157
  183. data/spec/syntax_checking_spec.rb +0 -81
  184. data/spec/wrapped_module_spec.rb +0 -261
  185. data/wiki/Customizing-pry.md +0 -397
  186. data/wiki/Home.md +0 -4
@@ -0,0 +1,27 @@
1
+ class Pry::Inspector
2
+ MAP = {
3
+ "default" => {
4
+ value: Pry::DEFAULT_PRINT,
5
+ description: <<-DESCRIPTION.each_line.map(&:lstrip!)
6
+ The default Pry inspector. It has paging and color support, and uses
7
+ pretty_inspect when printing an object.
8
+ DESCRIPTION
9
+ },
10
+
11
+ "simple" => {
12
+ value: Pry::SIMPLE_PRINT,
13
+ description: <<-DESCRIPTION.each_line.map(&:lstrip)
14
+ A simple inspector that uses #puts and #inspect when printing an
15
+ object. It has no pager, color, or pretty_inspect support.
16
+ DESCRIPTION
17
+ },
18
+
19
+ "clipped" => {
20
+ value: Pry::CLIPPED_PRINT,
21
+ description: <<-DESCRIPTION.each_line.map(&:lstrip)
22
+ The clipped inspector has the same features as the 'simple' inspector
23
+ but prints large objects as a smaller string.
24
+ DESCRIPTION
25
+ }
26
+ }
27
+ end
@@ -0,0 +1,61 @@
1
+ #
2
+ # {Pry::LastException} is a proxy class who wraps an Exception object for
3
+ # {Pry#last_exception}. it extends the exception object with methods that
4
+ # help pry commands be useful.
5
+ #
6
+ # the original exception object is not modified and method calls are forwarded
7
+ # to the wrapped exception object.
8
+ #
9
+ class Pry::LastException < BasicObject
10
+ attr_accessor :bt_index
11
+
12
+ def initialize(e)
13
+ @e = e
14
+ @bt_index = 0
15
+ @file, @line = bt_source_location_for(0)
16
+ end
17
+
18
+ def method_missing(name, *args, &block)
19
+ if @e.respond_to?(name)
20
+ @e.public_send(name, *args, &block)
21
+ else
22
+ super
23
+ end
24
+ end
25
+
26
+ def respond_to_missing?(name, include_private = false)
27
+ @e.respond_to?(name)
28
+ end
29
+
30
+ #
31
+ # @return [String]
32
+ # returns the path to a file for the current backtrace. see {#bt_index}.
33
+ #
34
+ def file
35
+ @file
36
+ end
37
+
38
+ #
39
+ # @return [Fixnum]
40
+ # returns the line for the current backtrace. see {#bt_index}.
41
+ #
42
+ def line
43
+ @line
44
+ end
45
+
46
+ # @return [Exception]
47
+ # returns the wrapped exception
48
+ #
49
+ def wrapped_exception
50
+ @e
51
+ end
52
+
53
+ def bt_source_location_for(index)
54
+ backtrace[index] =~ /(.*):(\d+)/
55
+ [$1, $2.to_i]
56
+ end
57
+
58
+ def inc_bt_index
59
+ @bt_index = (@bt_index + 1) % backtrace.size
60
+ end
61
+ end
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  require 'pry/helpers/documentation_helpers'
3
2
 
4
3
  class Pry
@@ -19,10 +18,10 @@ class Pry
19
18
  class Method
20
19
  require 'pry/method/weird_method_locator'
21
20
  require 'pry/method/disowned'
21
+ require 'pry/method/patcher'
22
22
 
23
23
  extend Helpers::BaseHelpers
24
24
  include Helpers::BaseHelpers
25
- include RbxMethod if rbx?
26
25
  include Helpers::DocumentationHelpers
27
26
  include CodeObject::Helpers
28
27
 
@@ -31,8 +30,7 @@ class Pry
31
30
  # search in, find and return the requested method wrapped in a `Pry::Method`
32
31
  # instance.
33
32
  #
34
- # @param [String, nil] name The name of the method to retrieve, or `nil` to
35
- # delegate to `from_binding` instead.
33
+ # @param [String] name The name of the method to retrieve.
36
34
  # @param [Binding] target The context in which to search for the method.
37
35
  # @param [Hash] options
38
36
  # @option options [Boolean] :instance Look for an instance method if `name` doesn't
@@ -40,13 +38,16 @@ class Pry
40
38
  # @option options [Boolean] :methods Look for a bound/singleton method if `name` doesn't
41
39
  # contain any context.
42
40
  # @return [Pry::Method, nil] A `Pry::Method` instance containing the requested
43
- # method, or `nil` if no method could be located matching the parameters.
41
+ # method, or `nil` if name is `nil` or no method could be located matching the parameters.
44
42
  def from_str(name, target=TOPLEVEL_BINDING, options={})
45
43
  if name.nil?
46
- from_binding(target)
44
+ nil
47
45
  elsif name.to_s =~ /(.+)\#(\S+)\Z/
48
46
  context, meth_name = $1, $2
49
47
  from_module(target.eval(context), meth_name, target)
48
+ elsif name.to_s =~ /(.+)(\[\])\Z/
49
+ context, meth_name = $1, $2
50
+ from_obj(target.eval(context), meth_name, target)
50
51
  elsif name.to_s =~ /(.+)(\.|::)(\S+)\Z/
51
52
  context, meth_name = $1, $3
52
53
  from_obj(target.eval(context), meth_name, target)
@@ -139,15 +140,34 @@ class Pry
139
140
  # @param [Boolean] include_super Whether to include methods from ancestors.
140
141
  # @return [Array[Pry::Method]]
141
142
  def all_from_class(klass, include_super=true)
142
- all_from_common(klass, :instance_method, include_super)
143
+ %w(public protected private).map do |visibility|
144
+ safe_send(klass, :"#{visibility}_instance_methods", include_super).map do |method_name|
145
+ new(safe_send(klass, :instance_method, method_name), :visibility => visibility.to_sym)
146
+ end
147
+ end.flatten(1)
143
148
  end
144
149
 
150
+ #
145
151
  # Get all of the methods on an `Object`
152
+ #
146
153
  # @param [Object] obj
147
- # @param [Boolean] include_super Whether to include methods from ancestors.
154
+ #
155
+ # @param [Boolean] include_super
156
+ # indicates whether or not to include methods from ancestors.
157
+ #
148
158
  # @return [Array[Pry::Method]]
159
+ #
149
160
  def all_from_obj(obj, include_super=true)
150
- all_from_common(obj, :method, include_super)
161
+ all_from_class(singleton_class_of(obj), include_super)
162
+ end
163
+
164
+ #
165
+ # @deprecated
166
+ # please use {#all_from_obj} instead.
167
+ # the `method_type` argument is ignored.
168
+ #
169
+ def all_from_common(obj, method_type = nil, include_super=true)
170
+ all_from_obj(obj, include_super)
151
171
  end
152
172
 
153
173
  # Get every `Class` and `Module`, in order, that will be checked when looking
@@ -158,7 +178,7 @@ class Pry
158
178
  if Class === obj
159
179
  singleton_class_resolution_order(obj) + instance_resolution_order(Class)
160
180
  else
161
- klass = singleton_class(obj) rescue obj.class
181
+ klass = singleton_class_of(obj) rescue obj.class
162
182
  instance_resolution_order(klass)
163
183
  end
164
184
  end
@@ -170,7 +190,7 @@ class Pry
170
190
  # @return [Array[Class, Module]]
171
191
  def instance_resolution_order(klass)
172
192
  # include klass in case it is a singleton class,
173
- ([klass] + klass.ancestors).uniq
193
+ ([klass] + Pry::Method.safe_send(klass, :ancestors)).uniq
174
194
  end
175
195
 
176
196
  def method_definition?(name, definition_line)
@@ -179,26 +199,11 @@ class Pry
179
199
  end
180
200
 
181
201
  def singleton_method_definition?(name, definition_line)
182
- /^define_singleton_method\(?\s*[:\"\']#{name}|^def\s*self\.#{name}/ =~ definition_line.strip
202
+ /^define_singleton_method\(?\s*[:\"\']#{Regexp.escape(name)}|^def\s*self\.#{Regexp.escape(name)}/ =~ definition_line.strip
183
203
  end
184
204
 
185
205
  def instance_method_definition?(name, definition_line)
186
- /^define_method\(?\s*[:\"\']#{name}|^def\s*#{name}/ =~ definition_line.strip
187
- end
188
-
189
- private
190
-
191
- # See all_from_class and all_from_obj.
192
- # If method_type is :instance_method, obj must be a `Class` or a `Module`
193
- # If method_type is :method, obj can be any `Object`
194
- #
195
- # N.B. we pre-cache the visibility here to avoid O(N²) behaviour in "ls".
196
- def all_from_common(obj, method_type, include_super=true)
197
- %w(public protected private).map do |visibility|
198
- safe_send(obj, :"#{visibility}_#{method_type}s", include_super).map do |method_name|
199
- new(safe_send(obj, method_type, method_name), :visibility => visibility.to_sym)
200
- end
201
- end.flatten(1)
206
+ /^define_method\(?\s*[:\"\']#{Regexp.escape(name)}|^def\s*#{Regexp.escape(name)}/ =~ definition_line.strip
202
207
  end
203
208
 
204
209
  # Get the singleton classes of superclasses that could define methods on
@@ -206,14 +211,21 @@ class Pry
206
211
  # If a module is included at multiple points in the ancestry, only
207
212
  # the lowest copy will be returned.
208
213
  def singleton_class_resolution_order(klass)
209
- resolution_order = klass.ancestors.map do |anc|
210
- [singleton_class(anc)] + singleton_class(anc).included_modules if anc.is_a?(Class)
211
- end.compact.flatten(1)
214
+ ancestors = Pry::Method.safe_send(klass, :ancestors)
215
+ resolution_order = ancestors.grep(Class).map do |anc|
216
+ [singleton_class_of(anc), *singleton_class_of(anc).included_modules]
217
+ end.flatten(1)
212
218
 
213
219
  resolution_order.reverse.uniq.reverse - Class.included_modules
214
220
  end
215
221
 
216
- def singleton_class(obj); class << obj; self; end end
222
+ def singleton_class_of(obj)
223
+ begin
224
+ class << obj; self; end
225
+ rescue TypeError # can't define singleton. Fixnum, Symbol, Float, ...
226
+ obj.class
227
+ end
228
+ end
217
229
  end
218
230
 
219
231
  # A new instance of `Pry::Method` wrapping the given `::Method`, `UnboundMethod`, or `Proc`.
@@ -263,26 +275,18 @@ class Pry
263
275
  def source
264
276
  @source ||= case source_type
265
277
  when :c
266
- info = pry_doc_info
267
- if info and info.source
268
- code = strip_comments_from_c_code(info.source)
269
- end
278
+ c_source
270
279
  when :ruby
271
- # clone of MethodSource.source_helper that knows to use our
272
- # hacked version of source_location for rbx core methods, and
273
- # our input buffer for methods defined in (pry)
274
- file, line = *source_location
275
- raise SourceNotFoundError, "Could not locate source for #{name_with_owner}!" unless file
276
-
277
- begin
278
- code = Pry::Code.from_file(file).expression_at(line)
279
- rescue SyntaxError => e
280
- raise MethodSource::SourceNotFoundError.new(e.message)
281
- end
282
- strip_leading_whitespace(code)
280
+ ruby_source
283
281
  end
284
282
  end
285
283
 
284
+ # Update the live copy of the method's source.
285
+ def redefine(source)
286
+ Patcher.new(self).patch_in_ram source
287
+ Pry::Method(owner.instance_method(name))
288
+ end
289
+
286
290
  # Can we get the source code for this method?
287
291
  # @return [Boolean]
288
292
  def source?
@@ -293,20 +297,13 @@ class Pry
293
297
 
294
298
  # @return [String, nil] The documentation for the method, or `nil` if it's
295
299
  # unavailable.
296
- # @raise [CommandError] Raises when the method was defined in the REPL.
297
300
  def doc
298
301
  @doc ||= case source_type
299
302
  when :c
300
303
  info = pry_doc_info
301
304
  info.docstring if info
302
305
  when :ruby
303
- if rbx? && !pry_method?
304
- get_comment_content(core_doc)
305
- elsif pry_method?
306
- get_comment_content(doc_for_pry_method)
307
- else
308
- get_comment_content(@method.comment)
309
- end
306
+ get_comment_content(comment)
310
307
  end
311
308
  end
312
309
 
@@ -316,15 +313,6 @@ class Pry
316
313
  source_location.nil? ? :c : :ruby
317
314
  end
318
315
 
319
- def source_location
320
- if @method.source_location && rbx?
321
- file, line = @method.source_location
322
- [RbxPath.convert_path_to_full(file), line]
323
- else
324
- @method.source_location
325
- end
326
- end
327
-
328
316
  # @return [String, nil] The name of the file the method is defined in, or
329
317
  # `nil` if the filename is unavailable.
330
318
  def source_file
@@ -434,15 +422,14 @@ class Pry
434
422
  end
435
423
 
436
424
  # @return [Array<String>] All known aliases for the method.
437
- # @note On Ruby 1.8 this method always returns an empty Array for methods
438
- # implemented in C.
439
425
  def aliases
440
426
  owner = @method.owner
441
427
  # Avoid using `to_sym` on {Method#name}, which returns a `String`, because
442
428
  # it won't be garbage collected.
443
429
  name = @method.name
444
430
 
445
- alias_list = owner.instance_methods.combination(2).select do |pair|
431
+ all_methods_to_compare = owner.instance_methods | owner.private_instance_methods
432
+ alias_list = all_methods_to_compare.combination(2).select do |pair|
446
433
  pair.include?(name) &&
447
434
  owner.instance_method(pair.first) == owner.instance_method(pair.last)
448
435
  end.flatten
@@ -483,6 +470,10 @@ class Pry
483
470
  @method.send(method_name, *args, &block)
484
471
  end
485
472
 
473
+ def comment
474
+ Pry::Code.from_file(source_file).comment_describing(source_line)
475
+ end
476
+
486
477
  private
487
478
 
488
479
  # @return [YARD::CodeObjects::MethodObject]
@@ -492,31 +483,13 @@ class Pry
492
483
  Pry::MethodInfo.info_for(@method) or raise CommandError, "Cannot locate this method: #{name}. (source_location returns nil)"
493
484
  else
494
485
  fail_msg = "Cannot locate this method: #{name}."
495
- if mri_18? || mri_19?
486
+ if mri?
496
487
  fail_msg += ' Try `gem-install pry-doc` to get access to Ruby Core documentation.'
497
488
  end
498
489
  raise CommandError, fail_msg
499
490
  end
500
491
  end
501
492
 
502
- # FIXME: a very similar method to this exists on WrappedModule: extract_doc_for_candidate
503
- def doc_for_pry_method
504
- _, line_num = source_location
505
-
506
- buffer = ""
507
- Pry.line_buffer[0..(line_num - 1)].each do |line|
508
- # Add any line that is a valid ruby comment,
509
- # but clear as soon as we hit a non comment line.
510
- if (line =~ /^\s*#/) || (line =~ /^\s*$/)
511
- buffer << line.lstrip
512
- else
513
- buffer.replace("")
514
- end
515
- end
516
-
517
- buffer
518
- end
519
-
520
493
  # @param [Class, Module] ancestors The ancestors to investigate
521
494
  # @return [Method] The unwrapped super-method
522
495
  def super_using_ancestors(ancestors, times=1)
@@ -547,5 +520,27 @@ class Pry
547
520
 
548
521
  nil
549
522
  end
523
+
524
+ def c_source
525
+ info = pry_doc_info
526
+ if info and info.source
527
+ strip_comments_from_c_code(info.source)
528
+ end
529
+ end
530
+
531
+ def ruby_source
532
+ # clone of MethodSource.source_helper that knows to use our
533
+ # hacked version of source_location for rbx core methods, and
534
+ # our input buffer for methods defined in (pry)
535
+ file, line = *source_location
536
+ raise SourceNotFoundError, "Could not locate source for #{name_with_owner}!" unless file
537
+
538
+ begin
539
+ code = Pry::Code.from_file(file).expression_at(line)
540
+ rescue SyntaxError => e
541
+ raise MethodSource::SourceNotFoundError.new(e.message)
542
+ end
543
+ strip_leading_whitespace(code)
544
+ end
550
545
  end
551
546
  end
@@ -1,37 +1,38 @@
1
1
  class Pry
2
- class Command::Edit
3
- class MethodPatcher
4
- attr_accessor :_pry_
5
- attr_accessor :code_object
2
+ class Method
3
+ class Patcher
4
+ attr_accessor :method
6
5
 
7
- def initialize(_pry_, code_object)
8
- @_pry_ = _pry_
9
- @code_object = code_object
6
+ @@source_cache = {}
7
+
8
+ def initialize(method)
9
+ @method = method
10
+ end
11
+
12
+ def self.code_for(filename)
13
+ @@source_cache[filename]
10
14
  end
11
15
 
12
16
  # perform the patch
13
- def perform_patch
14
- if code_object.alias?
17
+ def patch_in_ram(source)
18
+ if method.alias?
15
19
  with_method_transaction do
16
- _pry_.evaluate_ruby patched_code
20
+ redefine source
17
21
  end
18
22
  else
19
- _pry_.evaluate_ruby patched_code
23
+ redefine source
20
24
  end
21
25
  end
22
26
 
23
27
  private
24
28
 
25
- def patched_code
26
- @patched_code ||= wrap(Pry::Editor.edit_tempfile_with_content(adjusted_lines))
29
+ def redefine(source)
30
+ @@source_cache[cache_key] = source
31
+ TOPLEVEL_BINDING.eval wrap(source), cache_key
27
32
  end
28
33
 
29
- # The method code adjusted so that the first line is rewritten
30
- # so that def self.foo --> def foo
31
- def adjusted_lines
32
- lines = code_object.source.lines.to_a
33
- lines[0] = definition_line_for_owner(lines.first)
34
- lines
34
+ def cache_key
35
+ "pry-redefined(0x#{method.owner.object_id.to_s(16)}##{method.name})"
35
36
  end
36
37
 
37
38
  # Run some code ensuring that at the end target#meth_name will not have changed.
@@ -45,17 +46,17 @@ class Pry
45
46
  # @param [Module] target The owner of the method
46
47
 
47
48
  def with_method_transaction
48
- temp_name = "__pry_#{code_object.original_name}__"
49
- co = code_object
50
- code_object.owner.class_eval do
51
- alias_method temp_name, co.original_name
49
+ temp_name = "__pry_#{method.original_name}__"
50
+ method = self.method
51
+ method.owner.class_eval do
52
+ alias_method temp_name, method.original_name
52
53
  yield
53
- alias_method co.name, co.original_name
54
- alias_method co.original_name, temp_name
54
+ alias_method method.name, method.original_name
55
+ alias_method method.original_name, temp_name
55
56
  end
56
57
 
57
58
  ensure
58
- co.send(:remove_method, temp_name) rescue nil
59
+ method.send(:remove_method, temp_name) rescue nil
59
60
  end
60
61
 
61
62
  # Update the definition line so that it can be eval'd directly on the Method's
@@ -68,13 +69,13 @@ class Pry
68
69
  # This is necessarily done by String manipulation because we can't find out what
69
70
  # syntax is needed for the argument list by ruby-level introspection.
70
71
  #
71
- # @param String The original definition line. e.g. def self.foo(bar, baz=1)
72
- # @return String The new definition line. e.g. def foo(bar, baz=1)
73
- def definition_line_for_owner(line)
74
- if line =~ /^def (?:.*?\.)?#{Regexp.escape(code_object.original_name)}(?=[\(\s;]|$)/
75
- "def #{code_object.original_name}#{$'}"
72
+ # @param [String] line The original definition line. e.g. def self.foo(bar, baz=1)
73
+ # @return [String] The new definition line. e.g. def foo(bar, baz=1)
74
+ def definition_for_owner(line)
75
+ if line =~ /\Adef (?:.*?\.)?#{Regexp.escape(method.original_name)}(?=[\(\s;]|$)/
76
+ "def #{method.original_name}#{$'}"
76
77
  else
77
- raise CommandError, "Could not find original `def #{code_object.original_name}` line to patch."
78
+ raise CommandError, "Could not find original `def #{method.original_name}` line to patch."
78
79
  end
79
80
  end
80
81
 
@@ -87,15 +88,17 @@ class Pry
87
88
 
88
89
  # Update the source code so that when it has the right owner when eval'd.
89
90
  #
90
- # This (combined with definition_line_for_owner) is backup for the case that
91
+ # This (combined with definition_for_owner) is backup for the case that
91
92
  # wrap_for_nesting fails, to ensure that the method will stil be defined in
92
93
  # the correct place.
93
94
  #
94
95
  # @param [String] source The source to wrap
95
96
  # @return [String]
96
97
  def wrap_for_owner(source)
97
- Pry.current[:pry_owner] = code_object.owner
98
- "Pry.current[:pry_owner].class_eval do\n#{source}\nend"
98
+ Pry.current[:pry_owner] = method.owner
99
+ owner_source = definition_for_owner(source)
100
+ visibility_fix = "#{method.visibility.to_s} #{method.name.to_sym.inspect}"
101
+ "Pry.current[:pry_owner].class_eval do; #{owner_source}\n#{visibility_fix}\nend"
99
102
  end
100
103
 
101
104
  # Update the new source code to have the correct Module.nesting.
@@ -111,10 +114,10 @@ class Pry
111
114
  # @param [String] source The source to wrap.
112
115
  # @return [String]
113
116
  def wrap_for_nesting(source)
114
- nesting = Pry::Code.from_file(code_object.source_file).nesting_at(code_object.source_line)
117
+ nesting = Pry::Code.from_file(method.source_file).nesting_at(method.source_line)
115
118
 
116
- (nesting + [source] + nesting.map{ "end" } + [""]).join("\n")
117
- rescue Pry::Indent::UnparseableNestingError => e
119
+ (nesting + [source] + nesting.map{ "end" } + [""]).join(";")
120
+ rescue Pry::Indent::UnparseableNestingError
118
121
  source
119
122
  end
120
123
  end