pry 0.9.6.2-i386-mswin32 → 0.9.7-i386-mswin32

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 (45) hide show
  1. data/.gitignore +6 -0
  2. data/CHANGELOG +19 -1
  3. data/CONTRIBUTORS +22 -16
  4. data/Rakefile +12 -6
  5. data/bin/pry +15 -12
  6. data/lib/pry.rb +39 -28
  7. data/lib/pry/command_context.rb +1 -0
  8. data/lib/pry/command_processor.rb +9 -2
  9. data/lib/pry/command_set.rb +7 -0
  10. data/lib/pry/config.rb +8 -0
  11. data/lib/pry/default_commands/basic.rb +7 -10
  12. data/lib/pry/default_commands/context.rb +36 -26
  13. data/lib/pry/default_commands/documentation.rb +31 -123
  14. data/lib/pry/default_commands/gems.rb +9 -4
  15. data/lib/pry/default_commands/input.rb +21 -11
  16. data/lib/pry/default_commands/introspection.rb +79 -88
  17. data/lib/pry/default_commands/ls.rb +165 -176
  18. data/lib/pry/default_commands/shell.rb +8 -8
  19. data/lib/pry/extended_commands/experimental.rb +1 -5
  20. data/lib/pry/extended_commands/user_command_api.rb +17 -5
  21. data/lib/pry/helpers.rb +1 -0
  22. data/lib/pry/helpers/base_helpers.rb +5 -1
  23. data/lib/pry/helpers/command_helpers.rb +22 -241
  24. data/lib/pry/helpers/options_helpers.rb +58 -0
  25. data/lib/pry/helpers/text.rb +10 -4
  26. data/lib/pry/history.rb +1 -1
  27. data/lib/pry/indent.rb +205 -0
  28. data/lib/pry/method.rb +412 -0
  29. data/lib/pry/pry_class.rb +56 -15
  30. data/lib/pry/pry_instance.rb +63 -16
  31. data/lib/pry/rbx_method.rb +20 -0
  32. data/lib/pry/rbx_path.rb +34 -0
  33. data/lib/pry/version.rb +1 -1
  34. data/pry.gemspec +16 -16
  35. data/test/helper.rb +8 -4
  36. data/test/test_command_helpers.rb +1 -69
  37. data/test/test_command_set.rb +29 -28
  38. data/test/test_default_commands/test_documentation.rb +23 -10
  39. data/test/test_default_commands/test_introspection.rb +58 -13
  40. data/test/test_default_commands/test_ls.rb +148 -0
  41. data/test/test_indent.rb +234 -0
  42. data/test/test_input_stack.rb +13 -0
  43. data/test/test_method.rb +291 -0
  44. data/test/test_pry.rb +10 -1
  45. metadata +88 -71
data/lib/pry/history.rb CHANGED
@@ -34,7 +34,7 @@ class Pry
34
34
  # @param [String] line
35
35
  # @return [String] The same line that was passed in
36
36
  def push(line)
37
- unless line.empty? || (@history.last && line.strip == @history.last.strip)
37
+ unless line.empty? || (@history.last && line == @history.last)
38
38
  Readline::HISTORY << line
39
39
  @history << line
40
40
  end
