pry 0.10.4 → 0.11.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -18
  3. data/LICENSE +1 -1
  4. data/README.md +28 -26
  5. data/bin/pry +3 -7
  6. data/lib/pry.rb +3 -2
  7. data/lib/pry/basic_object.rb +6 -0
  8. data/lib/pry/cli.rb +39 -34
  9. data/lib/pry/code.rb +6 -1
  10. data/lib/pry/code/code_file.rb +8 -2
  11. data/lib/pry/code_object.rb +23 -0
  12. data/lib/pry/color_printer.rb +11 -8
  13. data/lib/pry/command.rb +40 -16
  14. data/lib/pry/command_set.rb +9 -2
  15. data/lib/pry/commands/cat/exception_formatter.rb +11 -10
  16. data/lib/pry/commands/cat/file_formatter.rb +7 -3
  17. data/lib/pry/commands/code_collector.rb +16 -14
  18. data/lib/pry/commands/easter_eggs.rb +9 -9
  19. data/lib/pry/commands/edit.rb +6 -2
  20. data/lib/pry/commands/edit/file_and_line_locator.rb +1 -1
  21. data/lib/pry/commands/find_method.rb +1 -1
  22. data/lib/pry/commands/gem_open.rb +1 -1
  23. data/lib/pry/commands/gem_readme.rb +25 -0
  24. data/lib/pry/commands/gem_search.rb +40 -0
  25. data/lib/pry/commands/hist.rb +2 -2
  26. data/lib/pry/commands/jump_to.rb +7 -7
  27. data/lib/pry/commands/ls/formatter.rb +1 -0
  28. data/lib/pry/commands/ls/jruby_hacks.rb +2 -2
  29. data/lib/pry/commands/ls/self_methods.rb +2 -0
  30. data/lib/pry/commands/play.rb +2 -2
  31. data/lib/pry/commands/reload_code.rb +2 -2
  32. data/lib/pry/commands/ri.rb +4 -0
  33. data/lib/pry/commands/shell_command.rb +34 -8
  34. data/lib/pry/commands/show_info.rb +10 -2
  35. data/lib/pry/commands/watch_expression/expression.rb +1 -1
  36. data/lib/pry/commands/whereami.rb +6 -6
  37. data/lib/pry/config.rb +3 -16
  38. data/lib/pry/config/behavior.rb +139 -49
  39. data/lib/pry/config/default.rb +21 -33
  40. data/lib/pry/config/lazy.rb +25 -0
  41. data/lib/pry/editor.rb +1 -1
  42. data/lib/pry/exceptions.rb +1 -1
  43. data/lib/pry/helpers/base_helpers.rb +6 -10
  44. data/lib/pry/helpers/documentation_helpers.rb +1 -0
  45. data/lib/pry/helpers/options_helpers.rb +1 -1
  46. data/lib/pry/helpers/text.rb +69 -76
  47. data/lib/pry/history.rb +22 -1
  48. data/lib/pry/history_array.rb +1 -1
  49. data/lib/pry/hooks.rb +48 -107
  50. data/lib/pry/indent.rb +6 -2
  51. data/lib/pry/input_completer.rb +118 -118
  52. data/lib/pry/method.rb +13 -13
  53. data/lib/pry/method/disowned.rb +1 -0
  54. data/lib/pry/method/patcher.rb +0 -3
  55. data/lib/pry/output.rb +37 -38
  56. data/lib/pry/pager.rb +11 -8
  57. data/lib/pry/plugins.rb +20 -5
  58. data/lib/pry/pry_class.rb +29 -3
  59. data/lib/pry/pry_instance.rb +8 -6
  60. data/lib/pry/repl.rb +37 -5
  61. data/lib/pry/repl_file_loader.rb +1 -1
  62. data/lib/pry/rubygem.rb +3 -1
  63. data/lib/pry/slop.rb +661 -0
  64. data/lib/pry/slop/LICENSE +20 -0
  65. data/lib/pry/slop/commands.rb +196 -0
  66. data/lib/pry/slop/option.rb +208 -0
  67. data/lib/pry/terminal.rb +16 -5
  68. data/lib/pry/test/helper.rb +11 -2
  69. data/lib/pry/version.rb +1 -1
  70. data/lib/pry/wrapped_module.rb +5 -5
  71. data/lib/pry/{module_candidate.rb → wrapped_module/candidate.rb} +2 -4
  72. metadata +14 -20
