pry 0.9.11.4 → 0.9.12pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.travis.yml +2 -0
  2. data/Rakefile +4 -0
  3. data/lib/pry.rb +1 -1
  4. data/lib/pry/cli.rb +14 -8
  5. data/lib/pry/code.rb +3 -3
  6. data/lib/pry/command.rb +20 -5
  7. data/lib/pry/command_set.rb +3 -3
  8. data/lib/pry/commands.rb +1 -1
  9. data/lib/pry/commands/disabled_commands.rb +2 -0
  10. data/lib/pry/commands/ls.rb +1 -2
  11. data/lib/pry/commands/reload_code.rb +8 -1
  12. data/lib/pry/commands/show_info.rb +27 -4
  13. data/lib/pry/commands/show_source.rb +2 -1
  14. data/lib/pry/commands/whereami.rb +87 -19
  15. data/lib/pry/completion.rb +7 -4
  16. data/lib/pry/helpers/base_helpers.rb +5 -2
  17. data/lib/pry/helpers/command_helpers.rb +3 -1
  18. data/lib/pry/helpers/documentation_helpers.rb +18 -7
  19. data/lib/pry/helpers/table.rb +4 -4
  20. data/lib/pry/indent.rb +2 -7
  21. data/lib/pry/method.rb +89 -129
  22. data/lib/pry/method/disowned.rb +53 -0
  23. data/lib/pry/method/weird_method_locator.rb +186 -0
  24. data/lib/pry/module_candidate.rb +3 -3
  25. data/lib/pry/pager.rb +13 -11
  26. data/lib/pry/pry_class.rb +10 -3
  27. data/lib/pry/terminal.rb +73 -0
  28. data/lib/pry/version.rb +1 -1
  29. data/lib/pry/wrapped_module.rb +51 -1
  30. data/spec/command_helpers_spec.rb +21 -1
  31. data/spec/commands/ls_spec.rb +4 -0
  32. data/spec/commands/show_doc_spec.rb +28 -28
  33. data/spec/commands/show_source_spec.rb +70 -22
  34. data/spec/commands/whereami_spec.rb +60 -11
  35. data/spec/documentation_helper_spec.rb +73 -0
  36. data/spec/fixtures/whereami_helper.rb +6 -0
  37. data/spec/helpers/table_spec.rb +19 -0
  38. data/spec/method_spec.rb +24 -7
  39. metadata +13 -7
  40. data/lib/pry/commands/deprecated_commands.rb +0 -2
  41. data/lib/pry/terminal_info.rb +0 -48
@@ -2,6 +2,7 @@ rvm:
2
2
  - 1.8.7
3
3
  - 1.9.2
4
4
  - 1.9.3
5
+ - ruby-head
5
6
  - ree
6
7
  - rbx-18mode
7
8
  - rbx-19mode
@@ -17,3 +18,4 @@ notifications:
17
18
  branches:
18
19
  only:
19
20
  - master