data/lib/pry/indent.rb ADDED
@@ -0,0 +1,205 @@
1
+ require 'coderay'
2
+
3
+ class Pry
4
+ ##
5
+ # Pry::Indent is a class that can be used to indent a number of lines
6
+ # containing Ruby code similar as to how IRB does it (but better). The class
7
+ # works by tokenizing a string using CodeRay and then looping over those
8
+ # tokens. Based on the tokens in a line of code that line (or the next one)
9
+ # will be indented or un-indented by correctly.
10
+ #
11
+ class Indent
12
+ # String containing the spaces to be inserted before the next line.
13
+ attr_reader :indent_level
14
+
15
+ # The amount of spaces to insert for each indent level.
16
+ SPACES = ' '
17
+
18
+ # Hash containing all the tokens that should increase the indentation
19
+ # level. The keys of this hash are open tokens, the values the matching
20
+ # tokens that should prevent a line from being indented if they appear on
21
+ # the same line.
22
+ OPEN_TOKENS = {
23
+ 'def' => 'end',
24
+ 'class' => 'end',
25
+ 'module' => 'end',
26
+ 'do' => 'end',
27
+ 'if' => 'end',
28
+ 'unless' => 'end',
29
+ 'while' => 'end',
30
+ 'until' => 'end',
31
+ 'for' => 'end',
32
+ 'case' => 'end',
33
+ 'begin' => 'end',
34
+ '[' => ']',
35
+ '{' => '}',
36
+ '(' => ')'
37
+ }
38
+
39
+ # Which tokens can either be open tokens, or appear as modifiers on
40
+ # a single-line.
41
+ SINGLELINE_TOKENS = %w(if while until unless rescue)
42
+
43
+ # Collection of token types that should be ignored. Without this list
44
+ # keywords such as "class" inside strings would cause the code to be
45
+ # indented incorrectly.
46
+ IGNORE_TOKENS = [:space, :content, :string, :delimiter, :method, :ident]
47
+
48
+ # Tokens that indicate the end of a statement (i.e. that, if they appear
49
+ # directly before an "if" indicates that that if applies to the same line,
50
+ # not the next line)
51
+ STATEMENT_END_TOKENS = IGNORE_TOKENS + [:regexp, :integer, :float]
52
+
53
+ # Collection of tokens that should appear dedented even though they
54
+ # don't affect the surrounding code.
55
+ MIDWAY_TOKENS = %w(when else elsif rescue)
56
+
57
+ def initialize
58
+ reset
59
+ end
60
+
61
+ # reset internal state
62
+ def reset
63
+ @stack = []
64
+ @indent_level = ''
65
+ self
66
+ end
67
+
68
+ # Indents a string and returns it. This string can either be a single line
69
+ # or multiple ones.
70
+ #
71
+ # @example
72
+ # str = <<TXT
73
+ # class User
74
+ # attr_accessor :name
75
+ # end
76
+ # TXT
77
+ #
78
+ # # This would result in the following being displayed:
79
+ # #
80
+ # # class User
81
+ # # attr_accessor :name
82
+ # # end
83
+ # #
84
+ # puts Pry::Indent.new.indent(str)
85
+ #
86
+ # @param [String] input The input string to indent.
87
+ # @return [String] The indented version of +input+.
88
+ #
89
+ def indent(input)
90
+ output = ''
91
+ open_tokens = OPEN_TOKENS.keys
92
+ prefix = indent_level
93
+
94
+ input.lines.each do |line|
95
+ tokens = CodeRay.scan(line, :ruby)
96
+ tokens = tokens.tokens.each_slice(2) if tokens.respond_to?(:tokens) # Coderay 1.0.0
97
+
98
+ before, after = indentation_delta(tokens)
99
+
100
+ before.times{ prefix.sub! SPACES, '' }
101
+ output += prefix + line.strip + "\n"
102
+ prefix += SPACES * after
103
+ end
104
+
105
+ @indent_level = prefix
106
+
107
+ return output.gsub(/\s+$/, '')
108
+ end
109
+
110
+ # Get the change in indentation indicated by the line.
111
+ #
112
+ # By convention, you remove indent from the line containing end tokens,
113
+ # but add indent to the line *after* that which contains the start tokens.
114
+ #
115
+ # This method returns a pair, where the first number is the number of closings
116
+ # on this line (i.e. the number of indents to remove before the line) and the
117
+ # second is the number of openings (i.e. the number of indents to add after
118
+ # this line)
119
+ #
120
+ # @param [Array] tokens A list of tokens to scan.
121
+ # @return [Array[Integer]]
122
+ #
123
+ def indentation_delta(tokens)
124
+
125
+ # We need to keep track of whether we've seen a "for" on this line because
126
+ # if the line ends with "do" then that "do" should be discounted (i.e. we're
127
+ # only opening one level not two) To do this robustly we want to keep track
128
+ # of the indent level at which we saw the for, so we can differentiate
129
+ # between "for x in [1,2,3] do" and "for x in ([1,2,3].map do" properly
130
+ seen_for_at = []
131
+
132
+ # When deciding whether an "if" token is the start of a multiline statement,
133
+ # or just the middle of a single-line if statement, we just look at the
134
+ # preceding token, which is tracked here.
135
+ last_token, last_kind = [nil, nil]
136
+
137
+ # delta keeps track of the total difference from the start of each line after
138
+ # the given token, 0 is just the level at which the current line started for
139
+ # reference.
140
+ remove_before, add_after = [0, 0]
141
+
142
+ # If the list of tokens contains a matching closing token the line should
143
+ # not be indented (and thus we should return true).
144
+ tokens.each do |token, kind|
145
+ is_singleline_if = (SINGLELINE_TOKENS.include?(token)) && end_of_statement?(last_token, last_kind)
146
+ is_optional_do = (token == "do" && seen_for_at.include?(add_after - 1))
147
+
148
+ last_token, last_kind = token, kind unless kind == :space
149
+ next if IGNORE_TOKENS.include?(kind)
150
+
151
+ seen_for_at << add_after if token == "for"
152
+
153
+ if OPEN_TOKENS.keys.include?(token) && !is_optional_do && !is_singleline_if
154
+ @stack << token
155
+ add_after += 1
156
+ elsif token == OPEN_TOKENS[@stack.last]
157
+ @stack.pop
158
+ if add_after == 0
159
+ remove_before += 1
160
+ else
161
+ add_after -= 1
162
+ end
163
+ elsif MIDWAY_TOKENS.include?(token)
164
+ if add_after == 0
165
+ remove_before += 1
166
+ add_after += 1
167
+ end
168
+ end
169
+ end
170
+
171
+ return [remove_before, add_after]
172
+ end
173
+
174
+ # If the code just before an "if" or "while" token on a line looks like the end of a statement,
175
+ # then we want to treat that "if" as a singleline, not multiline statement.
176
+ def end_of_statement?(last_token, last_kind)
177
+ (last_token =~ /^[)\]}\/]$/ || STATEMENT_END_TOKENS.include?(last_kind))
178
+ end
179
+
180
+ # Return a string which, when printed, will rewrite the previous line with
181
+ # the correct indentation. Mostly useful for fixing 'end'.
182
+ #
183
+ # @param [String] full_line The full line of input, including the prompt.
184
+ # @param [Fixnum] overhang (0) The number of chars to erase afterwards (i.e.,
185
+ # the difference in length between the old line and the new one).
186
+ # @return [String]
187
+ def correct_indentation(full_line, overhang=0)
188
+ if Readline.respond_to?(:get_screen_size)
189
+ _, cols = Readline.get_screen_size
190
+ lines = full_line.length / cols + 1
191
+ elsif ENV['COLUMNS'] && ENV['COLUMNS'] != ''
192
+ cols = ENV['COLUMNS'].to_i
193
+ lines = full_line.length / cols + 1
194
+ else
195
+ lines = 1
196
+ end
197
+
198
+ move_up = "\e[#{lines}F"
199
+ whitespace = ' ' * overhang
200
+ move_down = "\e[#{lines}E"
201
+
202
+ "#{move_up}#{full_line}#{whitespace}#{move_down}"
203
+ end
204
+ end
205
+ end
data/lib/pry/method.rb ADDED
@@ -0,0 +1,412 @@
1
+ class Pry
2
+ class Method
3
+ include RbxMethod if Helpers::BaseHelpers.rbx?
4
+
5
+ class << self
6
+ # Given a string representing a method name and optionally a binding to
7
+ # search in, find and return the requested method wrapped in a `Pry::Method`
8
+ # instance.
9
+ #
10
+ # @param [String, nil] name The name of the method to retrieve, or `nil` to
11
+ # delegate to `from_binding` instead.
12
+ # @param [Binding] target The context in which to search for the method.
13
+ # @param [Hash] options
14
+ # @option options [Boolean] :instance Look for an instance method if `name` doesn't
15
+ # contain any context.
16
+ # @option options [Boolean] :methods Look for a bound/singleton method if `name` doesn't
17
+ # contain any context.
18
+ # @return [Pry::Method, nil] A `Pry::Method` instance containing the requested
19
+ # method, or `nil` if no method could be located matching the parameters.
20
+ def from_str(name, target=TOPLEVEL_BINDING, options={})
21
+ if name.nil?
22
+ from_binding(target)
23
+ elsif name.to_s =~ /(.+)\#(\S+)\Z/
24
+ context, meth_name = $1, $2
25
+ from_module(target.eval(context), meth_name)
26
+ elsif name.to_s =~ /(.+)\.(\S+)\Z/
27
+ context, meth_name = $1, $2
28
+ from_obj(target.eval(context), meth_name)
29
+ elsif options[:instance]
30
+ from_module(target.eval("self"), name)
31
+ elsif options[:methods]
32
+ from_obj(target.eval("self"), name)
33
+ else
34
+ from_str(name, target, :instance => true) or
35
+ from_str(name, target, :methods => true)
36
+ end
37
+ end
38
+
39
+ # Given a `Binding`, try to extract the `::Method` it originated from and
40
+ # use it to instantiate a `Pry::Method`. Return `nil` if this isn't
41
+ # possible.
42
+ #
43
+ # @param [Binding] b
44
+ # @return [Pry::Method, nil]
45
+ #
46
+ def from_binding(b)
47
+ meth_name = b.eval('__method__')
48
+ if [:__script__, nil, :__binding__, :__binding_impl__].include?(meth_name)
49
+ nil
50
+ else
51
+ new(b.eval("method(:#{meth_name})"))
52
+ end
53
+ end
54
+
55
+ # Given a `Class` or `Module` and the name of a method, try to
56
+ # instantiate a `Pry::Method` containing the instance method of
57
+ # that name. Return `nil` if no such method exists.
58
+ #
59
+ # @param [Class, Module] klass
60
+ # @param [String] name
61
+ # @return [Pry::Method, nil]
62
+ def from_class(klass, name)
63
+ new(klass.instance_method(name)) rescue nil
64
+ end
65
+ alias from_module from_class
66
+
67
+ # Given an object and the name of a method, try to instantiate
68
+ # a `Pry::Method` containing the method of that name bound to
69
+ # that object. Return `nil` if no such method exists.
70
+ #
71
+ # @param [Object] obj
72
+ # @param [String] name
73
+ # @return [Pry::Method, nil]
74
+ def from_obj(obj, name)
75
+ new(obj.method(name)) rescue nil
76
+ end
77
+
78
+ # Get all of the instance methods of a `Class` or `Module`
79
+ # @param [Class,Module] klass
80
+ # @return [Array[Pry::Method]]
81
+ def all_from_class(klass)
82
+ all_from_common(klass, :instance_method)
83
+ end
84
+
85
+ # Get all of the methods on an `Object`
86
+ # @param [Object] obj
87
+ # @return [Array[Pry::Method]]
88
+ def all_from_obj(obj)
89
+ all_from_common(obj, :method)
90
+ end
91
+
92
+ # Get every `Class` and `Module`, in order, that will be checked when looking
93
+ # for an instance method to call on this object.
94
+ # @param [Object] obj
95
+ # @return [Array[Class, Module]]
96
+ def resolution_order(obj)
97
+ if Class === obj
98
+ singleton_class_resolution_order(obj) + instance_resolution_order(Class)
99
+ else
100
+ klass = singleton_class(obj) rescue obj.class
101
+ instance_resolution_order(klass)
102
+ end
103
+ end
104
+
105
+ # Get every `Class` and `Module`, in order, that will be checked when looking
106
+ # for methods on instances of the given `Class` or `Module`.
107
+ # This does not treat singleton classes of classes specially.
108
+ # @param [Class, Module] klass
109
+ # @return [Array[Class, Module]]
110
+ def instance_resolution_order(klass)
111
+ # include klass in case it is a singleton class,
112
+ ([klass] + klass.ancestors).uniq
113
+ end
114
+
115
+ private
116
+
117
+ # See all_from_class and all_from_obj.
118
+ # If method_type is :instance_method, obj must be a `Class` or a `Module`
119
+ # If method_type is :method, obj can be any `Object`
120
+ #
121
+ # N.B. we pre-cache the visibility here to avoid O(N²) behaviour in "ls".
122
+ def all_from_common(obj, method_type)
123
+ %w(public protected private).map do |visibility|
124
+ safe_send(obj, :"#{visibility}_#{method_type}s").map do |method_name|
125
+ new(safe_send(obj, method_type, method_name), :visibility => visibility.to_sym)
126
+ end
127
+ end.flatten(1)
128
+ end
129
+
130
+ # Acts like send but ignores any methods defined below Object or Class in the
131
+ # inheritance heirarchy.
132
+ # This is required to introspect methods on objects like Net::HTTP::Get that
133
+ # have overridden the `method` method.
134
+ def safe_send(obj, method, *args, &block)
135
+ (Class === obj ? Class : Object).instance_method(method).bind(obj).call(*args, &block)
136
+ end
137
+
138
+ # Get the singleton classes of superclasses that could define methods on
139
+ # the given class object, and any modules they include.
140
+ # If a module is included at multiple points in the ancestry, only
141
+ # the lowest copy will be returned.
142
+ def singleton_class_resolution_order(klass)
143
+ resolution_order = klass.ancestors.map do |anc|
144
+ [singleton_class(anc)] + singleton_class(anc).included_modules if anc.is_a?(Class)
145
+ end.compact.flatten(1)
146
+
147
+ resolution_order.reverse.uniq.reverse - Class.included_modules
148
+ end
149
+
150
+ def singleton_class(obj); class << obj; self; end end
151
+ end
152
+
153
+ # A new instance of `Pry::Method` wrapping the given `::Method`, `UnboundMethod`, or `Proc`.
154
+ #
155
+ # @param [::Method, UnboundMethod, Proc] method
156
+ # @param [Hash] known_info, can be used to pre-cache expensive to compute stuff.
157
+ # @return [Pry::Method]
158
+ def initialize(method, known_info={})
159
+ @method = method
160
+ @visibility = known_info[:visibility]
161
+ end
162
+
163
+ # Get the name of the method as a String, regardless of the underlying Method#name type.
164
+ # @return [String]
165
+ def name
166
+ @method.name.to_s
167
+ end
168
+
169
+ # @return [String, nil] The source code of the method, or `nil` if it's unavailable.
170
+ def source
171
+ @source ||= case source_type
172
+ when :c
173
+ info = pry_doc_info
174
+ if info and info.source
175
+ code = strip_comments_from_c_code(info.source)
176
+ end
177
+ when :rbx
178
+ strip_leading_whitespace(core_code)
179
+ when :ruby
180
+ if pry_method?
181
+ code = Pry.new(:input => StringIO.new(Pry.line_buffer[source_line..-1].join), :prompt => proc {""}, :hooks => {}).r
182
+ else
183
+ code = @method.source
184
+ end
185
+ strip_leading_whitespace(code)
186
+ end
187
+ end
188
+
189
+ # @return [String, nil] The documentation for the method, or `nil` if it's
190
+ # unavailable.
191
+ # @raise [CommandError] Raises when the method was defined in the REPL.
192
+ def doc
193
+ @doc ||= case source_type
194
+ when :c
195
+ info = pry_doc_info
196
+ info.docstring if info
197
+ when :rbx
198
+ strip_leading_hash_and_whitespace_from_ruby_comments(core_doc)
199
+ when :ruby
200
+ if pry_method?
201
+ raise CommandError, "Can't view doc for a REPL-defined method."
202
+ else
203
+ strip_leading_hash_and_whitespace_from_ruby_comments(@method.comment)
204
+ end
205
+ end
206
+ end
207
+
208
+ # @return [Symbol] The source type of the method. The options are
209
+ # `:ruby` for ordinary Ruby methods, `:c` for methods written in
210
+ # C, or `:rbx` for Rubinius core methods written in Ruby.
211
+ def source_type
212
+ if Helpers::BaseHelpers.rbx?
213
+ if core? then :rbx else :ruby end
214
+ else
215
+ if source_location.nil? then :c else :ruby end
216
+ end
217
+ end
218
+
219
+ # @return [String, nil] The name of the file the method is defined in, or
220
+ # `nil` if the filename is unavailable.
221
+ def source_file
222
+ if source_location.nil?
223
+ if !Helpers::BaseHelpers.rbx? and source_type == :c
224
+ info = pry_doc_info
225
+ info.file if info
226
+ end
227
+ else
228
+ source_location.first
229
+ end
230
+ end
231
+
232
+ # @return [Fixnum, nil] The line of code in `source_file` which begins
233
+ # the method's definition, or `nil` if that information is unavailable.
234
+ def source_line
235
+ source_location.nil? ? nil : source_location.last
236
+ end
237
+
238
+ # @return [Symbol] The visibility of the method. May be `:public`,
239
+ # `:protected`, or `:private`.
240
+ def visibility
241
+ @visibility ||= if owner.public_instance_methods.any? { |m| m.to_s == name }
242
+ :public
243
+ elsif owner.protected_instance_methods.any? { |m| m.to_s == name }
244
+ :protected
245
+ elsif owner.private_instance_methods.any? { |m| m.to_s == name }
246
+ :private
247
+ else
248
+ :none
249
+ end
250
+ end
251
+
252
+ # @return [String] A representation of the method's signature, including its
253
+ # name and parameters. Optional and "rest" parameters are marked with `*`
254
+ # and block parameters with `&`. If the parameter names are unavailable,
255
+ # they're given numbered names instead.
256
+ # Paraphrased from `awesome_print` gem.
257
+ def signature
258
+ if respond_to?(:parameters)
259
+ args = parameters.inject([]) do |arr, (type, name)|
260
+ name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
261
+ arr << case type
262
+ when :req then name.to_s
263
+ when :opt, :rest then "*#{name}"
264
+ when :block then "&#{name}"
265
+ else '?'
266
+ end
267
+ end
268
+ else
269
+ args = (1..arity.abs).map { |i| "arg#{i}" }
270
+ args[-1] = "*#{args[-1]}" if arity < 0
271
+ end
272
+
273
+ "#{name}(#{args.join(', ')})"
274
+ end
275
+
276
+ # @return [Pry::Method, nil] The wrapped method that is called when you
277
+ # use "super" in the body of this method.
278
+ def super(times=1)
279
+ if respond_to?(:receiver)
280
+ sup = super_using_ancestors(Pry::Method.resolution_order(receiver), times)
281
+ sup &&= sup.bind(receiver)
282
+ else
283
+ sup = super_using_ancestors(Pry::Method.instance_resolution_order(owner), times)
284
+ end
285
+ Pry::Method.new(sup) if sup
286
+ end
287
+
288
+ # @return [Symbol, nil] The original name the method was defined under,
289
+ # before any aliasing, or `nil` if it can't be determined.
290
+ def original_name
291
+ return nil if source_type != :ruby
292
+
293
+ first_line = source.lines.first
294
+ return nil if first_line.strip !~ /^def /
295
+
296
+ if RUBY_VERSION =~ /^1\.9/ && RUBY_ENGINE == "ruby"
297
+ require 'ripper'
298
+
299
+ # Ripper is ok with an extraneous end, so we don't need to worry about
300
+ # whether it's a one-liner.
301
+ tree = Ripper::SexpBuilder.new(first_line + ";end").parse
302
+
303
+ name = tree.flatten(2).each do |lst|
304
+ break lst[1] if lst[0] == :@ident
305
+ end
306
+
307
+ name.is_a?(String) ? name : nil
308
+ else
309
+ require 'ruby_parser'
310
+
311
+ # RubyParser breaks if there's an extra end, so we'll just rescue
312
+ # and try again.
313
+ tree = begin
314
+ RubyParser.new.parse(first_line + ";end")
315
+ rescue Racc::ParseError
316
+ RubyParser.new.parse(first_line)
317
+ end
318
+
319
+ name = tree.each_cons(2) do |a, b|
320
+ break a if b.is_a?(Array) && b.first == :args
321
+ end
322
+
323
+ name.is_a?(Symbol) ? name.to_s : nil
324
+ end
325
+ end
326
+
327
+ # @return [Boolean] Was the method defined outside a source file?
328
+ def dynamically_defined?
329
+ !!(source_file and source_file =~ /(\(.*\))|<.*>/)
330
+ end
331
+
332
+ # @return [Boolean] Was the method defined within the Pry REPL?
333
+ def pry_method?
334
+ source_file == Pry.eval_path
335
+ end
336
+
337
+ # @return [Boolean] Is the method definitely an alias?
338
+ def alias?
339
+ name != original_name
340
+ end
341
+
342
+ # @return [Boolean]
343
+ def ==(obj)
344
+ if obj.is_a? Pry::Method
345
+ super
346
+ else
347
+ @method == obj
348
+ end
349
+ end
350
+
351
+ # @param [Class] klass
352
+ # @return [Boolean]
353
+ def is_a?(klass)
354
+ klass == Pry::Method or @method.is_a?(klass)
355
+ end
356
+ alias kind_of? is_a?
357
+
358
+ # @param [String, Symbol] method_name
359
+ # @return [Boolean]
360
+ def respond_to?(method_name)
361
+ super or @method.respond_to?(method_name)
362
+ end
363
+
364
+ # Delegate any unknown calls to the wrapped method.
365
+ def method_missing(method_name, *args, &block)
366
+ @method.send(method_name, *args, &block)
367
+ end
368
+
369
+ private
370
+ # @return [YARD::CodeObjects::MethodObject]
371
+ # @raise [CommandError] Raises when the method can't be found or `pry-doc` isn't installed.
372
+ def pry_doc_info
373
+ if Pry.config.has_pry_doc
374
+ Pry::MethodInfo.info_for(@method) or raise CommandError, "Cannot locate this method: #{name}."
375
+ else
376
+ raise CommandError, "Cannot locate this method: #{name}. Try `gem install pry-doc` to get access to Ruby Core documentation."
377
+ end
378
+ end
379
+
380
+ # @param [String] code
381
+ # @return [String]
382
+ def strip_comments_from_c_code(code)
383
+ code.sub(/\A\s*\/\*.*?\*\/\s*/m, '')
384
+ end
385
+
386
+ # @param [String] comment
387
+ # @return [String]
388
+ def strip_leading_hash_and_whitespace_from_ruby_comments(comment)
389
+ comment = comment.dup
390
+ comment.gsub!(/\A\#+?$/, '')
391
+ comment.gsub!(/^\s*#/, '')
392
+ strip_leading_whitespace(comment)
393
+ end
394
+
395
+ # @param [String] text
396
+ # @return [String]
397
+ def strip_leading_whitespace(text)
398
+ Pry::Helpers::CommandHelpers.unindent(text)
399
+ end
400
+
401
+ # @param [Class,Module] the ancestors to investigate
402
+ # @return [Method] the unwrapped super-method
403
+ def super_using_ancestors(ancestors, times=1)
404
+ next_owner = self.owner
405
+ times.times do
406
+ next_owner = ancestors[ancestors.index(next_owner) + 1]
407
+ return nil unless next_owner
408
+ end
409
+ next_owner.instance_method(name) rescue nil
410
+ end
411
+ end
412
+ end