@@ -17,8 +17,12 @@ class Pry
17
17
  %w(.c .h) => :c,
18
18
  %w(.rhtml) => :rhtml,
19
19
  %w(.yaml .yml) => :yaml,
20
- %w(.cpp .hpp .cc .h cxx) => :cpp,
21
- %w(.rb .ru .irbrc .gemspec .pryrc) => :ruby,
20
+ %w(.cpp .hpp .cc .h .cxx) => :cpp,
21
+ %w(.rb .ru .irbrc .gemspec .pryrc .rake) => :ruby,
22
+ }
23
+
24
+ FILES = {
25
+ %w(Gemfile Rakefile Guardfile Capfile) => :ruby
22
26
  }
23
27
 
24
28
  # @return [Symbol] The type of code stored in this wrapper.
@@ -79,6 +83,8 @@ class Pry
79
83
  def type_from_filename(filename, default = :unknown)
80
84
  _, @code_type = EXTENSIONS.find do |k, _|
81
85
  k.any? { |ext| ext == File.extname(filename) }
86
+ end || FILES.find do |k, _|
87
+ k.any? { |file_name| file_name == File.basename(filename) }
82
88
  end
83
89
 
84
90
  code_type || default
@@ -37,6 +37,28 @@ class Pry
37
37
  def command?
38
38
  is_a?(Module) && self <= Pry::Command
39
39
  end
40
+
41
+ # @return [Boolean] `true` if this module was defined by means of the C API,
42
+ # `false` if it's a Ruby module.
43
+ # @note If a module defined by C was extended with a lot of methods written
44
+ # in Ruby, this method would fail.
45
+ def c_module?
46
+ if is_a?(WrappedModule)
47
+
48
+ method_locations = wrapped.methods(false).map do |m|
49
+ wrapped.method(m).source_location
50
+ end
51
+
52
+ method_locations.concat(wrapped.instance_methods(false).map do |m|
53
+ wrapped.instance_method(m).source_location
54
+ end)
55
+
56
+ c_methods = method_locations.grep(nil).count
57
+ ruby_methods = method_locations.count - c_methods
58
+
59
+ c_methods > ruby_methods
60
+ end
61
+ end
40
62
  end
41
63
 
42
64
  include Pry::Helpers::CommandHelpers
@@ -147,6 +169,7 @@ class Pry
147
169
  # @return [Boolean]
148
170
  def safe_to_evaluate?(str)
149
171
  return true if str.strip == "self"
172
+ return false if str =~ /%/
150
173
  kind = target.eval("defined?(#{str})")
151
174
  kind =~ /variable|constant/
152
175
  end
@@ -34,14 +34,17 @@ class Pry
34
34
  super
35
35
  rescue => e
36
36
  raise if e.is_a? Pry::Pager::StopPaging
37
-
38
- # Read the class name off of the singleton class to provide a default
39
- # inspect.
40
- singleton = class << obj; self; end
41
- ancestors = Pry::Method.safe_send(singleton, :ancestors)
42
- klass = ancestors.reject { |k| k == singleton }.first
43
- obj_id = obj.__id__.to_s(16) rescue 0
44
- str = "#<#{klass}:0x#{obj_id}>"
37
+ begin
38
+ str = obj.inspect
39
+ rescue Exception
40
+ # Read the class name off of the singleton class to provide a default
41
+ # inspect.
42
+ singleton = class << obj; self; end
43
+ ancestors = Pry::Method.safe_send(singleton, :ancestors)
44
+ klass = ancestors.reject { |k| k == singleton }.first
45
+ obj_id = obj.__id__.to_s(16) rescue 0
46
+ str = "#<#{klass}:0x#{obj_id}>"
47
+ end
45
48
 
46
49
  text highlight_object_literal(str)
47
50
  end
@@ -52,7 +52,7 @@ class Pry
52
52
  # Define or get the command's banner
53
53
  def banner(arg=nil)
54
54
  @banner = arg if arg
55
- @banner || description
55
+ @banner ||= description
56
56
  end
57
57
 
58
58
  def block
@@ -167,11 +167,12 @@ class Pry
167
167
  end
168
168
  end
169
169
 
170
+ # @deprecated Replaced with {Pry::Hooks#add_hook}. Left for compatibility.
170
171
  # Store hooks to be run before or after the command body.
171
172
  # @see {Pry::CommandSet#before_command}
172
173
  # @see {Pry::CommandSet#after_command}
173
174
  def hooks
