pry 0.9.11.4-i386-mingw32 → 0.9.12-i386-mingw32

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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
@@ -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
@@ -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