pry 0.10.4 → 0.11.0

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -18
  3. data/LICENSE +1 -1
  4. data/README.md +32 -31
  5. data/bin/pry +3 -7
  6. data/lib/pry/basic_object.rb +6 -0
  7. data/lib/pry/cli.rb +39 -34
  8. data/lib/pry/code/code_file.rb +8 -2
  9. data/lib/pry/code.rb +6 -1
  10. data/lib/pry/code_object.rb +23 -0
  11. data/lib/pry/color_printer.rb +20 -11
  12. data/lib/pry/command.rb +40 -16
  13. data/lib/pry/command_set.rb +9 -2
  14. data/lib/pry/commands/cat/exception_formatter.rb +11 -10
  15. data/lib/pry/commands/cat/file_formatter.rb +7 -3
  16. data/lib/pry/commands/code_collector.rb +16 -14
  17. data/lib/pry/commands/easter_eggs.rb +9 -9
  18. data/lib/pry/commands/edit/file_and_line_locator.rb +1 -1
  19. data/lib/pry/commands/edit.rb +7 -3
  20. data/lib/pry/commands/find_method.rb +1 -1
  21. data/lib/pry/commands/gem_open.rb +1 -1
  22. data/lib/pry/commands/gem_readme.rb +25 -0
  23. data/lib/pry/commands/gem_search.rb +40 -0
  24. data/lib/pry/commands/hist.rb +2 -2
  25. data/lib/pry/commands/jump_to.rb +7 -7
  26. data/lib/pry/commands/ls/constants.rb +12 -1
  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/ls.rb +3 -1
  31. data/lib/pry/commands/play.rb +2 -2
  32. data/lib/pry/commands/reload_code.rb +2 -2
  33. data/lib/pry/commands/ri.rb +4 -0
  34. data/lib/pry/commands/shell_command.rb +34 -8
  35. data/lib/pry/commands/show_info.rb +10 -2
  36. data/lib/pry/commands/watch_expression/expression.rb +1 -1
  37. data/lib/pry/commands/whereami.rb +7 -6
  38. data/lib/pry/config/behavior.rb +140 -49
  39. data/lib/pry/config/default.rb +21 -33
  40. data/lib/pry/config/memoization.rb +44 -0
  41. data/lib/pry/config.rb +3 -16
  42. data/lib/pry/core_extensions.rb +12 -2
  43. data/lib/pry/editor.rb +1 -1
  44. data/lib/pry/exceptions.rb +1 -1
  45. data/lib/pry/forwardable.rb +23 -0
  46. data/lib/pry/helpers/base_helpers.rb +6 -10
  47. data/lib/pry/helpers/documentation_helpers.rb +1 -0
  48. data/lib/pry/helpers/options_helpers.rb +1 -1
  49. data/lib/pry/helpers/text.rb +69 -75
  50. data/lib/pry/history.rb +22 -1
  51. data/lib/pry/history_array.rb +1 -1
  52. data/lib/pry/hooks.rb +48 -107
  53. data/lib/pry/indent.rb +6 -2
  54. data/lib/pry/input_completer.rb +138 -120
  55. data/lib/pry/last_exception.rb +2 -2
  56. data/lib/pry/method/disowned.rb +1 -0
  57. data/lib/pry/method/patcher.rb +0 -3
  58. data/lib/pry/method.rb +15 -15
  59. data/lib/pry/output.rb +37 -38
  60. data/lib/pry/pager.rb +11 -8
  61. data/lib/pry/plugins.rb +20 -5
  62. data/lib/pry/pry_class.rb +30 -4
  63. data/lib/pry/pry_instance.rb +8 -6
  64. data/lib/pry/repl.rb +38 -8
  65. data/lib/pry/repl_file_loader.rb +1 -1
  66. data/lib/pry/rubygem.rb +3 -1
  67. data/lib/pry/slop/LICENSE +20 -0
  68. data/lib/pry/slop/commands.rb +196 -0
  69. data/lib/pry/slop/option.rb +208 -0
  70. data/lib/pry/slop.rb +661 -0
  71. data/lib/pry/terminal.rb +16 -5
  72. data/lib/pry/test/helper.rb +12 -3
  73. data/lib/pry/version.rb +1 -1
  74. data/lib/pry/{module_candidate.rb → wrapped_module/candidate.rb} +7 -13
  75. data/lib/pry/wrapped_module.rb +7 -7
  76. data/lib/pry.rb +4 -4
  77. metadata +14 -19
