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.
Files changed (47) hide show
  1. data/.travis.yml +2 -0
  2. data/CHANGELOG +19 -0
  3. data/Rakefile +4 -0
  4. data/lib/pry.rb +1 -1
  5. data/lib/pry/cli.rb +14 -8
  6. data/lib/pry/code.rb +3 -3
  7. data/lib/pry/command.rb +20 -5
  8. data/lib/pry/command_set.rb +3 -3
  9. data/lib/pry/commands.rb +1 -1
  10. data/lib/pry/commands/disabled_commands.rb +2 -0
  11. data/lib/pry/commands/ls.rb +1 -2
  12. data/lib/pry/commands/reload_code.rb +8 -1
  13. data/lib/pry/commands/show_info.rb +66 -5
  14. data/lib/pry/commands/show_source.rb +2 -1
  15. data/lib/pry/commands/whereami.rb +87 -19
  16. data/lib/pry/completion.rb +13 -4
  17. data/lib/pry/helpers/base_helpers.rb +5 -2
  18. data/lib/pry/helpers/command_helpers.rb +3 -1
  19. data/lib/pry/helpers/documentation_helpers.rb +18 -7
  20. data/lib/pry/helpers/table.rb +4 -4
  21. data/lib/pry/indent.rb +2 -7
  22. data/lib/pry/method.rb +89 -129
  23. data/lib/pry/method/disowned.rb +53 -0
  24. data/lib/pry/method/weird_method_locator.rb +186 -0
  25. data/lib/pry/module_candidate.rb +13 -8
  26. data/lib/pry/pager.rb +12 -11
  27. data/lib/pry/plugins.rb +2 -0
  28. data/lib/pry/pry_class.rb +19 -3
  29. data/lib/pry/pry_instance.rb +3 -0
  30. data/lib/pry/terminal.rb +78 -0
  31. data/lib/pry/version.rb +1 -1
  32. data/lib/pry/wrapped_module.rb +63 -1
  33. data/spec/Procfile +3 -0
  34. data/spec/command_helpers_spec.rb +21 -1
  35. data/spec/commands/ls_spec.rb +4 -0
  36. data/spec/commands/show_doc_spec.rb +255 -123
  37. data/spec/commands/show_source_spec.rb +421 -236
  38. data/spec/commands/whereami_spec.rb +60 -11
  39. data/spec/completion_spec.rb +6 -0
  40. data/spec/documentation_helper_spec.rb +73 -0
  41. data/spec/fixtures/whereami_helper.rb +6 -0
  42. data/spec/helpers/table_spec.rb +19 -0
  43. data/spec/method_spec.rb +24 -7
  44. metadata +12 -5
  45. data/.gemtest +0 -0
  46. data/lib/pry/commands/deprecated_commands.rb +0 -2
  47. 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
@@ -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 instance`.
24
- to_delegate = [:lines_for_file, :method_candidates, :name, :wrapped,
25
- :yard_docs?, :number_of_candidates]
23
+ # Methods to delegate to associated `Pry::WrappedModule
24
+ # instance`.
25
+ private_delegates = [:lines_for_file, :method_candidates,
26
+ :yard_docs?]
26
27
 
27
- def_delegators :@wrapper, *to_delegate
28
- private(*to_delegate)
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 = strip_leading_hash_and_whitespace_from_ruby_comments(Pry::Code.from_file(file).comment_describing(line))
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
- is_jruby = defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
16
- (is_jruby || no_pager) ? SimplePager.new(text).page : SystemPager.new(text).page
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 ||= begin
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
- text_array.each_slice(Pry::Pager.page_size) do |chunk|
42
+
43
+ text_array.each_slice(page_size) do |chunk|
43
44
  puts chunk.join
44
- break if chunk.size < Pry::Pager.page_size
45
- if text_array.size > Pry::Pager.page_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
@@ -50,6 +50,8 @@ class Pry
50
50
  rescue LoadError => e
51
51
  warn "Found plugin #{gem_name}, but could not require '#{gem_name}'"
52
52
  warn e
53
+ rescue => e
54
+ warn "require '#{gem_name}' # Failed, saying: #{e}"
53
55
  end
54
56
 
55
57
  self.active = true
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
- size = `stty size`.split(/\s+/).map &:to_i
267
- Readline.set_screen_size *size
268
- Readline.refresh_line
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
 
@@ -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)
@@ -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