21
+ - 0-9-11-stable
data/Rakefile CHANGED
@@ -119,6 +119,8 @@ task :gems => [:clean, :rmgems, 'ruby:gem', 'mswin32:gem', 'mingw32:gem', 'jruby
119
119
 
120
120
  desc "remove all platform gems"
121
121
  task :rmgems => ['ruby:clobber_package']
122
+ task :rm_gems => :rmgems
123
+ task :rm_pkgs => :rmgems
122
124
 
123
125
  desc "reinstall gem"
124
126
  task :reinstall => :gems do
@@ -126,6 +128,8 @@ task :reinstall => :gems do
126
128
  sh "gem install #{File.dirname(__FILE__)}/pkg/pry-#{Pry::VERSION}.gem"
127
129
  end
128
130
 
131
+ task :install => :reinstall
132
+
129
133
  desc "build and push latest gems"
130
134
  task :pushgems => :gems do
131
135
  chdir("#{File.dirname(__FILE__)}/pkg") do
data/lib/pry.rb CHANGED
@@ -266,6 +266,6 @@ require 'pry/pry_class'
266
266
  require 'pry/pry_instance'
267
267
  require 'pry/cli'
268
268
  require 'pry/pager'
269
- require 'pry/terminal_info'
269
+ require 'pry/terminal'
270
270
  require 'pry/editor'
271
271
  require 'pry/rubygem'
@@ -99,10 +99,10 @@ Pry::CLI.add_options do
99
99
  banner %{Usage: pry [OPTIONS]
100
100
  Start a Pry session.
101
101
  See: `https://github.com/pry` for more information.
102
- Copyright (c) 2011 John Mair (banisterfiend)
102
+ Copyright (c) 2013 John Mair (banisterfiend)
103
103
  --
104
104
  }
105
- on :e, :exec, "A line of code to execute in context before the session starts", :argument => true do |input|
105
+ on :e, :exec=, "A line of code to execute in context before the session starts" do |input|
106
106
  exec_string << input + "\n"
107
107
  end
108
108
 
@@ -123,12 +123,12 @@ Copyright (c) 2011 John Mair (banisterfiend)
123
123
  Pry.config.should_load_local_rc = false
124
124
  end
125
125
 
126
- on :s, "select-plugin", "Only load specified plugin (and no others).", :argument => true do |plugin_name|
126
+ on :s, "select-plugin=", "Only load specified plugin (and no others)." do |plugin_name|
127
127
  Pry.config.should_load_plugins = false
128
128
  Pry.plugins[plugin_name].activate!
129
129
  end
130
130
 
131
- on :d, "disable-plugin", "Disable a specific plugin.", :argument => true do |plugin_name|
131
+ on :d, "disable-plugin=", "Disable a specific plugin." do |plugin_name|
132
132
  Pry.plugins[plugin_name].disable!
133
133
  end
134
134
 
@@ -149,11 +149,11 @@ Copyright (c) 2011 John Mair (banisterfiend)
149
149
  Pry.config.prompt = Pry::SIMPLE_PROMPT
150
150
  end
151
151
 
152
- on :r, :require, "`require` a Ruby script at startup", :argument => true do |file|
152
+ on :r, :require=, "`require` a Ruby script at startup" do |file|
153
153
  Pry.config.requires << file
154
154
  end
155
155
 
156
- on :I, "Add a path to the $LOAD_PATH", :argument => true, :as => Array, :delimiter => ":" do |load_path|
156
+ on :I=, "Add a path to the $LOAD_PATH", :as => Array, :delimiter => ":" do |load_path|
157
157
  load_path.map! do |path|
158
158
  /\A\.\// =~ path ? path : File.expand_path(path)
159
159
  end
@@ -161,14 +161,20 @@ Copyright (c) 2011 John Mair (banisterfiend)
161
161
  $LOAD_PATH.unshift(*load_path)
162
162
  end
163
163
 
164
+ on "gem", "Shorthand for -I./lib -rgemname" do |load_path|
165
+ $LOAD_PATH.unshift("./lib")
166
+ Dir["./lib/*.rb"].each do |file|
167
+ Pry.config.requires << file
168
+ end
169
+ end
170
+
164
171
  on :v, :version, "Display the Pry version" do
165
172
  puts "Pry version #{Pry::VERSION} on Ruby #{RUBY_VERSION}"
166
173
  exit
167
174
  end
168
175
 
169
- on(:c, :context,
176
+ on(:c, :context=,
170
177
  "Start the session in the specified context. Equivalent to `context.pry` in a session.",
171
- :argument => true,
172
178
  :default => "Pry.toplevel_binding"
173
179
  )
174
180
  end.process_options do |opts|
@@ -84,12 +84,12 @@ class Pry
84
84
  # Attempt to extract the source code for module (or class) `mod`.
85
85
  #
86
86
  # @param [Module, Class] mod The module (or class) of interest.
87
- # @param [Integer, nil] start_line The line number to start on, or nil to
88
- # use the method's original line numbers.
89
87
  # @param [Integer] candidate_rank The module candidate (by rank)
90
88
  # to use (see `Pry::WrappedModule::Candidate` for more information).
89
+ # @param [Integer, nil] start_line The line number to start on, or nil to
90
+ # use the method's original line numbers.
91
91
  # @return [Code]
92
- def from_module(mod, start_line = nil, candidate_rank = 0)
92
+ def from_module(mod, candidate_rank = 0, start_line=nil)
93
93
  candidate = Pry::WrappedModule(mod).candidate(candidate_rank)
94
94
  start_line ||= candidate.line
95
95
  new(candidate.source, start_line, :ruby)
@@ -520,7 +520,7 @@ class Pry
520
520
  end
521
521
 
522
522
  def source
523
- Pry::WrappedModule(self).source
523
+ source_object.source
524
524
  end
525
525
 
526
526
  def doc
@@ -528,18 +528,33 @@ class Pry
528
528
  end
529
529
 
530
530
  def source_location
531
- Pry::WrappedModule(self).source_location
531
+ source_object.source_location
532
532
  end
533
533
 
534
534
  def source_file
535
- Pry::WrappedModule(self).source_file
535
+ source_object.source_file
536
536
  end
537
537
  alias_method :file, :source_file
538
538
 
539
539
  def source_line
540
- Pry::WrappedModule(self).source_line
540
+ source_object.source_line
541
541
  end
542
542
  alias_method :line, :source_line
543
+
544
+ private
545
+
546
+ # The object used to extract the source for the command.
547
+ #
548
+ # This should be a `Pry::Method(block)` for a command made with `create_command`
549
+ # and a `Pry::WrappedModule(self)` for a command that's a standard class.
550
+ # @return [Pry::WrappedModule, Pry::Method]
551
+ def source_object
552
+ @source_object ||= if name =~ /^[A-Z]/
553
+ Pry::WrappedModule(self)
554
+ else
555
+ Pry::Method(block)
556
+ end
557
+ end
543
558
  end
544
559
 
545
560
  attr_accessor :opts
@@ -573,7 +588,7 @@ class Pry
573
588
  # Return an instance of Slop that can parse either subcommands or the
574
589
  # options that this command accepts.
575
590
  def slop
576
- Slop.parse do |opt|
591
+ Slop.new do |opt|
577
592
  opt.banner(unindent(self.class.banner))
578
593
  subcommands(opt)
579
594
  options(opt)
@@ -263,13 +263,13 @@ class Pry
263
263
  commands.delete(cmd.match)
264
264
  end
265
265
 
266
- def deprecated_command(name_of_deprecated_command, deprecation_message, matcher=name_of_deprecated_command)
267
- create_command name_of_deprecated_command do
266
+ def disabled_command(name_of_disabled_command, message, matcher=name_of_disabled_command)
267
+ create_command name_of_disabled_command do
268
268
  match matcher
269
269
  description ""
270
270
 
271
271
  define_method(:process) do
272
- output.puts "DEPRECATED: #{deprecation_message}"
272
+ output.puts "DISABLED: #{message}"
273
273
  end
274
274
  end
275
275
  end
@@ -1,6 +1,6 @@
1
1
  # Default commands used by Pry.
2
2
  Pry::Commands = Pry::CommandSet.new
3
3
 
4
- Dir[File.expand_path('../commands/*.rb', __FILE__)].each do |file|
4
+ Dir[File.expand_path('../commands', __FILE__) + '/*.rb'].each do |file|
5
5
  require file
6
6
  end
@@ -0,0 +1,2 @@
1
+ Pry::Commands.disabled_command("edit-method", "Use `edit` instead.")
2
+ Pry::Commands.disabled_command("show-command", "Use show-source [command_name] instead.")
@@ -189,8 +189,7 @@ class Pry
189
189
  return unless opts.present?(:constants) || (!has_user_specified_any_options && interrogating_a_module?)
190
190
 
191
191
  mod = interrogating_a_module? ? object_to_interrogate : Object
192
- constants = mod.constants
193
- constants -= (mod.ancestors - [mod]).map(&:constants).flatten unless opts.present?(:verbose)
192
+ constants = WrappedModule.new(mod).constants(opts.present?(:verbose))
194
193
  output_section("constants", grep[format_constants(mod, constants)])
195
194
  end
196
195
 
@@ -6,6 +6,12 @@ class Pry
6
6
 
7
7
  banner <<-'BANNER'
8
8
  Reload the source file that contains the specified code object.
9
+
10
+ e.g reload-code MyClass#my_method #=> reload a method
11
+ reload-code MyClass #=> reload a class
12
+ reload-code my-command #=> reload a pry command
13
+ reload-code self #=> reload the 'current' object
14
+ reload-code #=> identical to reload-code self
9
15
  BANNER
10
16
 
11
17
  def process
@@ -27,7 +33,7 @@ class Pry
27
33
  end
28
34
 
29
35
  def check_for_reloadability(code_object)
30
- if !code_object
36
+ if !code_object || !code_object.source_file
31
37
  raise CommandError, "Cannot locate #{obj_name}!"
32
38
  elsif !File.exists?(code_object.source_file)
33
39
  raise CommandError, "Cannot reload #{obj_name} as it has no associated file on disk. File found was: #{code_object.source_file}"
@@ -36,4 +42,5 @@ class Pry
36
42
  end
37
43
 
38
44
  Pry::Commands.add_command(Pry::Command::ReloadCode)
45
+ Pry::Commands.alias_command 'reload-method', 'reload-code'
39
46
  end
@@ -13,28 +13,47 @@ class Pry
13
13
  opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors", :as => :count
14
14
  opt.on :l, "line-numbers", "Show line numbers"
15
15
  opt.on :b, "base-one", "Show line numbers but start numbering at 1 (useful for `amend-line` and `play` commands)"
16
- opt.on :f, :flood, "Do not use a pager to view text longer than one screen"
17
16
  opt.on :a, :all, "Show all definitions and monkeypatches of the module/class"
18
17
  end
19
18
 
20
19
  def process
21
20
  code_object = Pry::CodeObject.lookup(obj_name, _pry_, :super => opts[:super])
22
- raise Pry::CommandError, "Couldn't locate #{obj_name}!" if !code_object
21
+ cannot_locate_source_error if !code_object
23
22
 
24
23
  if show_all_modules?(code_object)
25
24
  # show all monkey patches for a module
25
+
26
26
  result = content_and_headers_for_all_module_candidates(code_object)
27
27
  else
28
28
  # show a specific code object
29
- result = content_and_header_for_code_object(code_object)
29
+
30
+ co = code_object_with_accessible_source(code_object)
31
+ result = content_and_header_for_code_object(co)
30
32
  end
31
33
 
32
34
  set_file_and_dir_locals(code_object.source_file)
33
35
  stagger_output result
34
36
  end
35
37
 
38
+ # This method checks whether the `code_object` is a WrappedModule,
39
+ # if it is, then it returns the first candidate (monkeypatch) with
40
+ # accessible source (or docs). If `code_object` is not a WrappedModule (i.e a
41
+ # method or a command) then the `code_object` itself is just
42
+ # returned.
43
+ #
44
+ # @return [Pry::WrappedModule, Pry::Method, Pry::Command]
45
+ def code_object_with_accessible_source(code_object)
46
+ if code_object.is_a?(WrappedModule)
47
+ code_object.candidates.find(&:source).tap do |candidate|
48
+ cannot_locate_source_error if !candidate
49
+ end
50
+ else
51
+ code_object
52
+ end
53
+ end
54
+
36
55
  def content_and_header_for_code_object(code_object)
37
- header(code_object) << content_for(code_object)
56
+ header(code_object) + content_for(code_object)
38
57
  end
39
58
 
40
59
  def content_and_headers_for_all_module_candidates(mod)
@@ -54,6 +73,10 @@ class Pry
54
73
  result
55
74
  end
56
75
 
76
+ def cannot_locate_source_error
77
+ raise CommandError, "Couldn't locate a definition for #{obj_name}!"
78
+ end
79
+
57
80
  # Generate a header (meta-data information) for all the code
58
81
  # object types: methods, modules, commands, procs...
59
82
  def header(code_object)
@@ -25,7 +25,8 @@ class Pry
25
25
 
26
26
  # The source for code_object prepared for display.
27
27
  def content_for(code_object)
28
- raise CommandError, "Cannot locate source!" if !code_object.source
28
+ cannot_locate_source_error if !code_object.source
29
+
29
30
  Code.new(code_object.source, start_line_for(code_object)).
30
31
  with_line_numbers(use_line_numbers?).to_s
31
32
  end
@@ -1,16 +1,23 @@
1
1
  class Pry
2
2
  class Command::Whereami < Pry::ClassCommand
3
+
4
+ class << self
5
+ attr_accessor :method_size_cutoff
6
+ end
7
+
8
+ @method_size_cutoff = 30
9
+
3
10
  match 'whereami'
4
11
  description 'Show code surrounding the current context.'
5
12
  group 'Context'
6
13
 
7
14
  banner <<-'BANNER'
8
- Usage: whereami [-qn] [N]
15
+ Usage: whereami [-qn] [LINES]
9
16
 
10
17
  Describe the current location. If you use `binding.pry` inside a method then
11
18
  whereami will print out the source for that method.
12
19
 
13
- If a number is passed, then N lines before and after the current line will be
20
+ If a number is passed, then LINES lines before and after the current line will be
14
21
  shown instead of the method itself.
15
22
 
16
23
  The `-q` flag can be used to suppress error messages in the case that there's
@@ -25,29 +32,53 @@ class Pry
25
32
  BANNER
26
33
 
27
34
  def setup
28
- @method = Pry::Method.from_binding(target)
29
- @file = target.eval('__FILE__')
35
+ @file = expand_path(target.eval('__FILE__'))
30
36
  @line = target.eval('__LINE__')
37
+ @method = Pry::Method.from_binding(target)
31
38
  end
32
39
 
33
40
  def options(opt)
34
41
  opt.on :q, :quiet, "Don't display anything in case of an error"
35
42
  opt.on :n, :"no-line-numbers", "Do not display line numbers"
43
+ opt.on :m, :"method", "Show the complete source for the current method."
44
+ opt.on :c, :"class", "Show the complete source for the current class or module."
45
+ opt.on :f, :"file", "Show the complete source for the current file."
36
46
  end
37
47
 
38
48
  def code
39
- @code ||= if show_method?
40
- Pry::Code.from_method(@method)
49
+ @code ||= if opts.present?(:m)
50
+ method_code or raise CommandError, "Cannot find method code."
51
+ elsif opts.present?(:c)
52
+ class_code or raise CommandError, "Cannot find class code."
53
+ elsif opts.present?(:f)
54
+ Pry::Code.from_file(@file)
55
+ elsif args.any?
56
+ code_window
41
57
  else
42
- Pry::Code.from_file(@file).around(@line, window_size)
58
+ default_code
43
59
  end
44
60
  end
45
61
 
62
+ def code?
63
+ !!code
64
+ rescue MethodSource::SourceNotFoundError
65
+ false
66
+ end
67
+
68
+ def bad_option_combination?
69
+ [opts.present?(:m), opts.present?(:f),
70
+ opts.present?(:c), args.any?].count(true) > 1
71
+ end
72
+
46
73
  def location
47
74
  "#{@file} @ line #{@line} #{@method && @method.name_with_owner}"
48
75
  end
49
76
 
50
77
  def process
78
+ if bad_option_combination?
79
+ raise CommandError, "Only one of -m, -c, -f, and LINES may be specified."
80
+ end
81
+
51
82
  if nothing_to_do?
52
83
  return
53
84
  elsif internal_binding?(target)
@@ -57,9 +88,10 @@ class Pry
57
88
 
58
89
  set_file_and_dir_locals(@file)
59
90
 
60
- output.puts "\n#{text.bold('From:')} #{location}:\n\n"
61
- output.puts code.with_line_numbers(use_line_numbers?).with_marker(marker)
62
- output.puts
91
+ out = "\n#{text.bold('From:')} #{location}:\n\n" +
92
+ code.with_line_numbers(use_line_numbers?).with_marker(marker).to_s + "\n"
93
+
94
+ stagger_output(out)
63
95
  end
64
96
 
65
97
  private
@@ -88,17 +120,53 @@ class Pry
88
120
  end
89
121
  end
90
122
 
91
- def show_method?
92
- args.empty? && @method && @method.source? && @method.source_range.count < 20 &&
93
- # These checks are needed in case of an eval with a binding and file/line
94
- # numbers set to outside the function. As in rails' use of ERB.
95
- @method.source_file == @file && @method.source_range.include?(@line)
123
+ def small_method?
124
+ @method.source_range.count < self.class.method_size_cutoff
96
125
  end
97
126
 
98
- def code?
99
- !!code
100
- rescue MethodSource::SourceNotFoundError
101
- false
127
+ def default_code
128
+ if method_code && small_method?
129
+ method_code
130
+ else
131
+ code_window
132
+ end
133
+ end
134
+
135
+ def code_window
136
+ Pry::Code.from_file(@file).around(@line, window_size)
137
+ end
138
+
139
+ def method_code
140
+ return @method_code if @method_code
141
+
142
+ if valid_method?
143
+ @method_code = Pry::Code.from_method(@method)
144
+ end
145
+ end
146
+
147
+ def class_code
148
+ return @class_code if @class_code
149
+
150
+ if valid_method?
151
+ mod = Pry::WrappedModule(@method.owner)
152
+ idx = mod.candidates.find_index { |v| expand_path(v.source_file) == @file }
153
+ @class_code = idx && Pry::Code.from_module(mod, idx)
154
+ end
155
+ end
156
+
157
+ def valid_method?
158
+ @method && @method.source? && expand_path(@method.source_file) == @file &&
159
+ @method.source_range.include?(@line)
160
+ end
161
+
162
+ def expand_path(f)
163
+ return if !f
164
+
165
+ if Pry.eval_path == f
166
+ f
167
+ else
168
+ File.expand_path(f)
169
+ end
102
170
  end
103
171
 
104
172
  def window_size