174
- @hooks ||= {:before => [], :after => []}
175
+ Pry.hooks
175
176
  end
176
177
 
177
178
  def command_regex
@@ -223,6 +224,7 @@ class Pry
223
224
  attr_accessor :arg_string
224
225
  attr_accessor :context
225
226
  attr_accessor :command_set
227
+ attr_accessor :hooks
226
228
  attr_accessor :_pry_
227
229
 
228
230
  # The block we pass *into* a command so long as `:takes_block` is
@@ -271,6 +273,7 @@ class Pry
271
273
  self.output = context[:output]
272
274
  self.eval_string = context[:eval_string]
273
275
  self.command_set = context[:command_set]
276
+ self.hooks = context[:hooks]
274
277
  self._pry_ = context[:pry_instance]
275
278
  end
276
279
 
@@ -424,10 +427,20 @@ class Pry
424
427
  raise CommandError, "The command '#{command_name}' requires an argument."
425
428
  end
426
429
 
427
- ret = call_with_hooks(*args)
430
+ ret = use_unpatched_symbol do
431
+ call_with_hooks(*args)
432
+ end
428
433
  command_options[:keep_retval] ? ret : void
429
434
  end
430
435
 
436
+ def use_unpatched_symbol
437
+ call_method = Symbol.method_defined?(:call) && Symbol.instance_method(:call)
438
+ Symbol.class_eval { undef :call } if call_method
439
+ yield
440
+ ensure
441
+ Symbol.instance_eval { define_method(:call, call_method) } if call_method
442
+ end
443
+
431
444
  # Are all the gems required to use this command installed?
432
445
  #
433
446
  # @return Boolean
@@ -445,17 +458,28 @@ class Pry
445
458
 
446
459
  private
447
460
 
461
+ def find_hooks(event)
462
+ event_name = "#{event}_#{command_name}"
463
+ (self.hooks || self.class.hooks).get_hooks(event_name).values
464
+ end
465
+
466
+ def before_hooks
467
+ find_hooks('before')
468
+ end
469
+
470
+ def after_hooks
471
+ find_hooks('after')
472
+ end
473
+
448
474
  # Run the `#call` method and all the registered hooks.
449
475
  # @param [Array<String>] args The arguments to `#call`
450
476
  # @return [Object] The return value from `#call`
451
477
  def call_with_hooks(*args)
452
- self.class.hooks[:before].each do |block|
453
- instance_exec(*args, &block)
454
- end
478
+ before_hooks.each { |block| instance_exec(*args, &block) }
455
479
 
456
480
  ret = call(*args)
457
481
 
458
- self.class.hooks[:after].each do |block|
482
+ after_hooks.each do |block|
459
483
  ret = instance_exec(*args, &block)
460
484
  end
461
485
 
@@ -507,7 +531,7 @@ class Pry
507
531
  # subclasses.
508
532
  #
509
533
  # Create subclasses using {Pry::CommandSet#create_command}, and override the
510
- # `options(opt)` method to set up an instance of Slop, and the `process`
534
+ # `options(opt)` method to set up an instance of Pry::Slop, and the `process`
511
535
  # method to actually run the command. If necessary, you can also override
512
536
  # `setup` which will be called before `options`, for example to require any
513
537
  # gems your command needs to run, or to set up state.
@@ -583,15 +607,15 @@ class Pry
583
607
  end
584
608
  end
585
609
 
586
- # Return the help generated by Slop for this command.
610
+ # Return the help generated by Pry::Slop for this command.
587
611
  def help
588
612
  slop.help
589
613
  end
590
614
 
591
- # Return an instance of Slop that can parse either subcommands or the
615
+ # Return an instance of Pry::Slop that can parse either subcommands or the
592
616
  # options that this command accepts.
593
617
  def slop
594
- Slop.new do |opt|
618
+ Pry::Slop.new do |opt|
595
619
  opt.banner(unindent(self.class.banner))
596
620
  subcommands(opt)
597
621
  options(opt)
@@ -603,9 +627,9 @@ class Pry
603
627
  # @param [String] search The line typed so far
604
628
  # @return [Array<String>] the words to complete
605
629
  def complete(search)
606
- slop.map do |opt|
630
+ slop.flat_map do |opt|
607
631
  [opt.long && "--#{opt.long} " || opt.short && "-#{opt.short}"]
608
- end.flatten(1).compact + super
632
+ end.compact + super
609
633
  end