@@ -106,137 +106,155 @@ class Pry::InputCompleter
106
106
  begin
107
107
  context = target.eval("self")
108
108
  context = context.class unless context.respond_to? :constants
109
- candidates = context.constants.collect(&:to_s)
110
- rescue
111
- candidates = []
112
- end
113
- candidates = candidates.grep(/^#{message}/).collect(&path)
114
- when CONSTANT_OR_METHOD_REGEXP # Constant or class methods
115
- receiver = $1
116
- message = Regexp.quote($2)
117
- begin
118
- candidates = eval("#{receiver}.constants.collect(&:to_s)", bind)
119
- candidates |= eval("#{receiver}.methods.collect(&:to_s)", bind)
120
- rescue Pry::RescuableException
121
- candidates = []
122
- end
123
- candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
124
- when SYMBOL_METHOD_CALL_REGEXP # method call on a Symbol
125
- receiver = $1
126
- message = Regexp.quote($2)
127
- candidates = Symbol.instance_methods.collect(&:to_s)
128
- select_message(path, receiver, message, candidates)
129
- when NUMERIC_REGEXP
130
- # Numeric
131
- receiver = $1
132
- message = Regexp.quote($5)
133
- begin
134
- candidates = eval(receiver, bind).methods.collect(&:to_s)
135
- rescue Pry::RescuableException
136
- candidates = []
137
- end
138
- select_message(path, receiver, message, candidates)
139
- when HEX_REGEXP
140
- # Numeric(0xFFFF)
141
- receiver = $1
142
- message = Regexp.quote($2)
109
+ candidates = context.constants.collect(&:to_s)
110
+ rescue
111
+ candidates = []
112
+ end
113
+ candidates = candidates.grep(/^#{message}/).collect(&path)
114
+ when CONSTANT_OR_METHOD_REGEXP # Constant or class methods
115
+ receiver = $1
116
+ message = Regexp.quote($2)
117
+ begin
118
+ candidates = eval("#{receiver}.constants.collect(&:to_s)", bind)
119
+ candidates |= eval("#{receiver}.methods.collect(&:to_s)", bind)
120
+ rescue Pry::RescuableException
121
+ candidates = []
122
+ end
123
+ candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
124
+ when SYMBOL_METHOD_CALL_REGEXP # method call on a Symbol
125
+ receiver = $1
126
+ message = Regexp.quote($2)
127
+ candidates = Symbol.instance_methods.collect(&:to_s)
128
+ select_message(path, receiver, message, candidates)
129
+ when NUMERIC_REGEXP
130
+ # Numeric
131
+ receiver = $1
132
+ message = Regexp.quote($5)
133
+ begin
134
+ candidates = eval(receiver, bind).methods.collect(&:to_s)
135
+ rescue Pry::RescuableException
136
+ candidates = []
137
+ end
138
+ select_message(path, receiver, message, candidates)
139
+ when HEX_REGEXP
140
+ # Numeric(0xFFFF)
141
+ receiver = $1
142
+ message = Regexp.quote($2)
143
+ begin
144
+ candidates = eval(receiver, bind).methods.collect(&:to_s)
145
+ rescue Pry::RescuableException
146
+ candidates = []
147
+ end
148
+ select_message(path, receiver, message, candidates)
149
+ when GLOBALVARIABLE_REGEXP # global
150
+ regmessage = Regexp.new(Regexp.quote($1))
151
+ candidates = global_variables.collect(&:to_s).grep(regmessage)
152
+ when VARIABLE_REGEXP # variable
153
+ receiver = $1
154
+ message = Regexp.quote($2)
155
+
156
+ gv = eval("global_variables", bind).collect(&:to_s)
157
+ lv = eval("local_variables", bind).collect(&:to_s)
158
+ cv = eval("self.class.constants", bind).collect(&:to_s)
159
+
160
+ if (gv | lv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
161
+ # foo.func and foo is local var. OR
162
+ # Foo::Bar.func
143
163
  begin
144
- candidates = eval(receiver, bind).methods.collect(&:to_s)
164
+ candidates = eval("#{receiver}.methods", bind).collect(&:to_s)
145
165
  rescue Pry::RescuableException
146
166
  candidates = []
147
167
  end
148
- select_message(path, receiver, message, candidates)
149
- when GLOBALVARIABLE_REGEXP # global
150
- regmessage = Regexp.new(Regexp.quote($1))
151
- candidates = global_variables.collect(&:to_s).grep(regmessage)
152
- when VARIABLE_REGEXP # variable
153
- receiver = $1
154
- message = Regexp.quote($2)
155
-
156
- gv = eval("global_variables", bind).collect(&:to_s)
157
- lv = eval("local_variables", bind).collect(&:to_s)
158
- cv = eval("self.class.constants", bind).collect(&:to_s)
159
-
160
- if (gv | lv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
161
- # foo.func and foo is local var. OR
162
- # Foo::Bar.func
163
- begin
164
- candidates = eval("#{receiver}.methods", bind).collect(&:to_s)
165
- rescue Pry::RescuableException
166
- candidates = []
167
- end
168
- else
169
- # func1.func2
170
- candidates = []
171
- ObjectSpace.each_object(Module){|m|
172
- begin
173
- name = m.name.to_s
174
- rescue Pry::RescuableException
175
- name = ""
176
- end
177
- next if name != "IRB::Context" and
178
- /^(IRB|SLex|RubyLex|RubyToken)/ =~ name
179
-
180
- # jruby doesn't always provide #instance_methods() on each
181
- # object.
182
- if m.respond_to?(:instance_methods)
183
- candidates.concat m.instance_methods(false).collect(&:to_s)
184
- end
185
- }
186
- candidates.sort!
187
- candidates.uniq!
188
- end
189
- select_message(path, receiver, message, candidates)
190
- when /^\.([^.]*)$/
191
- # Unknown(maybe String)
192
- receiver = ""
193
- message = Regexp.quote($1)
194
- candidates = String.instance_methods(true).collect(&:to_s)
195
- select_message(path, receiver, message, candidates)
196
168
  else
197
- candidates = eval(
198
- "methods | private_methods | local_variables | " \
199
- "self.class.constants | instance_variables",
200
- bind
201
- ).collect(&:to_s)
202
-
203
- if eval("respond_to?(:class_variables)", bind)
204
- candidates += eval("class_variables", bind).collect(&:to_s)
205
- end
206
- candidates = (candidates|ReservedWords|custom_completions).grep(/^#{Regexp.quote(input)}/)
207
- candidates.collect(&path)
169
+ # func1.func2
170
+ candidates = Set.new
171
+ to_ignore = ignored_modules
172
+ ObjectSpace.each_object(Module){|m|
173
+ next if (to_ignore.include?(m) rescue true)
174
+ # jruby doesn't always provide #instance_methods() on each
175
+ # object.
176
+ if m.respond_to?(:instance_methods)
177
+ candidates.merge m.instance_methods(false).collect(&:to_s)
178
+ end
179
+ }
180
+ end
181
+ select_message(path, receiver, message, candidates.sort)
182
+ when /^\.([^.]*)$/
183
+ # Unknown(maybe String)
184
+ receiver = ""
185
+ message = Regexp.quote($1)
186
+ candidates = String.instance_methods(true).collect(&:to_s)
187
+ select_message(path, receiver, message, candidates)
188
+ else
189
+ candidates = eval(
190
+ "methods | private_methods | local_variables | " \
191
+ "self.class.constants | instance_variables",
192
+ bind
193
+ ).collect(&:to_s)
194
+
195
+ if eval("respond_to?(:class_variables)", bind)
196
+ candidates += eval("class_variables", bind).collect(&:to_s)
208
197
  end
209
- rescue Pry::RescuableException
210
- []
198
+ candidates = (candidates|ReservedWords|custom_completions).grep(/^#{Regexp.quote(input)}/)
199
+ candidates.collect(&path)
211
200
  end
201
+ rescue Pry::RescuableException
202
+ []
212
203
  end
204
+ end
213
205
 
214
- def select_message(path, receiver, message, candidates)
215
- candidates.grep(/^#{message}/).collect { |e|
216
- case e
217
- when /^[a-zA-Z_]/
218
- path.call(receiver + "." << e)
219
- when /^[0-9]/
220
- when *Operators
221
- #receiver + " " << e
222
- end
223
- }.compact
206
+ def select_message(path, receiver, message, candidates)
207
+ candidates.grep(/^#{message}/).collect { |e|
208
+ case e
209
+ when /^[a-zA-Z_]/
210
+ path.call(receiver + "." << e)
211
+ when /^[0-9]/
212
+ when *Operators
213
+ #receiver + " " << e
214
+ end
215
+ }.compact
216
+ end
217
+
218
+ # build_path seperates the input into two parts: path and input.
219
+ # input is the partial string that should be completed
220
+ # path is a proc that takes an input and builds a full path.
221
+ def build_path(input)
222
+ # check to see if the input is a regex
223
+ return proc {|i| i.to_s }, input if input[/\/\./]
224
+ trailing_slash = input.end_with?('/')
225
+ contexts = input.chomp('/').split(/\//)
226
+ input = contexts[-1]
227
+ path = proc do |i|
228
+ p = contexts[0..-2].push(i).join('/')
229
+ p += '/' if trailing_slash && !i.nil?
230
+ p
224
231
  end
232
+ return path, input
233
+ end
234
+
235
+ def ignored_modules
236
+ # We could cache the result, but IRB is not loaded by default.
237
+ # And this is very fast anyway.
238
+ # By using this approach, we avoid Module#name calls, which are
239
+ # relatively slow when there are a lot of anonymous modules defined.
240
+ s = Set.new
225
241
 
226
- # build_path seperates the input into two parts: path and input.
227
- # input is the partial string that should be completed
228
- # path is a proc that takes an input and builds a full path.
229
- def build_path(input)
230
- # check to see if the input is a regex
231
- return proc {|i| i.to_s }, input if input[/\/\./]
232
- trailing_slash = input.end_with?('/')
233
- contexts = input.chomp('/').split(/\//)
234
- input = contexts[-1]
235
- path = proc do |i|
236
- p = contexts[0..-2].push(i).join('/')
237
- p += '/' if trailing_slash && !i.nil?
238
- p
242
+ scanner = lambda do |m|
243
+ next if s.include?(m) # IRB::ExtendCommandBundle::EXCB recurses.
244
+ s << m
245
+ m.constants(false).each do |c|
246
+ value = m.const_get(c)
247
+ scanner.call(value) if value.is_a?(Module)
239
248
  end
240
- return path, input
241
249
  end
250
+
251
+ # FIXME: Add Pry here as well?
252
+ [:IRB, :SLex, :RubyLex, :RubyToken].each do |module_name|
253
+ next unless Object.const_defined?(module_name)
254
+ scanner.call(Object.const_get(module_name))
255
+ end
256
+
257
+ s.delete(IRB::Context) if defined?(IRB::Context)
258
+ s
259
+ end
242
260
  end
@@ -23,8 +23,8 @@ class Pry::LastException < BasicObject
23
23
  end
24
24
  end
25
25
 
26
- def respond_to_missing?(name, include_private = false)
27
- @e.respond_to?(name)
26
+ def respond_to_missing?(name, include_all=false)
27
+ @e.respond_to?(name, include_all)
28
28
  end
29
29
 
30
30
  #
@@ -22,6 +22,7 @@ class Pry
22
22
  # @param [String] method_name
23
23
  def initialize(receiver, method_name, binding=nil)
24
24
  @receiver, @name = receiver, method_name
25
+ @method = nil
25
26
  end
26
27
 
27
28
  # Is the method undefined? (aka `Disowned`)
@@ -42,9 +42,6 @@ class Pry
42
42
  # transation we make that not happen, which means that alias_method_chains, etc.
43
43
  # continue to work.
44
44
  #
45
- # @param [String] meth_name The method name before aliasing
46
- # @param [Module] target The owner of the method
47
-
48
45
  def with_method_transaction
49
46
  temp_name = "__pry_#{method.original_name}__"
50
47
  method = self.method
data/lib/pry/method.rb CHANGED
@@ -140,11 +140,11 @@ class Pry
140
140
  # @param [Boolean] include_super Whether to include methods from ancestors.
141
141
  # @return [Array[Pry::Method]]
142
142
  def all_from_class(klass, include_super=true)
143
- %w(public protected private).map do |visibility|
143
+ %w(public protected private).flat_map do |visibility|
144
144
  safe_send(klass, :"#{visibility}_instance_methods", include_super).map do |method_name|
145
145
  new(safe_send(klass, :instance_method, method_name), :visibility => visibility.to_sym)
146
146
  end
147
- end.flatten(1)
147
+ end
148
148
  end
149
149
 
150
150
  #
@@ -163,7 +163,7 @@ class Pry
163
163
 
164
164
  #
165
165
  # @deprecated
166
- # please use {#all_from_obj} instead.
166
+ # please use {all_from_obj} instead.
167
167
  # the `method_type` argument is ignored.
168
168
  #
169
169
  def all_from_common(obj, method_type = nil, include_super=true)
@@ -212,9 +212,9 @@ class Pry
212
212
  # the lowest copy will be returned.
213
213
  def singleton_class_resolution_order(klass)
214
214
  ancestors = Pry::Method.safe_send(klass, :ancestors)
215
- resolution_order = ancestors.grep(Class).map do |anc|
215
+ resolution_order = ancestors.grep(Class).flat_map do |anc|
216
216
  [singleton_class_of(anc), *singleton_class_of(anc).included_modules]
217
- end.flatten(1)
217
+ end
218
218
 
219
219
  resolution_order.reverse.uniq.reverse - Class.included_modules
220
220
  end
@@ -359,13 +359,13 @@ class Pry
359
359
  # Paraphrased from `awesome_print` gem.
360
360
  def signature
361
361
  if respond_to?(:parameters)
362
- args = parameters.inject([]) do |arr, (type, name)|
363
- name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
364
- arr << case type
365
- when :req then name.to_s
366
- when :opt then "#{name}=?"
367
- when :rest then "*#{name}"
368
- when :block then "&#{name}"
362
+ args = parameters.inject([]) do |arr, (typ, nam)|
363
+ nam ||= (typ == :block ? 'block' : "arg#{arr.size + 1}")
364
+ arr << case typ
365
+ when :req then nam.to_s
366
+ when :opt then "#{nam}=?"
367
+ when :rest then "*#{nam}"
368
+ when :block then "&#{nam}"
369
369
  else '?'
370
370
  end
371
371
  end
@@ -461,8 +461,8 @@ class Pry
461
461
 
462
462
  # @param [String, Symbol] method_name
463
463
  # @return [Boolean]
464
- def respond_to?(method_name)
465
- super or @method.respond_to?(method_name)
464
+ def respond_to?(method_name, include_all=false)
465
+ super or @method.respond_to?(method_name, include_all)
466
466
  end
467
467
 
468
468
  # Delegate any unknown calls to the wrapped method.
@@ -484,7 +484,7 @@ class Pry
484
484
  else
485
485
  fail_msg = "Cannot locate this method: #{name}."
486
486
  if mri?
487
- fail_msg += ' Try `gem-install pry-doc` to get access to Ruby Core documentation.'
487
+ fail_msg += " Invoke the 'gem-install pry-doc' Pry command to get access to Ruby Core documentation.\n"
488
488
  end
489
489
  raise CommandError, fail_msg
490
490
  end
data/lib/pry/output.rb CHANGED
@@ -1,50 +1,49 @@
1
- class Pry
2
- class Output
3
- attr_reader :_pry_
1
+ class Pry::Output
2
+ attr_reader :_pry_
4
3
 
5
- def initialize(_pry_)
6
- @_pry_ = _pry_
7
- end
8
-
9
- def puts(*objs)
10
- return print "\n" if objs.empty?
4
+ def initialize(_pry_)
5
+ @_pry_ = _pry_
6
+ @boxed_io = _pry_.config.output
7
+ end
11
8
 
12
- objs.each do |obj|
13
- if ary = Array.try_convert(obj)
14
- puts(*ary)
15
- else
16
- print "#{obj.to_s.chomp}\n"
17
- end
9
+ def puts(*objs)
10
+ return print "\n" if objs.empty?
11
+ objs.each do |obj|
12
+ if ary = Array.try_convert(obj)
13
+ puts(*ary)
14
+ else
15
+ print "#{obj.to_s.chomp}\n"
18
16
  end
19
-
20
- nil
21
17
  end
18
+ nil
19
+ end
22
20
 
23
- def print(*objs)
24
- objs.each do |obj|
25
- _pry_.config.output.print decolorize_maybe(obj.to_s)
26
- end
27
-
28
- nil
21
+ def print(*objs)
22
+ objs.each do |obj|
23
+ @boxed_io.print decolorize_maybe(obj.to_s)
29
24
  end
30
- alias << print
31
- alias write print
25
+ nil
26
+ end
27
+ alias << print
28
+ alias write print
32
29
 
33
- # If _pry_.config.color is currently false, removes ansi escapes from the string.
34
- def decolorize_maybe(str)
35
- if _pry_.config.color
36
- str
37
- else
38
- Helpers::Text.strip_color str
39
- end
40
- end
30
+ def tty?
31
+ @boxed_io.respond_to?(:tty?) and @boxed_io.tty?
32
+ end
41
33
 
42
- def method_missing(name, *args, &block)
43
- _pry_.config.output.send(name, *args, &block)
44
- end
34
+ def method_missing(name, *args, &block)
35
+ @boxed_io.__send__(name, *args, &block)
36
+ end
37
+
38
+ def respond_to_missing?(m, include_all=false)
39
+ @boxed_io.respond_to?(m, include_all)
40
+ end
45
41
 
46
- def respond_to_missing?(*a)
47
- _pry_.config.respond_to?(*a)
42
+ def decolorize_maybe(str)
43
+ if _pry_.config.color
44
+ str
45
+ else
46
+ Pry::Helpers::Text.strip_color str
48
47
  end
49
48
  end
50
49
  end
data/lib/pry/pager.rb CHANGED
@@ -14,11 +14,12 @@ class Pry::Pager
14
14
  end
15
15
 
16
16
  # Send the given text through the best available pager (if `Pry.config.pager` is
17
- # enabled).
18
- # If you want to send text through in chunks as you generate it, use `open` to
19
- # get a writable object instead.
20
- # @param [String] text A piece of text to run through a pager.
21
- # @param [IO] output (`$stdout`) An object to send output to.
17
+ # enabled). If you want to send text through in chunks as you generate it, use `open`
18
+ # to get a writable object instead.
19
+ #
20
+ # @param [String] text
21
+ # Text to run through a pager.
22
+ #
22
23
  def page(text)
23
24
  open do |pager|
24
25
  pager << text
@@ -27,7 +28,6 @@ class Pry::Pager
27
28
 
28
29
  # Yields a pager object (`NullPager`, `SimplePager`, or `SystemPager`). All
29
30
  # pagers accept output with `#puts`, `#print`, `#write`, and `#<<`.
30
- # @param [IO] output (`$stdout`) An object to send output to.
31
31
  def open
32
32
  pager = best_available
33
33
  yield pager
@@ -48,7 +48,6 @@ class Pry::Pager
48
48
  # `#print`, `#write`, and `#<<`. You must call `#close` when you're done
49
49
  # writing output to a pager, and you must rescue `Pry::Pager::StopPaging`.
50
50
  # These requirements can be avoided by using `.open` instead.
51
- # @param [#<<] output ($stdout) An object to send output to.
52
51
  def best_available
53
52
  if !_pry_.config.pager
54
53
  NullPager.new(_pry_.output)
@@ -139,7 +138,11 @@ class Pry::Pager
139
138
  if @system_pager.nil?
140
139
  @system_pager = begin
141
140
  pager_executable = default_pager.split(' ').first
142
- `which #{pager_executable}`
141
+ if Pry::Helpers::BaseHelpers.windows? || Pry::Helpers::BaseHelpers.windows_ansi?
142
+ `where #{pager_executable}`
143
+ else
144
+ `which #{pager_executable}`
145
+ end
143
146
  $?.success?
144
147
  rescue
145
148
  false
data/lib/pry/plugins.rb CHANGED
@@ -60,6 +60,16 @@ class Pry
60
60
 
61
61
  alias active? active
62
62
  alias enabled? enabled
63
+
64
+ def supported?
65
+ pry_version = Gem::Version.new(VERSION)
66
+ spec.dependencies.each do |dependency|
67
+ if dependency.name == "pry"
68
+ return dependency.requirement.satisfied_by?(pry_version)
69
+ end
70
+ end
71
+ true
72
+ end
63
73
  end
64
74
 
65
75
  def initialize
@@ -68,11 +78,11 @@ class Pry
68
78
 
69
79
  # Find all installed Pry plugins and store them in an internal array.
70
80
  def locate_plugins
71
- Gem.refresh
72
- (Gem::Specification.respond_to?(:each) ? Gem::Specification : Gem.source_index.find_name('')).each do |gem|
81
+ gem_list.each do |gem|
73
82
  next if gem.name !~ PRY_PLUGIN_PREFIX
74
83
  plugin_name = gem.name.split('-', 2).last
75
- @plugins << Plugin.new(plugin_name, gem.name, gem, true) if !gem_located?(gem.name)
84
+ plugin = Plugin.new(plugin_name, gem.name, gem, false)
85
+ @plugins << plugin.tap(&:enable!) if plugin.supported? && !plugin_located?(plugin)
76
86
  end
77
87
  @plugins
78
88
  end
@@ -95,8 +105,13 @@ class Pry
95
105
  end
96
106
 
97
107
  private
98
- def gem_located?(gem_name)
99
- @plugins.any? { |plugin| plugin.gem_name == gem_name }
108
+ def plugin_located?(plugin)
109
+ @plugins.any? { |existing| existing.gem_name == plugin.gem_name }
110
+ end
111
+
112
+ def gem_list
113
+ Gem.refresh
114
+ Gem::Specification.respond_to?(:each) ? Gem::Specification : Gem.source_index.find_name('')
100
115
  end
101
116
  end
102
117
 
data/lib/pry/pry_class.rb CHANGED
@@ -5,7 +5,7 @@ class Pry
5
5
  LOCAL_RC_FILE = "./.pryrc"
6
6
 
7
7
  class << self
8
- extend Forwardable
8
+ extend Pry::Forwardable
9
9
  attr_accessor :custom_completions
10
10
  attr_accessor :current_line
11
11
  attr_accessor :line_buffer
@@ -32,6 +32,21 @@ class Pry
32
32
  def history
33
33
  @history ||= History.new
34
34
  end
35
+
36
+ #
37
+ # @example
38
+ # Pry.configure do |config|
39
+ # config.eager_load! # optional
40
+ # config.input = # ..
41
+ # config.foo = 2
42
+ # end
43
+ #
44
+ # @yield [config]
45
+ # Yields a block with {Pry.config} as its argument.
46
+ #
47
+ def configure
48
+ yield config
49
+ end
35
50
  end
36
51
 
37
52
  #
@@ -81,7 +96,7 @@ class Pry
81
96
  expanded = Pathname.new(File.expand_path(file)).realpath.to_s
82
97
  # For rbx 1.9 mode [see rubinius issue #2165]
83
98
  File.exist?(expanded) ? expanded : nil
84
- rescue Errno::ENOENT
99
+ rescue Errno::ENOENT, Errno::EACCES
85
100
  nil
86
101
  end
87
102
 
@@ -124,6 +139,11 @@ you can add "Pry.config.windows_console_warning = false" to your .pryrc.
124
139
  # note these have to be loaded here rather than in pry_instance as
125
140
  # we only want them loaded once per entire Pry lifetime.
126
141
  load_rc_files
142
+ end
143
+
144
+ def self.final_session_setup
145
+ return if @session_finalized
146
+ @session_finalized = true
127
147
  load_plugins if Pry.config.should_load_plugins
128
148
  load_requires if Pry.config.should_load_requires
129
149
  load_history if Pry.config.history.should_load
@@ -141,6 +161,9 @@ you can add "Pry.config.windows_console_warning = false" to your .pryrc.
141
161
  # Pry.start(Object.new, :input => MyInput.new)
142
162
  def self.start(target=nil, options={})
143
163
  return if ENV['DISABLE_PRY']
164
+ if ENV['FAIL_PRY']
165
+ raise 'You have FAIL_PRY set to true, which results in Pry calls failing'
166
+ end
144
167
  options = options.to_hash
145
168
 
146
169
  if in_critical_section?
@@ -150,8 +173,8 @@ you can add "Pry.config.windows_console_warning = false" to your .pryrc.
150
173
  end
151
174
 
152
175
  options[:target] = Pry.binding_for(target || toplevel_binding)
153
- options[:hooks] = Pry::Hooks.from_hash options.delete(:hooks) if options.key?(:hooks)
154
176
  initial_session_setup
177
+ final_session_setup
155
178
 
156
179
  # Unless we were given a backtrace, save the current one
157
180
  if options[:backtrace].nil?
@@ -233,7 +256,7 @@ you can add "Pry.config.windows_console_warning = false" to your .pryrc.
233
256
  # @param [String] command_string The Pry command (including arguments,
234
257
  # if any).
235
258
  # @param [Hash] options Optional named parameters.
236
- # @return [Object] The return value of the Pry command.
259
+ # @return [nil]
237
260
  # @option options [Object, Binding] :target The object to run the
238
261
  # command under. Defaults to `TOPLEVEL_BINDING` (main).
239
262
  # @option options [Boolean] :show_output Whether to show command
@@ -258,6 +281,7 @@ you can add "Pry.config.windows_console_warning = false" to your .pryrc.
258
281
 
259
282
  pry = Pry.new(:output => output, :target => target, :commands => options[:commands])
260
283
  pry.eval command_string
284
+ nil
261
285
  end
262
286
 
263
287
  def self.default_editor_for_platform
@@ -306,6 +330,8 @@ Readline version #{Readline::VERSION} detected - will not auto_resize! correctly
306
330
  # Set all the configurable options back to their default values
307
331
  def self.reset_defaults
308
332
  @initial_session = true
333
+ @session_finalized = nil
334
+
309
335
  self.config = Pry::Config.new Pry::Config::Default.new
310
336
  self.cli = false
311
337
  self.current_line = 1