pry 0.12.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +162 -1
- data/LICENSE +1 -1
- data/README.md +331 -269
- data/bin/pry +5 -0
- data/lib/pry.rb +132 -119
- data/lib/pry/basic_object.rb +8 -4
- data/lib/pry/block_command.rb +22 -0
- data/lib/pry/class_command.rb +194 -0
- data/lib/pry/cli.rb +43 -51
- data/lib/pry/code.rb +40 -28
- data/lib/pry/code/code_file.rb +28 -24
- data/lib/pry/code/code_range.rb +4 -2
- data/lib/pry/code/loc.rb +15 -8
- data/lib/pry/code_object.rb +40 -38
- data/lib/pry/color_printer.rb +47 -46
- data/lib/pry/command.rb +166 -369
- data/lib/pry/command_set.rb +76 -73
- data/lib/pry/command_state.rb +31 -0
- data/lib/pry/commands/amend_line.rb +86 -81
- data/lib/pry/commands/bang.rb +18 -14
- data/lib/pry/commands/bang_pry.rb +15 -11
- data/lib/pry/commands/cat.rb +61 -54
- data/lib/pry/commands/cat/abstract_formatter.rb +23 -18
- data/lib/pry/commands/cat/exception_formatter.rb +71 -60
- data/lib/pry/commands/cat/file_formatter.rb +55 -49
- data/lib/pry/commands/cat/input_expression_formatter.rb +35 -30
- data/lib/pry/commands/cd.rb +40 -35
- data/lib/pry/commands/change_inspector.rb +29 -22
- data/lib/pry/commands/change_prompt.rb +44 -39
- data/lib/pry/commands/clear_screen.rb +16 -10
- data/lib/pry/commands/code_collector.rb +148 -133
- data/lib/pry/commands/disable_pry.rb +23 -19
- data/lib/pry/commands/easter_eggs.rb +19 -30
- data/lib/pry/commands/edit.rb +184 -161
- data/lib/pry/commands/edit/exception_patcher.rb +21 -17
- data/lib/pry/commands/edit/file_and_line_locator.rb +34 -23
- data/lib/pry/commands/exit.rb +39 -35
- data/lib/pry/commands/exit_all.rb +24 -20
- data/lib/pry/commands/exit_program.rb +20 -16
- data/lib/pry/commands/find_method.rb +168 -160
- data/lib/pry/commands/fix_indent.rb +16 -12
- data/lib/pry/commands/help.rb +140 -133
- data/lib/pry/commands/hist.rb +151 -150
- data/lib/pry/commands/import_set.rb +20 -16
- data/lib/pry/commands/jump_to.rb +25 -21
- data/lib/pry/commands/list_inspectors.rb +35 -28
- data/lib/pry/commands/ls.rb +124 -102
- data/lib/pry/commands/ls/constants.rb +59 -42
- data/lib/pry/commands/ls/formatter.rb +50 -46
- data/lib/pry/commands/ls/globals.rb +38 -34
- data/lib/pry/commands/ls/grep.rb +17 -13
- data/lib/pry/commands/ls/instance_vars.rb +29 -27
- data/lib/pry/commands/ls/interrogatable.rb +18 -12
- data/lib/pry/commands/ls/jruby_hacks.rb +47 -41
- data/lib/pry/commands/ls/local_names.rb +26 -22
- data/lib/pry/commands/ls/local_vars.rb +38 -28
- data/lib/pry/commands/ls/ls_entity.rb +47 -51
- data/lib/pry/commands/ls/methods.rb +44 -43
- data/lib/pry/commands/ls/methods_helper.rb +46 -42
- data/lib/pry/commands/ls/self_methods.rb +23 -22
- data/lib/pry/commands/nesting.rb +21 -17
- data/lib/pry/commands/play.rb +93 -82
- data/lib/pry/commands/pry_backtrace.rb +22 -17
- data/lib/pry/commands/pry_version.rb +15 -11
- data/lib/pry/commands/raise_up.rb +27 -22
- data/lib/pry/commands/reload_code.rb +60 -48
- data/lib/pry/commands/reset.rb +16 -12
- data/lib/pry/commands/ri.rb +55 -45
- data/lib/pry/commands/save_file.rb +45 -43
- data/lib/pry/commands/shell_command.rb +51 -51
- data/lib/pry/commands/shell_mode.rb +21 -17
- data/lib/pry/commands/show_doc.rb +80 -68
- data/lib/pry/commands/show_info.rb +189 -171
- data/lib/pry/commands/show_input.rb +16 -11
- data/lib/pry/commands/show_source.rb +110 -45
- data/lib/pry/commands/stat.rb +35 -31
- data/lib/pry/commands/switch_to.rb +21 -15
- data/lib/pry/commands/toggle_color.rb +20 -16
- data/lib/pry/commands/watch_expression.rb +89 -86
- data/lib/pry/commands/watch_expression/expression.rb +32 -27
- data/lib/pry/commands/whereami.rb +156 -148
- data/lib/pry/commands/wtf.rb +75 -50
- data/lib/pry/config.rb +307 -25
- data/lib/pry/config/attributable.rb +22 -0
- data/lib/pry/config/lazy_value.rb +29 -0
- data/lib/pry/config/memoized_value.rb +34 -0
- data/lib/pry/config/value.rb +24 -0
- data/lib/pry/control_d_handler.rb +28 -0
- data/lib/pry/core_extensions.rb +9 -7
- data/lib/pry/editor.rb +48 -21
- data/lib/pry/env.rb +18 -0
- data/lib/pry/exception_handler.rb +43 -0
- data/lib/pry/exceptions.rb +13 -16
- data/lib/pry/forwardable.rb +5 -1
- data/lib/pry/helpers.rb +2 -0
- data/lib/pry/helpers/base_helpers.rb +68 -197
- data/lib/pry/helpers/command_helpers.rb +50 -61
- data/lib/pry/helpers/documentation_helpers.rb +20 -13
- data/lib/pry/helpers/options_helpers.rb +14 -7
- data/lib/pry/helpers/platform.rb +7 -5
- data/lib/pry/helpers/table.rb +33 -26
- data/lib/pry/helpers/text.rb +17 -14
- data/lib/pry/history.rb +48 -56
- data/lib/pry/hooks.rb +21 -12
- data/lib/pry/indent.rb +54 -50
- data/lib/pry/input_completer.rb +248 -230
- data/lib/pry/input_lock.rb +8 -9
- data/lib/pry/inspector.rb +36 -24
- data/lib/pry/last_exception.rb +45 -45
- data/lib/pry/method.rb +141 -94
- data/lib/pry/method/disowned.rb +16 -4
- data/lib/pry/method/patcher.rb +12 -3
- data/lib/pry/method/weird_method_locator.rb +68 -44
- data/lib/pry/object_path.rb +33 -25
- data/lib/pry/output.rb +121 -35
- data/lib/pry/pager.rb +186 -180
- data/lib/pry/prompt.rb +123 -54
- data/lib/pry/pry_class.rb +61 -103
- data/lib/pry/pry_instance.rb +217 -215
- data/lib/pry/repl.rb +18 -22
- data/lib/pry/repl_file_loader.rb +27 -21
- data/lib/pry/ring.rb +11 -6
- data/lib/pry/slop.rb +574 -563
- data/lib/pry/slop/commands.rb +164 -169
- data/lib/pry/slop/option.rb +172 -168
- data/lib/pry/syntax_highlighter.rb +26 -0
- data/lib/pry/system_command_handler.rb +17 -0
- data/lib/pry/testable.rb +59 -61
- data/lib/pry/testable/evalable.rb +21 -12
- data/lib/pry/testable/mockable.rb +18 -10
- data/lib/pry/testable/pry_tester.rb +71 -56
- data/lib/pry/testable/utility.rb +29 -21
- data/lib/pry/testable/variables.rb +49 -43
- data/lib/pry/version.rb +3 -1
- data/lib/pry/warning.rb +27 -0
- data/lib/pry/wrapped_module.rb +51 -42
- data/lib/pry/wrapped_module/candidate.rb +21 -14
- metadata +35 -35
- data/lib/pry/commands.rb +0 -6
- data/lib/pry/commands/disabled_commands.rb +0 -2
- data/lib/pry/commands/gem_cd.rb +0 -26
- data/lib/pry/commands/gem_install.rb +0 -32
- data/lib/pry/commands/gem_list.rb +0 -33
- data/lib/pry/commands/gem_open.rb +0 -29
- data/lib/pry/commands/gem_readme.rb +0 -25
- data/lib/pry/commands/gem_search.rb +0 -40
- data/lib/pry/commands/gem_stats.rb +0 -83
- data/lib/pry/commands/gist.rb +0 -102
- data/lib/pry/commands/install_command.rb +0 -54
- data/lib/pry/config/behavior.rb +0 -255
- data/lib/pry/config/convenience.rb +0 -28
- data/lib/pry/config/default.rb +0 -159
- data/lib/pry/config/memoization.rb +0 -48
- data/lib/pry/platform.rb +0 -91
- data/lib/pry/plugins.rb +0 -122
- data/lib/pry/rubygem.rb +0 -84
- data/lib/pry/terminal.rb +0 -91
data/lib/pry/input_lock.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Pry
|
2
4
|
# There is one InputLock per input (such as STDIN) as two REPLs on the same
|
3
5
|
# input makes things delirious. InputLock serializes accesses to the input so
|
4
6
|
# that threads to not conflict with each other. The latest thread to request
|
5
7
|
# ownership of the input wins.
|
6
8
|
class InputLock
|
7
|
-
class Interrupt < Exception; end
|
9
|
+
class Interrupt < Exception; end # rubocop:disable Lint/InheritException
|
8
10
|
|
9
11
|
class << self
|
10
12
|
attr_accessor :input_locks
|
@@ -33,7 +35,7 @@ class Pry
|
|
33
35
|
|
34
36
|
# Adds ourselves to the ownership list. The last one in the list may access
|
35
37
|
# the input through interruptible_region().
|
36
|
-
def __with_ownership
|
38
|
+
def __with_ownership
|
37
39
|
@mutex.synchronize do
|
38
40
|
# Three cases:
|
39
41
|
# 1) There are no owners, in this case we are good to go.
|
@@ -56,8 +58,7 @@ class Pry
|
|
56
58
|
@owners << Thread.current
|
57
59
|
end
|
58
60
|
|
59
|
-
|
60
|
-
|
61
|
+
yield
|
61
62
|
ensure
|
62
63
|
@mutex.synchronize do
|
63
64
|
# We are releasing any desire to have the input ownership by removing
|
@@ -74,7 +75,7 @@ class Pry
|
|
74
75
|
def with_ownership(&block)
|
75
76
|
# If we are in a nested with_ownership() call (nested pry context), we do nothing.
|
76
77
|
nested = @mutex.synchronize { @owners.include?(Thread.current) }
|
77
|
-
nested ?
|
78
|
+
nested ? yield : __with_ownership(&block)
|
78
79
|
end
|
79
80
|
|
80
81
|
def enter_interruptible_region
|
@@ -104,14 +105,13 @@ class Pry
|
|
104
105
|
retry
|
105
106
|
end
|
106
107
|
|
107
|
-
def interruptible_region
|
108
|
+
def interruptible_region
|
108
109
|
enter_interruptible_region
|
109
110
|
|
110
111
|
# XXX Note that there is a chance that we get the interrupt right after
|
111
112
|
# the readline call succeeded, but we'll never know, and we will retry the
|
112
113
|
# call, discarding that piece of input.
|
113
|
-
|
114
|
-
|
114
|
+
yield
|
115
115
|
rescue Interrupt
|
116
116
|
# We were asked to back off. The one requesting the interrupt will be
|
117
117
|
# waiting on the conditional for the interruptible flag to change to false.
|
@@ -122,7 +122,6 @@ class Pry
|
|
122
122
|
leave_interruptible_region
|
123
123
|
sleep 0.01
|
124
124
|
retry
|
125
|
-
|
126
125
|
ensure
|
127
126
|
leave_interruptible_region
|
128
127
|
end
|
data/lib/pry/inspector.rb
CHANGED
@@ -1,27 +1,39 @@
|
|
1
|
-
|
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
|
-
},
|
1
|
+
# frozen_string_literal: true
|
10
2
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
3
|
+
class Pry
|
4
|
+
class Inspector
|
5
|
+
MAP = {
|
6
|
+
"default" => {
|
7
|
+
value: Pry.config.print,
|
8
|
+
description: <<-DESCRIPTION.each_line.map(&:lstrip!)
|
9
|
+
The default Pry inspector. It has paging and color support, and uses
|
10
|
+
pretty_inspect when printing an object.
|
11
|
+
DESCRIPTION
|
12
|
+
},
|
18
13
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
14
|
+
"simple" => {
|
15
|
+
value: proc do |output, value|
|
16
|
+
begin
|
17
|
+
output.puts value.inspect
|
18
|
+
rescue RescuableException
|
19
|
+
output.puts "unknown"
|
20
|
+
end
|
21
|
+
end,
|
22
|
+
description: <<-DESCRIPTION.each_line.map(&:lstrip)
|
23
|
+
A simple inspector that uses #puts and #inspect when printing an
|
24
|
+
object. It has no pager, color, or pretty_inspect support.
|
25
|
+
DESCRIPTION
|
26
|
+
},
|
27
|
+
|
28
|
+
"clipped" => {
|
29
|
+
value: proc do |output, value|
|
30
|
+
output.puts Pry.view_clip(value, id: true)
|
31
|
+
end,
|
32
|
+
description: <<-DESCRIPTION.each_line.map(&:lstrip)
|
33
|
+
The clipped inspector has the same features as the 'simple' inspector
|
34
|
+
but prints large objects as a smaller string.
|
35
|
+
DESCRIPTION
|
36
|
+
}
|
37
|
+
}.freeze
|
38
|
+
end
|
27
39
|
end
|
data/lib/pry/last_exception.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#
|
2
4
|
# {Pry::LastException} is a proxy class who wraps an Exception object for
|
3
5
|
# {Pry#last_exception}. it extends the exception object with methods that
|
@@ -6,56 +8,54 @@
|
|
6
8
|
# the original exception object is not modified and method calls are forwarded
|
7
9
|
# to the wrapped exception object.
|
8
10
|
#
|
9
|
-
class Pry
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
11
|
+
class Pry
|
12
|
+
class LastException < BasicObject
|
13
|
+
attr_accessor :bt_index
|
14
|
+
|
15
|
+
def initialize(exception)
|
16
|
+
@exception = exception
|
17
|
+
@bt_index = 0
|
18
|
+
@file, @line = bt_source_location_for(0)
|
23
19
|
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def respond_to_missing?(name, include_all = false)
|
27
|
-
@e.respond_to?(name, include_all)
|
28
|
-
end
|
29
20
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
21
|
+
def method_missing(name, *args, &block)
|
22
|
+
if @exception.respond_to?(name)
|
23
|
+
@exception.public_send(name, *args, &block)
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
37
28
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
#
|
42
|
-
def line
|
43
|
-
@line
|
44
|
-
end
|
29
|
+
def respond_to_missing?(name, include_all = false)
|
30
|
+
@exception.respond_to?(name, include_all)
|
31
|
+
end
|
45
32
|
|
46
|
-
|
47
|
-
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
|
33
|
+
#
|
34
|
+
# @return [String]
|
35
|
+
# returns the path to a file for the current backtrace. see {#bt_index}.
|
36
|
+
#
|
37
|
+
attr_reader :file
|
38
|
+
|
39
|
+
#
|
40
|
+
# @return [Fixnum]
|
41
|
+
# returns the line for the current backtrace. see {#bt_index}.
|
42
|
+
#
|
43
|
+
attr_reader :line
|
44
|
+
|
45
|
+
# @return [Exception]
|
46
|
+
# returns the wrapped exception
|
47
|
+
#
|
48
|
+
def wrapped_exception
|
49
|
+
@exception
|
50
|
+
end
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
def bt_source_location_for(index)
|
53
|
+
backtrace[index] =~ /(.*):(\d+)/
|
54
|
+
[::Regexp.last_match(1), ::Regexp.last_match(2).to_i]
|
55
|
+
end
|
57
56
|
|
58
|
-
|
59
|
-
|
57
|
+
def inc_bt_index
|
58
|
+
@bt_index = (@bt_index + 1) % backtrace.size
|
59
|
+
end
|
60
60
|
end
|
61
61
|
end
|
data/lib/pry/method.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'method_source'
|
2
4
|
|
3
5
|
class Pry
|
4
6
|
class << self
|
@@ -15,51 +17,52 @@ class Pry
|
|
15
17
|
|
16
18
|
# This class wraps the normal `Method` and `UnboundMethod` classes
|
17
19
|
# to provide extra functionality useful to Pry.
|
18
|
-
class Method
|
19
|
-
require 'pry/method/weird_method_locator'
|
20
|
-
require 'pry/method/disowned'
|
21
|
-
require 'pry/method/patcher'
|
22
|
-
|
20
|
+
class Method # rubocop:disable Metrics/ClassLength
|
23
21
|
extend Helpers::BaseHelpers
|
22
|
+
extend Forwardable
|
23
|
+
|
24
24
|
include Helpers::BaseHelpers
|
25
25
|
include Helpers::DocumentationHelpers
|
26
26
|
include CodeObject::Helpers
|
27
27
|
|
28
28
|
class << self
|
29
29
|
# Given a string representing a method name and optionally a binding to
|
30
|
-
# search in, find and return the requested method wrapped in a
|
31
|
-
# instance.
|
30
|
+
# search in, find and return the requested method wrapped in a
|
31
|
+
# `Pry::Method` instance.
|
32
32
|
#
|
33
33
|
# @param [String] name The name of the method to retrieve.
|
34
34
|
# @param [Binding] target The context in which to search for the method.
|
35
35
|
# @param [Hash] options
|
36
|
-
# @option options [Boolean] :instance Look for an instance method if
|
37
|
-
# contain any context.
|
38
|
-
# @option options [Boolean] :methods Look for a bound/singleton method if
|
39
|
-
#
|
40
|
-
# @return [Pry::Method, nil] A `Pry::Method` instance containing the
|
41
|
-
# method, or `nil` if name is `nil` or no method could be
|
36
|
+
# @option options [Boolean] :instance Look for an instance method if
|
37
|
+
# `name` doesn't contain any context.
|
38
|
+
# @option options [Boolean] :methods Look for a bound/singleton method if
|
39
|
+
# `name` doesn't contain any context.
|
40
|
+
# @return [Pry::Method, nil] A `Pry::Method` instance containing the
|
41
|
+
# requested method, or `nil` if name is `nil` or no method could be
|
42
|
+
# located matching the parameters.
|
42
43
|
def from_str(name, target = TOPLEVEL_BINDING, options = {})
|
43
44
|
if name.nil?
|
44
45
|
nil
|
45
46
|
elsif name.to_s =~ /(.+)\#(\S+)\Z/
|
46
|
-
context
|
47
|
+
context = Regexp.last_match(1)
|
48
|
+
meth_name = Regexp.last_match(2)
|
47
49
|
from_module(target.eval(context), meth_name, target)
|
48
50
|
elsif name.to_s =~ /(.+)(\[\])\Z/
|
49
|
-
context
|
51
|
+
context = Regexp.last_match(1)
|
52
|
+
meth_name = Regexp.last_match(2)
|
50
53
|
from_obj(target.eval(context), meth_name, target)
|
51
54
|
elsif name.to_s =~ /(.+)(\.|::)(\S+)\Z/
|
52
|
-
context
|
55
|
+
context = Regexp.last_match(1)
|
56
|
+
meth_name = Regexp.last_match(3)
|
53
57
|
from_obj(target.eval(context), meth_name, target)
|
54
58
|
elsif options[:instance]
|
55
59
|
from_module(target.eval("self"), name, target)
|
56
60
|
elsif options[:methods]
|
57
61
|
from_obj(target.eval("self"), name, target)
|
58
62
|
else
|
59
|
-
from_str(name, target, instance: true)
|
63
|
+
from_str(name, target, instance: true) ||
|
60
64
|
from_str(name, target, methods: true)
|
61
65
|
end
|
62
|
-
|
63
66
|
rescue Pry::RescuableException
|
64
67
|
nil
|
65
68
|
end
|
@@ -68,26 +71,33 @@ class Pry
|
|
68
71
|
# use it to instantiate a `Pry::Method`. Return `nil` if this isn't
|
69
72
|
# possible.
|
70
73
|
#
|
71
|
-
# @param [Binding]
|
74
|
+
# @param [Binding] binding
|
72
75
|
# @return [Pry::Method, nil]
|
73
76
|
#
|
74
|
-
def from_binding(
|
75
|
-
meth_name =
|
77
|
+
def from_binding(binding)
|
78
|
+
meth_name = binding.eval('::Kernel.__method__')
|
76
79
|
if [:__script__, nil].include?(meth_name)
|
77
80
|
nil
|
78
81
|
else
|
79
|
-
method =
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
82
|
+
method =
|
83
|
+
begin
|
84
|
+
if Object === binding.eval('self') # rubocop:disable Style/CaseEquality
|
85
|
+
new(
|
86
|
+
Kernel.instance_method(:method)
|
87
|
+
.bind(binding.eval("self"))
|
88
|
+
.call(meth_name)
|
89
|
+
)
|
90
|
+
else
|
91
|
+
str = 'class << self; self; end' \
|
92
|
+
'.instance_method(::Kernel.__method__).bind(self)'
|
93
|
+
new(binding.eval(str))
|
94
|
+
end
|
95
|
+
rescue NameError, NoMethodError # rubocop:disable Lint/ShadowedException
|
96
|
+
Disowned.new(binding.eval('self'), meth_name.to_s)
|
97
|
+
end
|
98
|
+
|
99
|
+
if WeirdMethodLocator.weird_method?(method, binding)
|
100
|
+
WeirdMethodLocator.new(method, binding).find_method || method
|
91
101
|
else
|
92
102
|
method
|
93
103
|
end
|
@@ -101,11 +111,16 @@ class Pry
|
|
101
111
|
# @param [Symbol] method_type The type of method: :method or :instance_method
|
102
112
|
# @param [Binding] target The binding where the method is looked up.
|
103
113
|
# @return [Method, UnboundMethod] The 'refined' method object.
|
104
|
-
def lookup_method_via_binding(
|
114
|
+
def lookup_method_via_binding(
|
115
|
+
obj, method_name, method_type, target = TOPLEVEL_BINDING
|
116
|
+
)
|
105
117
|
Pry.current[:obj] = obj
|
106
118
|
Pry.current[:name] = method_name
|
107
119
|
receiver = obj.is_a?(Module) ? "Module" : "Kernel"
|
108
|
-
target.eval(
|
120
|
+
target.eval(
|
121
|
+
"::#{receiver}.instance_method(:#{method_type})" \
|
122
|
+
".bind(Pry.current[:obj]).call(Pry.current[:name])"
|
123
|
+
)
|
109
124
|
ensure
|
110
125
|
Pry.current[:obj] = Pry.current[:name] = nil
|
111
126
|
end
|
@@ -119,7 +134,9 @@ class Pry
|
|
119
134
|
# @param [Binding] target The binding where the method is looked up.
|
120
135
|
# @return [Pry::Method, nil]
|
121
136
|
def from_class(klass, name, target = TOPLEVEL_BINDING)
|
122
|
-
new(lookup_method_via_binding(klass, name, :instance_method, target))
|
137
|
+
new(lookup_method_via_binding(klass, name, :instance_method, target))
|
138
|
+
rescue StandardError
|
139
|
+
nil
|
123
140
|
end
|
124
141
|
alias from_module from_class
|
125
142
|
|
@@ -132,7 +149,9 @@ class Pry
|
|
132
149
|
# @param [Binding] target The binding where the method is looked up.
|
133
150
|
# @return [Pry::Method, nil]
|
134
151
|
def from_obj(obj, name, target = TOPLEVEL_BINDING)
|
135
|
-
new(lookup_method_via_binding(obj, name, :method, target))
|
152
|
+
new(lookup_method_via_binding(obj, name, :method, target))
|
153
|
+
rescue StandardError
|
154
|
+
nil
|
136
155
|
end
|
137
156
|
|
138
157
|
# Get all of the instance methods of a `Class` or `Module`
|
@@ -140,9 +159,14 @@ class Pry
|
|
140
159
|
# @param [Boolean] include_super Whether to include methods from ancestors.
|
141
160
|
# @return [Array[Pry::Method]]
|
142
161
|
def all_from_class(klass, include_super = true)
|
143
|
-
%w
|
144
|
-
safe_send(
|
145
|
-
|
162
|
+
%w[public protected private].flat_map do |visibility|
|
163
|
+
safe_send(
|
164
|
+
klass, :"#{visibility}_instance_methods", include_super
|
165
|
+
).map do |method_name|
|
166
|
+
new(
|
167
|
+
safe_send(klass, :instance_method, method_name),
|
168
|
+
visibility: visibility.to_sym
|
169
|
+
)
|
146
170
|
end
|
147
171
|
end
|
148
172
|
end
|
@@ -161,24 +185,19 @@ class Pry
|
|
161
185
|
all_from_class(singleton_class_of(obj), include_super)
|
162
186
|
end
|
163
187
|
|
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)
|
171
|
-
end
|
172
|
-
|
173
188
|
# Get every `Class` and `Module`, in order, that will be checked when looking
|
174
189
|
# for an instance method to call on this object.
|
175
190
|
# @param [Object] obj
|
176
191
|
# @return [Array[Class, Module]]
|
177
192
|
def resolution_order(obj)
|
178
|
-
if Class === obj
|
193
|
+
if Class === obj # rubocop:disable Style/CaseEquality
|
179
194
|
singleton_class_resolution_order(obj) + instance_resolution_order(Class)
|
180
195
|
else
|
181
|
-
klass =
|
196
|
+
klass = begin
|
197
|
+
singleton_class_of(obj)
|
198
|
+
rescue StandardError
|
199
|
+
obj.class
|
200
|
+
end
|
182
201
|
instance_resolution_order(klass)
|
183
202
|
end
|
184
203
|
end
|
@@ -199,11 +218,17 @@ class Pry
|
|
199
218
|
end
|
200
219
|
|
201
220
|
def singleton_method_definition?(name, definition_line)
|
202
|
-
|
221
|
+
regexp =
|
222
|
+
/^define_singleton_method\(?\s*[:\"\']#{Regexp.escape(name)}|
|
223
|
+
^def\s*self\.#{Regexp.escape(name)}/x
|
224
|
+
regexp =~ definition_line.strip
|
203
225
|
end
|
204
226
|
|
205
227
|
def instance_method_definition?(name, definition_line)
|
206
|
-
|
228
|
+
regexp =
|
229
|
+
/^define_method\(?\s*[:\"\']#{Regexp.escape(name)}|
|
230
|
+
^def\s*#{Regexp.escape(name)}/x
|
231
|
+
regexp =~ definition_line.strip
|
207
232
|
end
|
208
233
|
|
209
234
|
# Get the singleton classes of superclasses that could define methods on
|
@@ -220,15 +245,17 @@ class Pry
|
|
220
245
|
end
|
221
246
|
|
222
247
|
def singleton_class_of(obj)
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
obj.class
|
227
|
-
end
|
248
|
+
class << obj; self; end
|
249
|
+
rescue TypeError # can't define singleton. Fixnum, Symbol, Float, ...
|
250
|
+
obj.class
|
228
251
|
end
|
229
252
|
end
|
230
253
|
|
231
|
-
#
|
254
|
+
# Workaround for https://github.com/pry/pry/pull/2086
|
255
|
+
def_delegators :@method, :owner, :parameters, :receiver
|
256
|
+
|
257
|
+
# A new instance of `Pry::Method` wrapping the given `::Method`,
|
258
|
+
# `UnboundMethod`, or `Proc`.
|
232
259
|
#
|
233
260
|
# @param [::Method, UnboundMethod, Proc] method
|
234
261
|
# @param [Hash] known_info Can be used to pre-cache expensive to compute stuff.
|
@@ -238,7 +265,9 @@ class Pry
|
|
238
265
|
@visibility = known_info[:visibility]
|
239
266
|
end
|
240
267
|
|
241
|
-
# Get the name of the method as a String, regardless of the underlying
|
268
|
+
# Get the name of the method as a String, regardless of the underlying
|
269
|
+
# Method#name type.
|
270
|
+
#
|
242
271
|
# @return [String]
|
243
272
|
def name
|
244
273
|
@method.name.to_s
|
@@ -342,15 +371,16 @@ class Pry
|
|
342
371
|
# @return [Symbol] The visibility of the method. May be `:public`,
|
343
372
|
# `:protected`, or `:private`.
|
344
373
|
def visibility
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
374
|
+
@visibility ||=
|
375
|
+
if owner.public_instance_methods.any? { |m| m.to_s == name }
|
376
|
+
:public
|
377
|
+
elsif owner.protected_instance_methods.any? { |m| m.to_s == name }
|
378
|
+
:protected
|
379
|
+
elsif owner.private_instance_methods.any? { |m| m.to_s == name }
|
380
|
+
:private
|
381
|
+
else
|
382
|
+
:none
|
383
|
+
end
|
354
384
|
end
|
355
385
|
|
356
386
|
# @return [String] A representation of the method's signature, including its
|
@@ -385,7 +415,7 @@ class Pry
|
|
385
415
|
# @return [Pry::Method, nil] The wrapped method that is called when you
|
386
416
|
# use "super" in the body of this method.
|
387
417
|
def super(times = 1)
|
388
|
-
if
|
418
|
+
if @method.is_a?(UnboundMethod)
|
389
419
|
sup = super_using_ancestors(Pry::Method.instance_resolution_order(owner), times)
|
390
420
|
else
|
391
421
|
sup = super_using_ancestors(Pry::Method.resolution_order(receiver), times)
|
@@ -404,7 +434,7 @@ class Pry
|
|
404
434
|
|
405
435
|
# @return [Boolean] Was the method defined outside a source file?
|
406
436
|
def dynamically_defined?
|
407
|
-
!!(source_file
|
437
|
+
!!(source_file && source_file =~ /(\(.*\))|<.*>/)
|
408
438
|
end
|
409
439
|
|
410
440
|
# @return [Boolean] Whether the method is unbound.
|
@@ -450,30 +480,36 @@ class Pry
|
|
450
480
|
end
|
451
481
|
|
452
482
|
# @return [Boolean]
|
453
|
-
def ==(
|
454
|
-
if
|
455
|
-
|
456
|
-
|
457
|
-
@method == obj
|
458
|
-
end
|
483
|
+
def ==(other)
|
484
|
+
return other == @method if other.is_a?(Pry::Method)
|
485
|
+
|
486
|
+
@method == other
|
459
487
|
end
|
460
488
|
|
461
489
|
# @param [Class] klass
|
462
490
|
# @return [Boolean]
|
463
491
|
def is_a?(klass)
|
464
|
-
klass == Pry::Method
|
492
|
+
(klass == Pry::Method) || @method.is_a?(klass)
|
465
493
|
end
|
466
494
|
alias kind_of? is_a?
|
467
495
|
|
468
496
|
# @param [String, Symbol] method_name
|
469
497
|
# @return [Boolean]
|
470
498
|
def respond_to?(method_name, include_all = false)
|
471
|
-
super
|
499
|
+
super || @method.respond_to?(method_name, include_all)
|
472
500
|
end
|
473
501
|
|
474
502
|
# Delegate any unknown calls to the wrapped method.
|
475
503
|
def method_missing(method_name, *args, &block)
|
476
|
-
@method.
|
504
|
+
if @method.respond_to?(method_name)
|
505
|
+
@method.__send__(method_name, *args, &block)
|
506
|
+
else
|
507
|
+
super
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
def respond_to_missing?(method_name, include_private = false)
|
512
|
+
@method.respond_to?(method_name) || super
|
477
513
|
end
|
478
514
|
|
479
515
|
def comment
|
@@ -485,12 +521,17 @@ class Pry
|
|
485
521
|
# @return [YARD::CodeObjects::MethodObject]
|
486
522
|
# @raise [CommandError] when the method can't be found or `pry-doc` isn't installed.
|
487
523
|
def pry_doc_info
|
488
|
-
if
|
489
|
-
Pry::MethodInfo.info_for(@method)
|
524
|
+
if defined?(PryDoc)
|
525
|
+
Pry::MethodInfo.info_for(@method) ||
|
526
|
+
raise(
|
527
|
+
CommandError,
|
528
|
+
"Cannot locate this method: #{name}. (source_location returns nil)"
|
529
|
+
)
|
490
530
|
else
|
491
531
|
fail_msg = "Cannot locate this method: #{name}."
|
492
532
|
if Helpers::Platform.mri?
|
493
|
-
fail_msg += " Invoke the 'gem-install pry-doc' Pry command to get
|
533
|
+
fail_msg += " Invoke the 'gem-install pry-doc' Pry command to get " \
|
534
|
+
"access to Ruby Core documentation.\n"
|
494
535
|
end
|
495
536
|
raise CommandError, fail_msg
|
496
537
|
end
|
@@ -499,16 +540,22 @@ class Pry
|
|
499
540
|
# @param [Class, Module] ancestors The ancestors to investigate
|
500
541
|
# @return [Method] The unwrapped super-method
|
501
542
|
def super_using_ancestors(ancestors, times = 1)
|
502
|
-
next_owner =
|
543
|
+
next_owner = owner
|
503
544
|
times.times do
|
504
545
|
i = ancestors.index(next_owner) + 1
|
505
|
-
while ancestors[i] &&
|
546
|
+
while ancestors[i] &&
|
547
|
+
!(ancestors[i].method_defined?(name) ||
|
548
|
+
ancestors[i].private_method_defined?(name))
|
506
549
|
i += 1
|
507
550
|
end
|
508
|
-
next_owner = ancestors[i]
|
551
|
+
(next_owner = ancestors[i]) || (return nil)
|
509
552
|
end
|
510
553
|
|
511
|
-
|
554
|
+
begin
|
555
|
+
safe_send(next_owner, :instance_method, name)
|
556
|
+
rescue StandardError
|
557
|
+
nil
|
558
|
+
end
|
512
559
|
end
|
513
560
|
|
514
561
|
# @param [String] first_ln The first line of a method definition.
|
@@ -516,7 +563,7 @@ class Pry
|
|
516
563
|
def method_name_from_first_line(first_ln)
|
517
564
|
return nil if first_ln.strip !~ /^def /
|
518
565
|
|
519
|
-
tokens =
|
566
|
+
tokens = SyntaxHighlighter.tokenize(first_ln)
|
520
567
|
tokens = tokens.tokens.each_slice(2) if tokens.respond_to?(:tokens)
|
521
568
|
tokens.each_cons(2) do |t1, t2|
|
522
569
|
if t2.last == :method || t2.last == :ident && t1 == [".", :operator]
|
@@ -529,9 +576,7 @@ class Pry
|
|
529
576
|
|
530
577
|
def c_source
|
531
578
|
info = pry_doc_info
|
532
|
-
if info
|
533
|
-
strip_comments_from_c_code(info.source)
|
534
|
-
end
|
579
|
+
strip_comments_from_c_code(info.source) if info && info.source
|
535
580
|
end
|
536
581
|
|
537
582
|
def ruby_source
|
@@ -539,12 +584,14 @@ class Pry
|
|
539
584
|
# hacked version of `source_location` for our input buffer for methods
|
540
585
|
# defined in `(pry)`.
|
541
586
|
file, line = *source_location
|
542
|
-
|
587
|
+
unless file
|
588
|
+
raise SourceNotFoundError, "Could not locate source for #{name_with_owner}!"
|
589
|
+
end
|
543
590
|
|
544
591
|
begin
|
545
592
|
code = Pry::Code.from_file(file).expression_at(line)
|
546
593
|
rescue SyntaxError => e
|
547
|
-
raise MethodSource::SourceNotFoundError
|
594
|
+
raise MethodSource::SourceNotFoundError, e.message
|
548
595
|
end
|
549
596
|
strip_leading_whitespace(code)
|
550
597
|
end
|