610
634
 
611
635
  # A method called just before `options(opt)` as part of `call`.
@@ -620,7 +644,7 @@ class Pry
620
644
  # end
621
645
  def setup; end
622
646
 
623
- # A method to setup Slop commands so it can parse the subcommands your
647
+ # A method to setup Pry::Slop commands so it can parse the subcommands your
624
648
  # command expects. If you need to set up default values, use `setup`
625
649
  # instead.
626
650
  #
@@ -655,7 +679,7 @@ class Pry
655
679
  # end
656
680
  def subcommands(cmd); end
657
681
 
658
- # A method to setup Slop so it can parse the options your command expects.
682
+ # A method to setup Pry::Slop so it can parse the options your command expects.
659
683
  #
660
684
  # @note Please don't do anything side-effecty in the main part of this
661
685
  # method, as it may be called by Pry at any time for introspection reasons.
@@ -672,7 +696,7 @@ class Pry
672
696
 
673
697
  # The actual body of your command should go here.
674
698
  #
675
- # The `opts` mehod can be called to get the options that Slop has passed,
699
+ # The `opts` mehod can be called to get the options that Pry::Slop has passed,
676
700
  # and `args` gives the remaining, unparsed arguments.
677
701
  #
678
702
  # The return value of this method is discarded unless the command was
@@ -125,9 +125,10 @@ class Pry
125
125
  # Pry.config.commands.before_command("whereami") do |n|
126
126
  # output.puts "parameter passed was #{n}"
127
127
  # end
128
+ # @deprecated Use {Pry::Hooks#add_hook} instead.
128
129
  def before_command(search, &block)
129
130
  cmd = find_command_by_match_or_listing(search)
130
- cmd.hooks[:before].unshift block
131
+ cmd.hooks.add_hook("before_#{cmd.command_name}", random_hook_name, block)
131
132
  end
132
133
 
133
134
  # Execute a block of code after a command is invoked. The block also
@@ -139,11 +140,17 @@ class Pry
139
140
  # Pry.config.commands.after_command("whereami") do |n|
140
141
  # output.puts "command complete!"
141
142
  # end
143
+ # @deprecated Use {Pry::Hooks#add_hook} instead.
142
144
  def after_command(search, &block)
143
145
  cmd = find_command_by_match_or_listing(search)
144
- cmd.hooks[:after] << block
146
+ cmd.hooks.add_hook("after_#{cmd.command_name}", random_hook_name, block)
145
147
  end
146
148
 
149
+ def random_hook_name
150
+ (0...8).map { ('a'..'z').to_a[rand(26)] }.join
151
+ end
152
+ private :random_hook_name
153
+
147
154
  def each(&block)
148
155
  @commands.each(&block)
149
156
  end
@@ -27,16 +27,17 @@ class Pry
27
27
  end
28
28
 
29
29
  def backtrace_level
30
- return @backtrace_level if @backtrace_level
31
-
32
- bl = if opts[:ex].nil?
33
- ex.bt_index
34
- else
35
- ex.bt_index = absolute_index_number(opts[:ex], ex.backtrace.size)
36
- end
37
-
38
- increment_backtrace_level
39
- @backtrace_level = bl
30
+ @backtrace_level ||=
31
+ begin
32
+ bl = if opts[:ex].nil?
33
+ ex.bt_index
34
+ else
35
+ ex.bt_index = absolute_index_number(opts[:ex], ex.backtrace.size)
36
+ end
37
+
38
+ increment_backtrace_level
39
+ bl
40
+ end
40
41
  end
41
42
 
42
43
  def increment_backtrace_level
@@ -6,6 +6,8 @@ class Pry
6
6
  attr_reader :_pry_
7
7
 
8
8
  def initialize(file_with_embedded_line, _pry_, opts)
9
+ raise CommandError, "Must provide a filename, --in, or --ex." if !file_with_embedded_line
10
+
9
11
  @file_with_embedded_line = file_with_embedded_line
10
12
  @opts = opts
11
13
  @_pry_ = _pry_
@@ -13,8 +15,6 @@ class Pry
13
15
  end
14
16
 
15
17
  def format
16
- raise CommandError, "Must provide a filename, --in, or --ex." if !file_with_embedded_line
17
-
18
18
  set_file_and_dir_locals(file_name, _pry_, _pry_.current_context)
19
19
  decorate(@code_from_file)
20
20
  end
@@ -40,7 +40,11 @@ class Pry
40
40
  end
