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
@@ -71,9 +71,18 @@ class Pry
71
71
  # get new target for 1/2 and find candidates for 3
72
72
  path, input = build_path(input)
73
73
 
74
- unless path.call.empty?
75
- target, _ = Pry::Helpers::BaseHelpers.context_from_object_path(path.call, pry)
76
- target = target.last
74
+ # We silence warnings here or Ruby 1.8 cries about "multiple values for
75
+ # block 0 for 1".
76
+ Helpers::BaseHelpers.silence_warnings do
77
+ unless path.call.empty?
78
+ target = begin
79
+ ctx = Helpers::BaseHelpers.context_from_object_path(path.call, pry)
80
+ ctx.first
81
+ rescue Pry::CommandError
82
+ []
83
+ end
84
+ target = target.last
85
+ end
77
86
  end
78
87
 
79
88
  begin
@@ -283,7 +292,7 @@ class Pry
283
292
  contexts = input.chomp('/').split(/\//)
284
293
  input = contexts[-1]
285
294
 
286
- path = proc do |input|
295
+ path = Proc.new do |input|
287
296
  p = contexts[0..-2].push(input).join('/')
288
297
  p += '/' if trailing_slash && !input.nil?
289
298
  p
@@ -83,12 +83,15 @@ class Pry
83
83
  defined?(Win32::Console) || ENV['ANSICON']
84
84
  end
85
85
 
86
- # are we on Jruby platform?
87
86
  def jruby?
88
87
  RbConfig::CONFIG['ruby_install_name'] == 'jruby'
89
88
  end
90
89
 
91
- # are we on rbx platform?
90
+ def jruby_19?
91
+ RbConfig::CONFIG['ruby_install_name'] == 'jruby' &&
92
+ RbConfig::CONFIG['ruby_version'] == '1.9'
93
+ end
94
+
92
95
  def rbx?
93
96
  RbConfig::CONFIG['ruby_install_name'] == 'rbx'
94
97
  end
@@ -84,7 +84,9 @@ class Pry
84
84
  text = text.sub(/^[ \t]+$/, '')
85
85
 
86
86
  # Find the longest common whitespace to all indented lines
87
- margin = text.scan(/^[ \t]*(?=[^ \t\n])/).inject do |current_margin, next_indent|
87
+ # Ignore lines containing just -- or ++ as these seem to be used by
88
+ # comment authors as delimeters.
89
+ margin = text.scan(/^[ \t]*(?!--\n|\+\+\n)(?=[^ \t\n])/).inject do |current_margin, next_indent|
88
90
  if next_indent.start_with?(current_margin)
89
91
  current_margin
90
92
  elsif current_margin.start_with?(next_indent)
@@ -4,14 +4,18 @@ class Pry
4
4
  # This class contains methods useful for extracting
5
5
  # documentation from methods and classes.
6
6
  module DocumentationHelpers
7
+
8
+ module_function
9
+
7
10
  def process_rdoc(comment)
11
+ return comment unless Pry.color
8
12
  comment = comment.dup
9
- comment.gsub(/<code>(?:\s*\n)?(.*?)\s*<\/code>/m) { Pry.color ? CodeRay.scan($1, :ruby).term : $1 }.
10
- gsub(/<em>(?:\s*\n)?(.*?)\s*<\/em>/m) { Pry.color ? "\e[1m#{$1}\e[0m": $1 }.
11
- gsub(/<i>(?:\s*\n)?(.*?)\s*<\/i>/m) { Pry.color ? "\e[1m#{$1}\e[0m" : $1 }.
12
- gsub(/\B\+(\w*?)\+\B/) { Pry.color ? "\e[32m#{$1}\e[0m": $1 }.
13
- gsub(/((?:^[ \t]+.+(?:\n+|\Z))+)/) { Pry.color ? CodeRay.scan($1, :ruby).term : $1 }.
14
- gsub(/`(?:\s*\n)?([^\e]*?)\s*`/) { "`#{Pry.color ? CodeRay.scan($1, :ruby).term : $1}`" }
13
+ comment.gsub(/<code>(?:\s*\n)?(.*?)\s*<\/code>/m) { CodeRay.scan($1, :ruby).term }.
14
+ gsub(/<em>(?:\s*\n)?(.*?)\s*<\/em>/m) { "\e[1m#{$1}\e[0m" }.
15
+ gsub(/<i>(?:\s*\n)?(.*?)\s*<\/i>/m) { "\e[1m#{$1}\e[0m" }.
16
+ gsub(/\B\+(\w+?)\+\B/) { "\e[32m#{$1}\e[0m" }.
17
+ gsub(/((?:^[ \t]+.+(?:\n+|\Z))+)/) { CodeRay.scan($1, :ruby).term }.
18
+ gsub(/`(?:\s*\n)?([^\e]*?)\s*`/) { "`#{CodeRay.scan($1, :ruby).term}`" }
15
19
  end
16
20
 
17
21
  def process_yardoc_tag(comment, tag)
@@ -46,10 +50,17 @@ class Pry
46
50
  code.sub(/\A\s*\/\*.*?\*\/\s*/m, '')
47
51
  end
48
52
 
53
+ # Given a string that makes up a comment in a source-code file parse out the content
54
+ # that the user is intended to read. (i.e. without leading indentation, #-characters
55
+ # or shebangs)
56
+ #
49
57
  # @param [String] comment
50
58
  # @return [String]
51
- def strip_leading_hash_and_whitespace_from_ruby_comments(comment)
59
+ def get_comment_content(comment)
52
60
  comment = comment.dup
61
+ # Remove #!/usr/bin/ruby
62
+ comment.gsub!(/\A\#!.*$/, '')
63
+ # Remove leading empty comment lines
53
64
  comment.gsub!(/\A\#+?$/, '')
54
65
  comment.gsub!(/^\s*#/, '')
55
66
  strip_leading_whitespace(comment)
@@ -3,7 +3,7 @@ class Pry
3
3
  def self.tablify_or_one_line(heading, things)
4
4
  plain_heading = Pry::Helpers::Text.strip_color(heading)
5
5
  attempt = Table.new(things, :column_count => things.size)
6
- if attempt.fits_on_line?(TerminalInfo.width! - plain_heading.size - 2)
6
+ if attempt.fits_on_line?(Terminal.width! - plain_heading.size - 2)
7
7
  "#{heading}: #{attempt}\n"
8
8
  else
9
9
  "#{heading}: \n#{tablify_to_screen_width(things, :indent => ' ')}\n"
@@ -13,16 +13,16 @@ class Pry
13
13
  def self.tablify_to_screen_width(things, options = {})
14
14
  things = things.compact
15
15
  if indent = options[:indent]
16
- usable_width = TerminalInfo.width! - indent.size
16
+ usable_width = Terminal.width! - indent.size
17
17
  tablify(things, usable_width).to_s.gsub(/^/, indent)
18
18
  else
19
- tablify(things, TerminalInfo.width!).to_s
19
+ tablify(things, Terminal.width!).to_s
20
20
  end
21
21
  end
22
22
 
23
23
  def self.tablify(things, line_length)
24
24
  table = Table.new(things, :column_count => things.size)
25
- table.column_count -= 1 until 0 == table.column_count or
25
+ table.column_count -= 1 until 1 == table.column_count or
26
26
  table.fits_on_line?(line_length)
27
27
  table
28
28
  end
data/lib/pry/indent.rb CHANGED
@@ -1,12 +1,6 @@
1
1
  require 'coderay'
2
2
 
3
3
  class Pry
4
- # Load io-console if possible, so that we can use $stdout.winsize.
5
- begin
6
- require 'io/console'
7
- rescue LoadError
8
- end
9
-
10
4
  ##
11
5
  # Pry::Indent is a class that can be used to indent a number of lines
12
6
  # containing Ruby code similar as to how IRB does it (but better). The class
@@ -389,10 +383,11 @@ class Pry
389
383
  # the difference in length between the old line and the new one).
390
384
  # @return [String]
391
385
  def correct_indentation(prompt, code, overhang=0)
386
+ prompt = prompt.delete("\001\002")
392
387
  full_line = prompt + code
393
388
  whitespace = ' ' * overhang
394
389
 
395
- _, cols = TerminalInfo.screen_size
390
+ _, cols = Terminal.screen_size
396
391
 
397
392
  cols = cols.to_i
398
393
  lines = cols != 0 ? (full_line.length / cols + 1) : 1
data/lib/pry/method.rb CHANGED
@@ -17,9 +17,12 @@ class Pry
17
17
  # This class wraps the normal `Method` and `UnboundMethod` classes
18
18
  # to provide extra functionality useful to Pry.
19
19
  class Method
20
+ require 'pry/method/weird_method_locator'
21
+ require 'pry/method/disowned'
22
+
20
23
  extend Helpers::BaseHelpers
21
24
  include Helpers::BaseHelpers
22
- include RbxMethod if Helpers::BaseHelpers.rbx?
25
+ include RbxMethod if rbx?
23
26
  include Helpers::DocumentationHelpers
24
27
  include CodeObject::Helpers
25
28
 
@@ -82,37 +85,11 @@ class Pry
82
85
  Disowned.new(b.eval('self'), meth_name.to_s)
83
86
  end
84
87
 
85
- # it's possible in some cases that the method we find by this approach is a sub-method of
86
- # the one we're currently in, consider:
87
- #
88
- # class A; def b; binding.pry; end; end
89
- # class B < A; def b; super; end; end
90
- #
91
- # Given that we can normally find the source_range of methods, and that we know which
92
- # __FILE__ and __LINE__ the binding is at, we can hope to disambiguate these cases.
93
- #
94
- # This obviously won't work if the source is unavaiable for some reason, or if both
95
- # methods have the same __FILE__ and __LINE__, or if we're in rbx where b.eval('__LINE__')
96
- # is broken.
97
- #
98
- guess = method
99
-
100
- while guess
101
- # needs rescue if this is a Disowned method or a C method or something...
102
- # TODO: Fix up the exception handling so we don't need a bare rescue
103
- if (guess.source_file && guess.source_range rescue false) &&
104
- File.expand_path(guess.source_file) == File.expand_path(b.eval('__FILE__')) &&
105
- guess.source_range.include?(b.eval('__LINE__'))
106
- return guess
107
- else
108
- guess = guess.super
109
- end
88
+ if WeirdMethodLocator.weird_method?(method, b)
89
+ WeirdMethodLocator.new(method, b).get_method || method
90
+ else
91
+ method
110
92
  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
- method
116
93
  end
117
94
  end
118
95
 
@@ -196,6 +173,19 @@ class Pry
196
173
  ([klass] + klass.ancestors).uniq
197
174
  end
198
175
 
176
+ def method_definition?(name, definition_line)
177
+ singleton_method_definition?(name, definition_line) ||
178
+ instance_method_definition?(name, definition_line)
179
+ end
180
+
181
+ def singleton_method_definition?(name, definition_line)
182
+ /^define_singleton_method\(?\s*[:\"\']#{name}|^def\s*self\.#{name}/ =~ definition_line.strip
183
+ end
184
+
185
+ def instance_method_definition?(name, definition_line)
186
+ /^define_method\(?\s*[:\"\']#{name}|^def\s*#{name}/ =~ definition_line.strip
187
+ end
188
+
199
189
  private
200
190
 
201
191
  # See all_from_class and all_from_obj.
@@ -310,12 +300,12 @@ class Pry
310
300
  info = pry_doc_info
311
301
  info.docstring if info
312
302
  when :ruby
313
- if Helpers::BaseHelpers.rbx? && !pry_method?
314
- strip_leading_hash_and_whitespace_from_ruby_comments(core_doc)
303
+ if rbx? && !pry_method?
304
+ get_comment_content(core_doc)
315
305
  elsif pry_method?
316
- strip_leading_hash_and_whitespace_from_ruby_comments(doc_for_pry_method)
306
+ get_comment_content(doc_for_pry_method)
317
307
  else
318
- strip_leading_hash_and_whitespace_from_ruby_comments(@method.comment)
308
+ get_comment_content(@method.comment)
319
309
  end
320
310
  end
321
311
  end
@@ -327,7 +317,7 @@ class Pry
327
317
  end
328
318
 
329
319
  def source_location
330
- if @method.source_location && Helpers::BaseHelpers.rbx?
320
+ if @method.source_location && rbx?
331
321
  file, line = @method.source_location
332
322
  [RbxPath.convert_path_to_full(file), line]
333
323
  else
@@ -339,7 +329,7 @@ class Pry
339
329
  # `nil` if the filename is unavailable.
340
330
  def source_file
341
331
  if source_location.nil?
342
- if !Helpers::BaseHelpers.rbx? and source_type == :c
332
+ if !rbx? and source_type == :c
343
333
  info = pry_doc_info
344
334
  info.file if info
345
335
  end
@@ -423,6 +413,21 @@ class Pry
423
413
  !!(source_file and source_file =~ /(\(.*\))|<.*>/)
424
414
  end
425
415
 
416
+ # @return [Boolean] Whether the method is unbound.
417
+ def unbound_method?
418
+ is_a?(::UnboundMethod)
419
+ end
420
+
421
+ # @return [Boolean] Whether the method is bound.
422
+ def bound_method?
423
+ is_a?(::Method)
424
+ end
425
+
426
+ # @return [Boolean] Whether the method is a singleton method.
427
+ def singleton_method?
428
+ wrapped_owner.singleton_class?
429
+ end
430
+
426
431
  # @return [Boolean] Was the method defined within the Pry REPL?
427
432
  def pry_method?
428
433
  source_file == Pry.eval_path
@@ -479,113 +484,68 @@ class Pry
479
484
  end
480
485
 
481
486
  private
482
- # @return [YARD::CodeObjects::MethodObject]
483
- # @raise [CommandError] Raises when the method can't be found or `pry-doc` isn't installed.
484
- def pry_doc_info
485
- if Pry.config.has_pry_doc
486
- Pry::MethodInfo.info_for(@method) or raise CommandError, "Cannot locate this method: #{name}. (source_location returns nil)"
487
- else
488
- raise CommandError, "Cannot locate this method: #{name}. Try `gem install pry-doc` to get access to Ruby Core documentation."
489
- end
490
- end
491
-
492
- # FIXME: a very similar method to this exists on WrappedModule: extract_doc_for_candidate
493
- def doc_for_pry_method
494
- _, line_num = source_location
495
-
496
- buffer = ""
497
- Pry.line_buffer[0..(line_num - 1)].each do |line|
498
- # Add any line that is a valid ruby comment,
499
- # but clear as soon as we hit a non comment line.
500
- if (line =~ /^\s*#/) || (line =~ /^\s*$/)
501
- buffer << line.lstrip
502
- else
503
- buffer.replace("")
504
- end
505
- end
506
487
 
507
- buffer
508
- end
509
-
510
- # @param [Class, Module] ancestors The ancestors to investigate
511
- # @return [Method] The unwrapped super-method
512
- def super_using_ancestors(ancestors, times=1)
513
- next_owner = self.owner
514
- times.times do
515
- i = ancestors.index(next_owner) + 1
516
- while ancestors[i] && !(ancestors[i].method_defined?(name) || ancestors[i].private_method_defined?(name))
517
- i += 1
518
- end
519
- next_owner = ancestors[i] or return nil
488
+ # @return [YARD::CodeObjects::MethodObject]
489
+ # @raise [CommandError] when the method can't be found or `pry-doc` isn't installed.
490
+ def pry_doc_info
491
+ if Pry.config.has_pry_doc
492
+ Pry::MethodInfo.info_for(@method) or raise CommandError, "Cannot locate this method: #{name}. (source_location returns nil)"
493
+ else
494
+ fail_msg = "Cannot locate this method: #{name}."
495
+ if mri_18? || mri_19?
496
+ fail_msg += ' Try `gem-install pry-doc` to get access to Ruby Core documentation.'
520
497
  end
521
-
522
- safe_send(next_owner, :instance_method, name) rescue nil
498
+ raise CommandError, fail_msg
523
499
  end
500
+ end
524
501
 
525
- # @param [String] first_ln The first line of a method definition.
526
- # @return [String, nil]
527
- def method_name_from_first_line(first_ln)
528
- return nil if first_ln.strip !~ /^def /
502
+ # FIXME: a very similar method to this exists on WrappedModule: extract_doc_for_candidate
503
+ def doc_for_pry_method
504
+ _, line_num = source_location
529
505
 
530
- tokens = CodeRay.scan(first_ln, :ruby)
531
- tokens = tokens.tokens.each_slice(2) if tokens.respond_to?(:tokens)
532
- tokens.each_cons(2) do |t1, t2|
533
- if t2.last == :method || t2.last == :ident && t1 == [".", :operator]
534
- return t2.first
535
- end
506
+ buffer = ""
507
+ Pry.line_buffer[0..(line_num - 1)].each do |line|
508
+ # Add any line that is a valid ruby comment,
509
+ # but clear as soon as we hit a non comment line.
510
+ if (line =~ /^\s*#/) || (line =~ /^\s*$/)
511
+ buffer << line.lstrip
512
+ else
513
+ buffer.replace("")
536
514
  end
537
-
538
- nil
539
515
  end
540
516
 
541
- # A Disowned Method is one that's been removed from the class on which it was defined.
542
- #
543
- # e.g.
544
- # class C
545
- # def foo
546
- # C.send(:undefine_method, :foo)
547
- # Pry::Method.from_binding(binding)
548
- # end
549
- # end
550
- #
551
- # In this case we assume that the "owner" is the singleton class of the receiver.
552
- #
553
- # This occurs mainly in Sinatra applications.
554
- class Disowned < Method
555
- attr_reader :receiver, :name
517
+ buffer
518
+ end
556
519
 
557
- # Create a new Disowned method.
558
- #
559
- # @param [Object] receiver
560
- # @param [String] method_name
561
- def initialize(receiver, method_name)
562
- @receiver, @name = receiver, method_name
520
+ # @param [Class, Module] ancestors The ancestors to investigate
521
+ # @return [Method] The unwrapped super-method
522
+ def super_using_ancestors(ancestors, times=1)
523
+ next_owner = self.owner
524
+ times.times do
525
+ i = ancestors.index(next_owner) + 1
526
+ while ancestors[i] && !(ancestors[i].method_defined?(name) || ancestors[i].private_method_defined?(name))
527
+ i += 1
528
+ end
529
+ next_owner = ancestors[i] or return nil
563
530
  end
564
531
 
565
- # Is the method undefined? (aka `Disowned`)
566
- # @return [Boolean] true
567
- def undefined?
568
- true
569
- end
532
+ safe_send(next_owner, :instance_method, name) rescue nil
533
+ end
570
534
 
571
- # Can we get the source for this method?
572
- # @return [Boolean] false
573
- def source?
574
- false
575
- end
535
+ # @param [String] first_ln The first line of a method definition.
536
+ # @return [String, nil]
537
+ def method_name_from_first_line(first_ln)
538
+ return nil if first_ln.strip !~ /^def /
576
539
 
577
- # Get the hypothesized owner of the method.
578
- #
579
- # @return [Object]
580
- def owner
581
- class << receiver; self; end
540
+ tokens = CodeRay.scan(first_ln, :ruby)
541
+ tokens = tokens.tokens.each_slice(2) if tokens.respond_to?(:tokens)
542
+ tokens.each_cons(2) do |t1, t2|
543
+ if t2.last == :method || t2.last == :ident && t1 == [".", :operator]
544
+ return t2.first
545
+ end
582
546
  end
583
547
 
584
- # Raise a more useful error message instead of trying to forward to nil.
585
- def method_missing(meth_name, *args, &block)
586
- raise "Cannot call '#{meth_name}' on an undef'd method." if method(:name).respond_to?(meth_name)
587
- Object.instance_method(:method_missing).bind(self).call(meth_name, *args, &block)
588
- end
548
+ nil
589
549
  end
590
550
  end
591
551
  end