pry 0.9.11.4-java → 0.9.12-java
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.
- data/.travis.yml +2 -0
- data/CHANGELOG +19 -0
- data/Rakefile +4 -0
- data/lib/pry.rb +1 -1
- data/lib/pry/cli.rb +14 -8
- data/lib/pry/code.rb +3 -3
- data/lib/pry/command.rb +20 -5
- data/lib/pry/command_set.rb +3 -3
- data/lib/pry/commands.rb +1 -1
- data/lib/pry/commands/disabled_commands.rb +2 -0
- data/lib/pry/commands/ls.rb +1 -2
- data/lib/pry/commands/reload_code.rb +8 -1
- data/lib/pry/commands/show_info.rb +66 -5
- data/lib/pry/commands/show_source.rb +2 -1
- data/lib/pry/commands/whereami.rb +87 -19
- data/lib/pry/completion.rb +13 -4
- data/lib/pry/helpers/base_helpers.rb +5 -2
- data/lib/pry/helpers/command_helpers.rb +3 -1
- data/lib/pry/helpers/documentation_helpers.rb +18 -7
- data/lib/pry/helpers/table.rb +4 -4
- data/lib/pry/indent.rb +2 -7
- data/lib/pry/method.rb +89 -129
- data/lib/pry/method/disowned.rb +53 -0
- data/lib/pry/method/weird_method_locator.rb +186 -0
- data/lib/pry/module_candidate.rb +13 -8
- data/lib/pry/pager.rb +12 -11
- data/lib/pry/plugins.rb +2 -0
- data/lib/pry/pry_class.rb +19 -3
- data/lib/pry/pry_instance.rb +3 -0
- data/lib/pry/terminal.rb +78 -0
- data/lib/pry/version.rb +1 -1
- data/lib/pry/wrapped_module.rb +63 -1
- data/spec/Procfile +3 -0
- data/spec/command_helpers_spec.rb +21 -1
- data/spec/commands/ls_spec.rb +4 -0
- data/spec/commands/show_doc_spec.rb +255 -123
- data/spec/commands/show_source_spec.rb +421 -236
- data/spec/commands/whereami_spec.rb +60 -11
- data/spec/completion_spec.rb +6 -0
- data/spec/documentation_helper_spec.rb +73 -0
- data/spec/fixtures/whereami_helper.rb +6 -0
- data/spec/helpers/table_spec.rb +19 -0
- data/spec/method_spec.rb +24 -7
- metadata +12 -5
- data/.gemtest +0 -0
- data/lib/pry/commands/deprecated_commands.rb +0 -2
- data/lib/pry/terminal_info.rb +0 -48
@@ -0,0 +1,53 @@
|
|
1
|
+
class Pry
|
2
|
+
class Method
|
3
|
+
# A Disowned Method is one that's been removed from the class on which it was defined.
|
4
|
+
#
|
5
|
+
# e.g.
|
6
|
+
# class C
|
7
|
+
# def foo
|
8
|
+
# C.send(:undefine_method, :foo)
|
9
|
+
# Pry::Method.from_binding(binding)
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# In this case we assume that the "owner" is the singleton class of the receiver.
|
14
|
+
#
|
15
|
+
# This occurs mainly in Sinatra applications.
|
16
|
+
class Disowned < Method
|
17
|
+
attr_reader :receiver, :name
|
18
|
+
|
19
|
+
# Create a new Disowned method.
|
20
|
+
#
|
21
|
+
# @param [Object] receiver
|
22
|
+
# @param [String] method_name
|
23
|
+
def initialize(receiver, method_name, binding=nil)
|
24
|
+
@receiver, @name = receiver, method_name
|
25
|
+
end
|
26
|
+
|
27
|
+
# Is the method undefined? (aka `Disowned`)
|
28
|
+
# @return [Boolean] true
|
29
|
+
def undefined?
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
# Can we get the source for this method?
|
34
|
+
# @return [Boolean] false
|
35
|
+
def source?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
# Get the hypothesized owner of the method.
|
40
|
+
#
|
41
|
+
# @return [Object]
|
42
|
+
def owner
|
43
|
+
class << receiver; self; end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Raise a more useful error message instead of trying to forward to nil.
|
47
|
+
def method_missing(meth_name, *args, &block)
|
48
|
+
raise "Cannot call '#{meth_name}' on an undef'd method." if method(:name).respond_to?(meth_name)
|
49
|
+
Object.instance_method(:method_missing).bind(self).call(meth_name, *args, &block)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
class Pry
|
2
|
+
class Method
|
3
|
+
|
4
|
+
# This class is responsible for locating the *real* `Pry::Method`
|
5
|
+
# object captured by a binding.
|
6
|
+
#
|
7
|
+
# Given a `Binding` from inside a method and a 'seed' Pry::Method object,
|
8
|
+
# there are primarily two situations where the seed method doesn't match
|
9
|
+
# the Binding:
|
10
|
+
# 1. The Pry::Method is from a subclass 2. The Pry::Method represents a method of the same name
|
11
|
+
# while the original was renamed to something else. For 1. we
|
12
|
+
# search vertically up the inheritance chain,
|
13
|
+
# and for 2. we search laterally along the object's method table.
|
14
|
+
#
|
15
|
+
# When we locate the method that matches the Binding we wrap it in
|
16
|
+
# Pry::Method and return it, or return nil if we fail.
|
17
|
+
class WeirdMethodLocator
|
18
|
+
class << self
|
19
|
+
|
20
|
+
# Whether the given method object matches the associated binding.
|
21
|
+
# If the method object does not match the binding, then it's
|
22
|
+
# most likely not the method captured by the binding, and we
|
23
|
+
# must commence a search.
|
24
|
+
#
|
25
|
+
# @param [Pry::Method] method
|
26
|
+
# @param [Binding] b
|
27
|
+
# @return [Boolean]
|
28
|
+
def normal_method?(method, b)
|
29
|
+
method && (method.source_file && method.source_range rescue false) &&
|
30
|
+
File.expand_path(method.source_file) == File.expand_path(b.eval('__FILE__')) &&
|
31
|
+
method.source_range.include?(b.eval('__LINE__'))
|
32
|
+
end
|
33
|
+
|
34
|
+
def weird_method?(method, b)
|
35
|
+
!normal_method?(method, b)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_accessor :method
|
40
|
+
attr_accessor :target
|
41
|
+
|
42
|
+
# @param [Pry::Method] method The seed method.
|
43
|
+
# @param [Binding] target The Binding that captures the method
|
44
|
+
# we want to locate.
|
45
|
+
def initialize(method, target)
|
46
|
+
@method, @target = method, target
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Pry::Method, nil] The Pry::Method that matches the
|
50
|
+
# given binding.
|
51
|
+
def get_method
|
52
|
+
find_method_in_superclass || find_renamed_method
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Boolean] Whether the Pry::Method is unrecoverable
|
56
|
+
# This usually happens when the method captured by the Binding
|
57
|
+
# has been subsequently deleted.
|
58
|
+
def lost_method?
|
59
|
+
!!(get_method.nil? && renamed_method_source_location)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def normal_method?(method)
|
65
|
+
self.class.normal_method?(method, target)
|
66
|
+
end
|
67
|
+
|
68
|
+
def target_self
|
69
|
+
target.eval('self')
|
70
|
+
end
|
71
|
+
|
72
|
+
def target_file
|
73
|
+
pry_file? ? target.eval('__FILE__') : File.expand_path(target.eval('__FILE__'))
|
74
|
+
end
|
75
|
+
|
76
|
+
def target_line
|
77
|
+
target.eval('__LINE__')
|
78
|
+
end
|
79
|
+
|
80
|
+
def pry_file?
|
81
|
+
Pry.eval_path == target.eval('__FILE__')
|
82
|
+
end
|
83
|
+
|
84
|
+
# it's possible in some cases that the method we find by this approach is a sub-method of
|
85
|
+
# the one we're currently in, consider:
|
86
|
+
#
|
87
|
+
# class A; def b; binding.pry; end; end
|
88
|
+
# class B < A; def b; super; end; end
|
89
|
+
#
|
90
|
+
# Given that we can normally find the source_range of methods, and that we know which
|
91
|
+
# __FILE__ and __LINE__ the binding is at, we can hope to disambiguate these cases.
|
92
|
+
#
|
93
|
+
# This obviously won't work if the source is unavaiable for some reason, or if both
|
94
|
+
# methods have the same __FILE__ and __LINE__, or if we're in rbx where b.eval('__LINE__')
|
95
|
+
# is broken.
|
96
|
+
#
|
97
|
+
# @return [Pry::Method, nil] The Pry::Method representing the
|
98
|
+
# superclass method.
|
99
|
+
def find_method_in_superclass
|
100
|
+
guess = method
|
101
|
+
|
102
|
+
while guess
|
103
|
+
# needs rescue if this is a Disowned method or a C method or something...
|
104
|
+
# TODO: Fix up the exception handling so we don't need a bare rescue
|
105
|
+
if normal_method?(guess)
|
106
|
+
return guess
|
107
|
+
else
|
108
|
+
guess = guess.super
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Uhoh... none of the methods in the chain had the right __FILE__ and __LINE__
|
113
|
+
# This may be caused by rbx https://github.com/rubinius/rubinius/issues/953,
|
114
|
+
# or other unknown circumstances (TODO: we should warn the user when this happens)
|
115
|
+
nil
|
116
|
+
end
|
117
|
+
|
118
|
+
# This is the case where the name of a method has changed
|
119
|
+
# (via alias_method) so we locate the Method object for the
|
120
|
+
# renamed method.
|
121
|
+
#
|
122
|
+
# @return [Pry::Method, nil] The Pry::Method representing the
|
123
|
+
# renamed method
|
124
|
+
def find_renamed_method
|
125
|
+
return if !valid_file?(target_file)
|
126
|
+
alias_name = all_methods_for(target_self).find do |v|
|
127
|
+
expanded_source_location(target_self.method(v).source_location) == renamed_method_source_location
|
128
|
+
end
|
129
|
+
|
130
|
+
alias_name && Pry::Method(target_self.method(alias_name))
|
131
|
+
end
|
132
|
+
|
133
|
+
def expanded_source_location(sl)
|
134
|
+
return if !sl
|
135
|
+
|
136
|
+
if pry_file?
|
137
|
+
sl
|
138
|
+
else
|
139
|
+
[File.expand_path(sl.first), sl.last]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Use static analysis to locate the start of the method definition.
|
144
|
+
# We have the `__FILE__` and `__LINE__` from the binding and the
|
145
|
+
# original name of the method so we search up until we find a
|
146
|
+
# def/define_method, etc defining a method of the appropriate name.
|
147
|
+
#
|
148
|
+
# @return [Array<String, Fixnum>] The `source_location` of the
|
149
|
+
# renamed method
|
150
|
+
def renamed_method_source_location
|
151
|
+
return @original_method_source_location if defined?(@original_method_source_location)
|
152
|
+
|
153
|
+
source_index = lines_for_file(target_file)[0..(target_line - 1)].rindex do |v|
|
154
|
+
Pry::Method.method_definition?(method.name, v)
|
155
|
+
end
|
156
|
+
|
157
|
+
@original_method_source_location = source_index &&
|
158
|
+
[target_file, index_to_line_number(source_index)]
|
159
|
+
end
|
160
|
+
|
161
|
+
def index_to_line_number(index)
|
162
|
+
# Pry.line_buffer is 0-indexed
|
163
|
+
pry_file? ? index : index + 1
|
164
|
+
end
|
165
|
+
|
166
|
+
def valid_file?(file)
|
167
|
+
File.exists?(file) || Pry.eval_path == file
|
168
|
+
end
|
169
|
+
|
170
|
+
def lines_for_file(file)
|
171
|
+
@lines_for_file ||= {}
|
172
|
+
@lines_for_file[file] ||= if Pry.eval_path == file
|
173
|
+
Pry.line_buffer
|
174
|
+
else
|
175
|
+
File.readlines(file)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def all_methods_for(obj)
|
180
|
+
obj.public_methods(false) +
|
181
|
+
obj.private_methods(false) +
|
182
|
+
obj.protected_methods(false)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
data/lib/pry/module_candidate.rb
CHANGED
@@ -20,12 +20,17 @@ class Pry
|
|
20
20
|
attr_reader :line
|
21
21
|
alias_method :source_line, :line
|
22
22
|
|
23
|
-
# Methods to delegate to associated `Pry::WrappedModule
|
24
|
-
|
25
|
-
|
23
|
+
# Methods to delegate to associated `Pry::WrappedModule
|
24
|
+
# instance`.
|
25
|
+
private_delegates = [:lines_for_file, :method_candidates,
|
26
|
+
:yard_docs?]
|
26
27
|
|
27
|
-
|
28
|
-
|
28
|
+
public_delegates = [:wrapped, :module?, :class?, :name, :nonblank_name,
|
29
|
+
:number_of_candidates]
|
30
|
+
|
31
|
+
def_delegators :@wrapper, *(private_delegates + public_delegates)
|
32
|
+
private *private_delegates
|
33
|
+
public *public_delegates
|
29
34
|
|
30
35
|
# @raise [Pry::CommandError] If `rank` is out of bounds.
|
31
36
|
# @param [Pry::WrappedModule] wrapper The associated
|
@@ -52,8 +57,8 @@ class Pry
|
|
52
57
|
# @return [String] The source for the candidate, i.e the
|
53
58
|
# complete module/class definition.
|
54
59
|
def source
|
60
|
+
return nil if file.nil?
|
55
61
|
return @source if @source
|
56
|
-
raise CommandError, "Could not locate source for #{wrapped}!" if file.nil?
|
57
62
|
|
58
63
|
@source = strip_leading_whitespace(Pry::Code.from_file(file).expression_at(line, number_of_lines_in_first_chunk))
|
59
64
|
end
|
@@ -61,10 +66,10 @@ class Pry
|
|
61
66
|
# @raise [Pry::CommandError] If documentation cannot be found.
|
62
67
|
# @return [String] The documentation for the candidate.
|
63
68
|
def doc
|
69
|
+
return nil if file.nil?
|
64
70
|
return @doc if @doc
|
65
|
-
raise CommandError, "Could not locate doc for #{wrapped}!" if file.nil?
|
66
71
|
|
67
|
-
@doc =
|
72
|
+
@doc = get_comment_content(Pry::Code.from_file(file).comment_describing(line))
|
68
73
|
end
|
69
74
|
|
70
75
|
# @return [Array, nil] A `[String, Fixnum]` pair representing the
|
data/lib/pry/pager.rb
CHANGED
@@ -12,8 +12,11 @@ class Pry::Pager
|
|
12
12
|
case pager
|
13
13
|
when nil
|
14
14
|
no_pager = !SystemPager.available?
|
15
|
-
|
16
|
-
|
15
|
+
if no_pager || Pry::Helpers::BaseHelpers.jruby?
|
16
|
+
SimplePager.new(text).page
|
17
|
+
else
|
18
|
+
SystemPager.new(text).page
|
19
|
+
end
|
17
20
|
when :simple
|
18
21
|
SimplePager.new(text).page
|
19
22
|
when :system
|
@@ -24,12 +27,7 @@ class Pry::Pager
|
|
24
27
|
end
|
25
28
|
|
26
29
|
def self.page_size
|
27
|
-
@page_size ||=
|
28
|
-
require 'io/console'
|
29
|
-
$stdout.winsize.first
|
30
|
-
rescue LoadError
|
31
|
-
27
|
32
|
-
end
|
30
|
+
@page_size ||= Pry::Terminal.height!
|
33
31
|
end
|
34
32
|
|
35
33
|
def initialize(text)
|
@@ -38,11 +36,14 @@ class Pry::Pager
|
|
38
36
|
|
39
37
|
class SimplePager < Pry::Pager
|
40
38
|
def page
|
39
|
+
# The pager size minus the number of lines used by the simple pager info bar.
|
40
|
+
page_size = Pry::Pager.page_size - 3
|
41
41
|
text_array = @text.lines.to_a
|
42
|
-
|
42
|
+
|
43
|
+
text_array.each_slice(page_size) do |chunk|
|
43
44
|
puts chunk.join
|
44
|
-
break if chunk.size <
|
45
|
-
if text_array.size >
|
45
|
+
break if chunk.size < page_size
|
46
|
+
if text_array.size > page_size
|
46
47
|
puts "\n<page break> --- Press enter to continue ( q<enter> to break ) --- <page break>"
|
47
48
|
break if $stdin.gets.chomp == "q"
|
48
49
|
end
|
data/lib/pry/plugins.rb
CHANGED
data/lib/pry/pry_class.rb
CHANGED
@@ -262,10 +262,26 @@ class Pry
|
|
262
262
|
end
|
263
263
|
|
264
264
|
def self.auto_resize!
|
265
|
+
ver = Readline::VERSION
|
266
|
+
if ver[/edit/i]
|
267
|
+
warn <<-EOT
|
268
|
+
Readline version #{ver} detected - will not auto_resize! correctly.
|
269
|
+
For the fix, use GNU Readline instead:
|
270
|
+
https://github.com/guard/guard/wiki/Add-proper-Readline-support-to-Ruby-on-Mac-OS-X
|
271
|
+
EOT
|
272
|
+
return
|
273
|
+
end
|
265
274
|
trap :WINCH do
|
266
|
-
|
267
|
-
|
268
|
-
|
275
|
+
begin
|
276
|
+
Readline.set_screen_size *Terminal.size!
|
277
|
+
rescue => e
|
278
|
+
warn "\nPry.auto_resize!'s Readline.set_screen_size failed: #{e}"
|
279
|
+
end
|
280
|
+
begin
|
281
|
+
Readline.refresh_line
|
282
|
+
rescue => e
|
283
|
+
warn "\nPry.auto_resize!'s Readline.refresh_line failed: #{e}"
|
284
|
+
end
|
269
285
|
end
|
270
286
|
end
|
271
287
|
|
data/lib/pry/pry_instance.rb
CHANGED
@@ -618,6 +618,9 @@ class Pry
|
|
618
618
|
end
|
619
619
|
|
620
620
|
if input == Readline
|
621
|
+
if !$stdout.tty? && $stdin.tty? && !Pry::Helpers::BaseHelpers.windows?
|
622
|
+
Readline.output = File.open('/dev/tty', 'w')
|
623
|
+
end
|
621
624
|
input.readline(current_prompt, false) # false since we'll add it manually
|
622
625
|
elsif defined? Coolline and input.is_a? Coolline
|
623
626
|
input.readline(current_prompt)
|
data/lib/pry/terminal.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
class Pry::Terminal
|
2
|
+
class << self
|
3
|
+
# Return a pair of [rows, columns] which gives the size of the window.
|
4
|
+
#
|
5
|
+
# If the window size cannot be determined, return nil.
|
6
|
+
def screen_size
|
7
|
+
rows, cols = actual_screen_size
|
8
|
+
if rows && cols
|
9
|
+
[rows.to_i, cols.to_i]
|
10
|
+
else
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Return a screen size or a default if that fails.
|
16
|
+
def size! default = [27, 80]
|
17
|
+
screen_size || default
|
18
|
+
end
|
19
|
+
|
20
|
+
# Return a screen width or the default if that fails.
|
21
|
+
def width!
|
22
|
+
size![1]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return a screen height or the default if that fails.
|
26
|
+
def height!
|
27
|
+
size![0]
|
28
|
+
end
|
29
|
+
|
30
|
+
def actual_screen_size
|
31
|
+
# The best way, if possible (requires non-jruby ≥1.9 or io-console gem)
|
32
|
+
screen_size_according_to_io_console or
|
33
|
+
# Fall back to the old standby, though it might be stale:
|
34
|
+
screen_size_according_to_env or
|
35
|
+
# Fall further back, though this one is also out of date without something
|
36
|
+
# calling Readline.set_screen_size
|
37
|
+
screen_size_according_to_readline or
|
38
|
+
# Windows users can otherwise run ansicon and get a decent answer:
|
39
|
+
screen_size_according_to_ansicon_env
|
40
|
+
end
|
41
|
+
|
42
|
+
def screen_size_according_to_io_console
|
43
|
+
return if Pry::Helpers::BaseHelpers.jruby?
|
44
|
+
require 'io/console'
|
45
|
+
$stdout.winsize if $stdout.tty? and $stdout.respond_to?(:winsize)
|
46
|
+
rescue LoadError
|
47
|
+
# They're probably on 1.8 without the io-console gem. We'll keep trying.
|
48
|
+
end
|
49
|
+
|
50
|
+
def screen_size_according_to_env
|
51
|
+
size = [ENV['LINES'] || ENV['ROWS'], ENV['COLUMNS']]
|
52
|
+
size if nonzero_column?(size)
|
53
|
+
end
|
54
|
+
|
55
|
+
def screen_size_according_to_readline
|
56
|
+
if Readline.respond_to?(:get_screen_size)
|
57
|
+
size = Readline.get_screen_size
|
58
|
+
size if nonzero_column?(size)
|
59
|
+
end
|
60
|
+
rescue Java::JavaLang::NullPointerException
|
61
|
+
# This rescue won't happen on jrubies later than:
|
62
|
+
# https://github.com/jruby/jruby/pull/436
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def screen_size_according_to_ansicon_env
|
67
|
+
return unless ENV['ANSICON'] =~ /\((.*)x(.*)\)/
|
68
|
+
size = [$2, $1]
|
69
|
+
size if nonzero_column?(size)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def nonzero_column?(size)
|
75
|
+
size[1].to_i > 0
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|