41
41
 
42
42
  def decorate(content)
43
- line_number ? super.around(line_number, code_window_size) : super
43
+ if line_number
44
+ super(content.around(line_number, code_window_size))
45
+ else
46
+ super
47
+ end
44
48
  end
45
49
 
46
50
  def code_type
@@ -51,21 +51,23 @@ class Pry
51
51
  #
52
52
  # @return [String]
53
53
  def content
54
- return @content if @content
55
- raise CommandError, "Only one of --out, --in, --doc and CODE_OBJECT may be specified." if bad_option_combination?
54
+ @content ||=
55
+ begin
56
+ raise CommandError, "Only one of --out, --in, --doc and CODE_OBJECT may be specified." if bad_option_combination?
56
57
 
57
- content = case
58
- when opts.present?(:o)
59
- pry_output_content
60
- when opts.present?(:i)
61
- pry_input_content
62
- when opts.present?(:d)
63
- code_object_doc
64
- else
65
- code_object_source_or_file
66
- end
58
+ content = case
59
+ when opts.present?(:o)
60
+ pry_output_content
61
+ when opts.present?(:i)
62
+ pry_input_content
63
+ when opts.present?(:d)
64
+ code_object_doc
65
+ else
66
+ code_object_source_or_file
67
+ end
67
68
 
68
- @content ||= restrict_to_lines(content, line_range)
69
+ restrict_to_lines(content, line_range)
70
+ end
69
71
  end
70
72
 
71
73
  # The code object
@@ -141,7 +143,7 @@ class Pry
141
143
  end
142
144
 
143
145
  def file_content
144
- if File.exists?(obj_name)
146
+ if File.exist?(obj_name)
145
147
  # Set the file accessor.
146
148
  self.file = obj_name
147
149
  File.read(obj_name)
@@ -10,17 +10,17 @@ class Pry
10
10
  end
11
11
 
12
12
  command "get-naked", "" do
13
- text = %{
13
+ txt = %{
14
14
  --
15
15
  We dont have to take our clothes off to have a good time.
16
16
  We could dance & party all night And drink some cherry wine.
17
17
  -- Jermaine Stewart }
18
- output.puts text
19
- text
18
+ output.puts txt
19
+ txt
20
20
  end
21
21
 
22
22
  command "east-coker", "" do
23
- text = %{
23
+ txt = %{
24
24
  --
25
25
  Now the light falls
26
26
  Across the open field, leaving the deep lane
@@ -34,12 +34,12 @@ class Pry
34
34
  Wait for the early owl.
35
35
  -- T.S Eliot
36
36
  }
37
- output.puts text
38
- text
37
+ output.puts txt
38
+ txt
39
39
  end
40
40
 
41
41
  command "cohen-poem", "" do
42
- text = %{
42
+ txt = %{
43
43
  --
44
44
  When this American woman,
45
45
  whose thighs are bound in casual red cloth,
@@ -57,8 +57,8 @@ class Pry
57
57
  they are lost for hours.
58
58
  -- Leonard Cohen
59
59
  }
60
- output.puts text
61
- text
60
+ output.puts txt
61
+ txt
62
62
  end
63
63
 
64
64
  command "pessoa-poem", "" do
@@ -46,7 +46,7 @@ class Pry
46
46
  # code defined in pry, eval'd within pry.
47
47
  repl_edit
48
48
  elsif runtime_patch?
49
- # patch code without persisting changes
49
+ # patch code without persisting changes, implies future changes are patches
50
50
  apply_runtime_patch
51
51
  else
52
52
  # code stored in actual files, eval'd at top-level
@@ -72,7 +72,7 @@ class Pry
72
72
  end
73
73
 
74
74
  def runtime_patch?
75
- !file_based_exception? && (opts.present?(:patch) || pry_method?(code_object))
75
+ !file_based_exception? && (opts.present?(:patch) || previously_patched?(code_object) || pry_method?(code_object))
76
76
  end
77
77
 
78
78
  def apply_runtime_patch
@@ -140,6 +140,10 @@ class Pry
140
140
  code_object.pry_method?
141
141
  end
142
142
 
143
+ def previously_patched?(code_object)
144
+ code_object.is_a?(Pry::Method) && Pry::Method::Patcher.code_for(code_object.source_location.first)
145
+ end
146
+
143
147
  def patch_exception?
144
148
  opts.present?(:ex) && opts.present?(:patch)
145
149
  end