pry 0.10.3 → 0.14.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +439 -16
  3. data/LICENSE +1 -1
  4. data/README.md +362 -302
  5. data/bin/pry +4 -7
  6. data/lib/pry/basic_object.rb +10 -0
  7. data/lib/pry/block_command.rb +22 -0
  8. data/lib/pry/class_command.rb +194 -0
  9. data/lib/pry/cli.rb +84 -97
  10. data/lib/pry/code/code_file.rb +37 -26
  11. data/lib/pry/code/code_range.rb +7 -5
  12. data/lib/pry/code/loc.rb +26 -13
  13. data/lib/pry/code.rb +42 -31
  14. data/lib/pry/code_object.rb +53 -28
  15. data/lib/pry/color_printer.rb +46 -35
  16. data/lib/pry/command.rb +197 -369
  17. data/lib/pry/command_set.rb +89 -114
  18. data/lib/pry/command_state.rb +31 -0
  19. data/lib/pry/commands/amend_line.rb +86 -82
  20. data/lib/pry/commands/bang.rb +18 -14
  21. data/lib/pry/commands/bang_pry.rb +15 -11
  22. data/lib/pry/commands/cat/abstract_formatter.rb +23 -18
  23. data/lib/pry/commands/cat/exception_formatter.rb +85 -72
  24. data/lib/pry/commands/cat/file_formatter.rb +56 -46
  25. data/lib/pry/commands/cat/input_expression_formatter.rb +35 -30
  26. data/lib/pry/commands/cat.rb +62 -54
  27. data/lib/pry/commands/cd.rb +40 -35
  28. data/lib/pry/commands/change_inspector.rb +29 -22
  29. data/lib/pry/commands/change_prompt.rb +48 -23
  30. data/lib/pry/commands/clear_screen.rb +20 -0
  31. data/lib/pry/commands/code_collector.rb +148 -131
  32. data/lib/pry/commands/disable_pry.rb +23 -19
  33. data/lib/pry/commands/easter_eggs.rb +23 -34
  34. data/lib/pry/commands/edit/exception_patcher.rb +21 -17
  35. data/lib/pry/commands/edit/file_and_line_locator.rb +34 -23
  36. data/lib/pry/commands/edit.rb +185 -157
  37. data/lib/pry/commands/exit.rb +40 -35
  38. data/lib/pry/commands/exit_all.rb +24 -20
  39. data/lib/pry/commands/exit_program.rb +20 -16
  40. data/lib/pry/commands/find_method.rb +168 -162
  41. data/lib/pry/commands/fix_indent.rb +16 -12
  42. data/lib/pry/commands/help.rb +140 -133
  43. data/lib/pry/commands/hist.rb +151 -149
  44. data/lib/pry/commands/import_set.rb +20 -15
  45. data/lib/pry/commands/jump_to.rb +25 -21
  46. data/lib/pry/commands/list_inspectors.rb +35 -28
  47. data/lib/pry/commands/ls/constants.rb +59 -31
  48. data/lib/pry/commands/ls/formatter.rb +42 -36
  49. data/lib/pry/commands/ls/globals.rb +38 -36
  50. data/lib/pry/commands/ls/grep.rb +17 -15
  51. data/lib/pry/commands/ls/instance_vars.rb +29 -28
  52. data/lib/pry/commands/ls/interrogatable.rb +18 -12
  53. data/lib/pry/commands/ls/jruby_hacks.rb +47 -41
  54. data/lib/pry/commands/ls/local_names.rb +26 -24
  55. data/lib/pry/commands/ls/local_vars.rb +38 -30
  56. data/lib/pry/commands/ls/ls_entity.rb +47 -52
  57. data/lib/pry/commands/ls/methods.rb +49 -51
  58. data/lib/pry/commands/ls/methods_helper.rb +46 -42
  59. data/lib/pry/commands/ls/self_methods.rb +23 -21
  60. data/lib/pry/commands/ls.rb +124 -103
  61. data/lib/pry/commands/nesting.rb +21 -17
  62. data/lib/pry/commands/play.rb +92 -82
  63. data/lib/pry/commands/pry_backtrace.rb +22 -17
  64. data/lib/pry/commands/pry_version.rb +15 -11
  65. data/lib/pry/commands/raise_up.rb +33 -27
  66. data/lib/pry/commands/reload_code.rb +60 -48
  67. data/lib/pry/commands/reset.rb +16 -12
  68. data/lib/pry/commands/ri.rb +57 -42
  69. data/lib/pry/commands/save_file.rb +45 -43
  70. data/lib/pry/commands/shell_command.rb +56 -29
  71. data/lib/pry/commands/shell_mode.rb +22 -18
  72. data/lib/pry/commands/show_doc.rb +80 -70
  73. data/lib/pry/commands/show_info.rb +194 -155
  74. data/lib/pry/commands/show_input.rb +16 -11
  75. data/lib/pry/commands/show_source.rb +110 -42
  76. data/lib/pry/commands/stat.rb +35 -31
  77. data/lib/pry/commands/switch_to.rb +21 -15
  78. data/lib/pry/commands/toggle_color.rb +20 -16
  79. data/lib/pry/commands/watch_expression/expression.rb +32 -27
  80. data/lib/pry/commands/watch_expression.rb +89 -84
  81. data/lib/pry/commands/whereami.rb +156 -141
  82. data/lib/pry/commands/wtf.rb +78 -40
  83. data/lib/pry/config/attributable.rb +22 -0
  84. data/lib/pry/config/lazy_value.rb +29 -0
  85. data/lib/pry/config/memoized_value.rb +34 -0
  86. data/lib/pry/config/value.rb +24 -0
  87. data/lib/pry/config.rb +310 -20
  88. data/lib/pry/control_d_handler.rb +28 -0
  89. data/lib/pry/core_extensions.rb +22 -9
  90. data/lib/pry/editor.rb +56 -34
  91. data/lib/pry/env.rb +18 -0
  92. data/lib/pry/exception_handler.rb +43 -0
  93. data/lib/pry/exceptions.rb +13 -18
  94. data/lib/pry/forwardable.rb +27 -0
  95. data/lib/pry/helpers/base_helpers.rb +20 -62
  96. data/lib/pry/helpers/command_helpers.rb +52 -62
  97. data/lib/pry/helpers/documentation_helpers.rb +21 -12
  98. data/lib/pry/helpers/options_helpers.rb +15 -8
  99. data/lib/pry/helpers/platform.rb +55 -0
  100. data/lib/pry/helpers/table.rb +44 -32
  101. data/lib/pry/helpers/text.rb +96 -85
  102. data/lib/pry/helpers.rb +3 -0
  103. data/lib/pry/history.rb +81 -55
  104. data/lib/pry/hooks.rb +60 -110
  105. data/lib/pry/indent.rb +74 -68
  106. data/lib/pry/input_completer.rb +199 -158
  107. data/lib/pry/input_lock.rb +7 -10
  108. data/lib/pry/inspector.rb +36 -24
  109. data/lib/pry/last_exception.rb +45 -45
  110. data/lib/pry/method/disowned.rb +19 -5
  111. data/lib/pry/method/patcher.rb +14 -8
  112. data/lib/pry/method/weird_method_locator.rb +79 -45
  113. data/lib/pry/method.rb +178 -124
  114. data/lib/pry/object_path.rb +37 -28
  115. data/lib/pry/output.rb +102 -16
  116. data/lib/pry/pager.rb +187 -174
  117. data/lib/pry/prompt.rb +213 -25
  118. data/lib/pry/pry_class.rb +119 -98
  119. data/lib/pry/pry_instance.rb +261 -224
  120. data/lib/pry/repl.rb +83 -29
  121. data/lib/pry/repl_file_loader.rb +27 -22
  122. data/lib/pry/ring.rb +89 -0
  123. data/lib/pry/slop/LICENSE +20 -0
  124. data/lib/pry/slop/commands.rb +190 -0
  125. data/lib/pry/slop/option.rb +210 -0
  126. data/lib/pry/slop.rb +672 -0
  127. data/lib/pry/syntax_highlighter.rb +26 -0
  128. data/lib/pry/system_command_handler.rb +17 -0
  129. data/lib/pry/testable/evalable.rb +24 -0
  130. data/lib/pry/testable/mockable.rb +22 -0
  131. data/lib/pry/testable/pry_tester.rb +88 -0
  132. data/lib/pry/testable/utility.rb +34 -0
  133. data/lib/pry/testable/variables.rb +52 -0
  134. data/lib/pry/testable.rb +68 -0
  135. data/lib/pry/version.rb +3 -1
  136. data/lib/pry/warning.rb +20 -0
  137. data/lib/pry/{module_candidate.rb → wrapped_module/candidate.rb} +35 -32
  138. data/lib/pry/wrapped_module.rb +68 -63
  139. data/lib/pry.rb +133 -149
  140. metadata +58 -69
  141. data/lib/pry/commands/disabled_commands.rb +0 -2
  142. data/lib/pry/commands/gem_cd.rb +0 -26
  143. data/lib/pry/commands/gem_install.rb +0 -32
  144. data/lib/pry/commands/gem_list.rb +0 -33
  145. data/lib/pry/commands/gem_open.rb +0 -29
  146. data/lib/pry/commands/gist.rb +0 -101
  147. data/lib/pry/commands/install_command.rb +0 -53
  148. data/lib/pry/commands/list_prompts.rb +0 -35
  149. data/lib/pry/commands/simple_prompt.rb +0 -22
  150. data/lib/pry/commands.rb +0 -6
  151. data/lib/pry/config/behavior.rb +0 -139
  152. data/lib/pry/config/convenience.rb +0 -25
  153. data/lib/pry/config/default.rb +0 -161
  154. data/lib/pry/history_array.rb +0 -121
  155. data/lib/pry/plugins.rb +0 -103
  156. data/lib/pry/rbx_path.rb +0 -22
  157. data/lib/pry/rubygem.rb +0 -82
  158. data/lib/pry/terminal.rb +0 -79
  159. data/lib/pry/test/helper.rb +0 -170
data/lib/pry/command.rb CHANGED
@@ -1,20 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'delegate'
2
- require 'pry/helpers/documentation_helpers'
4
+ require 'shellwords'
3
5
 
4
6
  class Pry
5
-
6
7
  # The super-class of all commands, new commands should be created by calling
7
- # {Pry::CommandSet#command} which creates a BlockCommand or {Pry::CommandSet#create_command}
8
- # which creates a ClassCommand. Please don't use this class directly.
8
+ # {Pry::CommandSet#command} which creates a BlockCommand or
9
+ # {Pry::CommandSet#create_command} which creates a ClassCommand. Please don't
10
+ # use this class directly.
9
11
  class Command
10
12
  extend Helpers::DocumentationHelpers
11
13
  extend CodeObject::Helpers
12
14
 
15
+ include Pry::Helpers::BaseHelpers
16
+ include Pry::Helpers::CommandHelpers
17
+ include Pry::Helpers::Text
18
+
13
19
  # represents a void return value for a command
14
20
  VOID_VALUE = Object.new
15
21
 
16
22
  # give it a nice inspect
17
- def VOID_VALUE.inspect() "void" end
23
+ def VOID_VALUE.inspect
24
+ "void"
25
+ end
18
26
 
19
27
  # Properties of the command itself (as passed as arguments to
20
28
  # {CommandSet#command} or {CommandSet#create_command}).
@@ -24,7 +32,7 @@ class Pry
24
32
  attr_writer :command_options
25
33
  attr_writer :match
26
34
 
27
- def match(arg=nil)
35
+ def match(arg = nil)
28
36
  if arg
29
37
  @command_options ||= default_options(arg)
30
38
  @command_options[:listing] = arg.is_a?(String) ? arg : arg.inspect
@@ -34,25 +42,25 @@ class Pry
34
42
  end
35
43
 
36
44
  # Define or get the command's description
37
- def description(arg=nil)
45
+ def description(arg = nil)
38
46
  @description = arg if arg
39
47
  @description ||= nil
40
48
  end
41
49
 
42
50
  # Define or get the command's options
43
- def command_options(arg=nil)
51
+ def command_options(arg = nil)
44
52
  @command_options ||= default_options(match)
45
53
  @command_options.merge!(arg) if arg
46
54
  @command_options
47
55
  end
48
56
  # backward compatibility
49
- alias_method :options, :command_options
50
- alias_method :options=, :command_options=
57
+ alias options command_options
58
+ alias options= command_options=
51
59
 
52
60
  # Define or get the command's banner
53
- def banner(arg=nil)
61
+ def banner(arg = nil)
54
62
  @banner = arg if arg
55
- @banner || description
63
+ @banner ||= description
56
64
  end
57
65
 
58
66
  def block
@@ -68,45 +76,28 @@ class Pry
68
76
  new.help
69
77
  end
70
78
 
71
- def source_location
72
- block.source_location
73
- end
74
-
75
79
  def source_file
76
80
  Array(block.source_location).first
77
81
  end
78
- alias_method :file, :source_file
82
+ alias file source_file
79
83
 
80
84
  def source_line
81
85
  Array(block.source_location).last
82
86
  end
83
- alias_method :line, :source_line
87
+ alias line source_line
84
88
 
85
89
  def default_options(match)
86
90
  {
87
- :requires_gem => [],
88
- :keep_retval => false,
89
- :argument_required => false,
90
- :interpolate => true,
91
- :shellwords => true,
92
- :listing => (String === match ? match : match.inspect),
93
- :use_prefix => true,
94
- :takes_block => false
91
+ keep_retval: false,
92
+ argument_required: false,
93
+ interpolate: true,
94
+ shellwords: true,
95
+ listing: (match.is_a?(String) ? match : match.inspect),
96
+ use_prefix: true,
97
+ takes_block: false
95
98
  }
96
99
  end
97
- end
98
100
 
99
- # Make those properties accessible to instances
100
- def name; self.class.name; end
101
- def match; self.class.match; end
102
- def description; self.class.description; end
103
- def block; self.class.block; end
104
- def command_options; self.class.options; end
105
- def command_name; self.class.command_name; end
106
- def source; self.class.source; end
107
- def source_location; self.class.source_location; end
108
-
109
- class << self
110
101
  def name
111
102
  super.to_s == "" ? "#<class(Pry::Command #{match.inspect})>" : super
112
103
  end
@@ -116,7 +107,7 @@ class Pry
116
107
  end
117
108
 
118
109
  def command_name
119
- self.options[:listing]
110
+ options[:listing]
120
111
  end
121
112
 
122
113
  # Create a new command with the given properties.
@@ -161,25 +152,21 @@ class Pry
161
152
  # @return [Fixnum]
162
153
  def match_score(val)
163
154
  if command_regex =~ val
164
- Regexp.last_match.size > 1 ? Regexp.last_match.begin(1) : Regexp.last_match.end(0)
155
+ if Regexp.last_match.size > 1
156
+ Regexp.last_match.begin(1)
157
+ else
158
+ Regexp.last_match.end(0)
159
+ end
165
160
  else
166
161
  -1
167
162
  end
168
163
  end
169
164
 
170
- # Store hooks to be run before or after the command body.
171
- # @see {Pry::CommandSet#before_command}
172
- # @see {Pry::CommandSet#after_command}
173
- def hooks
174
- @hooks ||= {:before => [], :after => []}
175
- end
176
-
177
165
  def command_regex
178
- pr = Pry.respond_to?(:config) ? Pry.config.command_prefix : ""
179
- prefix = convert_to_regex(pr)
166
+ prefix = convert_to_regex(Pry.config.command_prefix)
180
167
  prefix = "(?:#{prefix})?" unless options[:use_prefix]
181
168
 
182
- /^#{prefix}#{convert_to_regex(match)}(?!\S)/
169
+ /\A#{prefix}#{convert_to_regex(match)}(?!\S)/
183
170
  end
184
171
 
185
172
  def convert_to_regex(obj)
@@ -195,22 +182,25 @@ class Pry
195
182
  # This is usually auto-generated from directory naming, but it can be
196
183
  # manually overridden if necessary.
197
184
  # Group should not be changed once it is initialized.
198
- def group(name=nil)
199
- @group ||= if name
200
- name
201
- else
202
- case Pry::Method(block).source_file
203
- when %r{/pry/.*_commands/(.*).rb}
204
- $1.capitalize.gsub(/_/, " ")
205
- when %r{(pry-\w+)-([\d\.]+([\w\.]+)?)}
206
- name, version = $1, $2
207
- "#{name.to_s} (v#{version.to_s})"
208
- when /pryrc/
209
- "~/.pryrc"
210
- else
211
- "(other)"
212
- end
213
- end
185
+ def group(name = nil)
186
+ @group ||= begin
187
+ name || case Pry::Method(block).source_file
188
+ when %r{/pry/.*_commands/(.*).rb}
189
+ Regexp.last_match(1).capitalize.tr('_', " ")
190
+ when /(pry-\w+)-([\d\.]+([\w\.]+)?)/
191
+ name = Regexp.last_match(1)
192
+ version = Regexp.last_match(2)
193
+ "#{name} (v#{version})"
194
+ when /pryrc/
195
+ "pryrc"
196
+ else
197
+ "(other)"
198
+ end
199
+ end
200
+ end
201
+
202
+ def state
203
+ Pry::CommandState.default.state_for(match)
214
204
  end
215
205
  end
216
206
 
@@ -223,7 +213,9 @@ class Pry
223
213
  attr_accessor :arg_string
224
214
  attr_accessor :context
225
215
  attr_accessor :command_set
226
- attr_accessor :_pry_
216
+ attr_accessor :hooks
217
+ attr_accessor :pry_instance
218
+ alias _pry_= pry_instance=
227
219
 
228
220
  # The block we pass *into* a command so long as `:takes_block` is
229
221
  # not equal to `false`
@@ -233,6 +225,47 @@ class Pry
233
225
  # end
234
226
  attr_accessor :command_block
235
227
 
228
+ # Instantiate a command, in preparation for calling it.
229
+ # @param [Hash] context The runtime context to use with this command.
230
+ def initialize(context = {})
231
+ self.context = context
232
+ self.target = context[:target]
233
+ self.output = context[:output]
234
+ self.eval_string = context[:eval_string]
235
+ self.command_set = context[:command_set]
236
+ self.hooks = context[:hooks]
237
+ self.pry_instance = context[:pry_instance]
238
+ end
239
+
240
+ # Make those properties accessible to instances
241
+ def name
242
+ self.class.name
243
+ end
244
+
245
+ def match
246
+ self.class.match
247
+ end
248
+
249
+ def description
250
+ self.class.description
251
+ end
252
+
253
+ def block
254
+ self.class.block
255
+ end
256
+
257
+ def command_options
258
+ self.class.options
259
+ end
260
+
261
+ def command_name
262
+ self.class.command_name
263
+ end
264
+
265
+ def source
266
+ self.class.source
267
+ end
268
+
236
269
  # Run a command from another command.
237
270
  # @param [String] command_string The string that invokes the command
238
271
  # @param [Array] args Further arguments to pass to the command
@@ -243,8 +276,8 @@ class Pry
243
276
  # @example
244
277
  # run "amend-line", "5", 'puts "hello world"'
245
278
  def run(command_string, *args)
246
- command_string = _pry_.config.command_prefix.to_s + command_string
247
- complete_string = "#{command_string} #{args.join(" ")}".rstrip
279
+ command_string = pry_instance.config.command_prefix.to_s + command_string
280
+ complete_string = "#{command_string} #{args.join(' ')}".rstrip
248
281
  command_set.process_line(complete_string, context)
249
282
  end
250
283
 
@@ -252,30 +285,19 @@ class Pry
252
285
  command_set.to_hash
253
286
  end
254
287
 
255
- def text
256
- Pry::Helpers::Text
257
- end
258
-
259
288
  def void
260
289
  VOID_VALUE
261
290
  end
262
291
 
263
- include Pry::Helpers::BaseHelpers
264
- include Pry::Helpers::CommandHelpers
265
-
266
- # Instantiate a command, in preparation for calling it.
267
- # @param [Hash] context The runtime context to use with this command.
268
- def initialize(context={})
269
- self.context = context
270
- self.target = context[:target]
271
- self.output = context[:output]
272
- self.eval_string = context[:eval_string]
273
- self.command_set = context[:command_set]
274
- self._pry_ = context[:pry_instance]
292
+ def _pry_
293
+ Pry::Warning.warn('_pry_ is deprecated, use pry_instance instead')
294
+ pry_instance
275
295
  end
276
296
 
277
297
  # @return [Object] The value of `self` inside the `target` binding.
278
- def target_self; target.eval('self'); end
298
+ def target_self
299
+ target.eval('self')
300
+ end
279
301
 
280
302
  # @return [Hash] Pry commands can store arbitrary state
281
303
  # here. This state persists between subsequent command invocations.
@@ -285,7 +307,7 @@ class Pry
285
307
  # state.my_state = "my state" # this will not conflict with any
286
308
  # # `state.my_state` used in another command.
287
309
  def state
288
- _pry_.command_state[match] ||= Pry::Config.from_hash({})
310
+ self.class.state
289
311
  end
290
312
 
291
313
  # Revaluate the string (str) and perform interpolation.
@@ -306,12 +328,15 @@ class Pry
306
328
  # the current scope.
307
329
  def check_for_command_collision(command_match, arg_string)
308
330
  collision_type = target.eval("defined?(#{command_match})")
309
- collision_type ||= 'local-variable' if arg_string.match(%r{\A\s*[-+*/%&|^]*=})
331
+ collision_type ||= 'local-variable' if arg_string =~ %r{\A\s*[-+*/%&|^]*=}
310
332
 
311
333
  if collision_type
312
- output.puts "#{text.bold('WARNING:')} Calling Pry command '#{command_match}', which conflicts with a #{collision_type}.\n\n"
334
+ output.puts(
335
+ "#{Helpers::Text.bold('WARNING:')} Calling Pry command '#{command_match}', " \
336
+ "which conflicts with a #{collision_type}.\n\n"
337
+ )
313
338
  end
314
- rescue Pry::RescuableException
339
+ rescue Pry::RescuableException # rubocop:disable Lint/HandleExceptions
315
340
  end
316
341
 
317
342
  # Extract necessary information from a line that Command.matches? this
@@ -329,12 +354,15 @@ class Pry
329
354
  # @param [String] val The line of input
330
355
  # @return [Array]
331
356
  def tokenize(val)
332
- val.replace(interpolate_string(val)) if command_options[:interpolate]
357
+ val = interpolate_string(val) if command_options[:interpolate]
333
358
 
334
359
  self.class.command_regex =~ val
335
360
 
336
361
  # please call Command.matches? before Command#call_safely
337
- raise CommandError, "fatal: called a command which didn't match?!" unless Regexp.last_match
362
+ unless Regexp.last_match
363
+ raise CommandError, "fatal: called a command which didn't match?!"
364
+ end
365
+
338
366
  captures = Regexp.last_match.captures
339
367
  pos = Regexp.last_match.end(0)
340
368
 
@@ -346,11 +374,16 @@ class Pry
346
374
  # process and pass a block if one is found
347
375
  pass_block(arg_string) if command_options[:takes_block]
348
376
 
349
- if arg_string
350
- args = command_options[:shellwords] ? Shellwords.shellwords(arg_string) : arg_string.split(" ")
351
- else
352
- args = []
353
- end
377
+ args =
378
+ if arg_string
379
+ if command_options[:shellwords]
380
+ Shellwords.shellwords(arg_string)
381
+ else
382
+ arg_string.split(" ")
383
+ end
384
+ else
385
+ []
386
+ end
354
387
 
355
388
  [val[0..pos].rstrip, arg_string, captures, args]
356
389
  end
@@ -361,7 +394,9 @@ class Pry
361
394
  def process_line(line)
362
395
  command_match, arg_string, captures, args = tokenize(line)
363
396
 
364
- check_for_command_collision(command_match, arg_string) if Pry.config.collision_warning
397
+ if Pry.config.collision_warning
398
+ check_for_command_collision(command_match, arg_string)
399
+ end
365
400
 
366
401
  self.arg_string = arg_string
367
402
  self.captures = captures
@@ -369,6 +404,43 @@ class Pry
369
404
  call_safely(*(captures + args))
370
405
  end
371
406
 
407
+ # Generate completions for this command
408
+ #
409
+ # @param [String] _search The line typed so far
410
+ # @return [Array<String>] Completion words
411
+ def complete(_search)
412
+ []
413
+ end
414
+
415
+ private
416
+
417
+ # Run the command with the given `args`.
418
+ #
419
+ # This is a public wrapper around `#call` which ensures all preconditions
420
+ # are met.
421
+ #
422
+ # @param [Array<String>] args The arguments to pass to this command.
423
+ # @return [Object] The return value of the `#call` method, or
424
+ # {Command::VOID_VALUE}.
425
+ def call_safely(*args)
426
+ if command_options[:argument_required] && args.empty?
427
+ raise CommandError, "The command '#{command_name}' requires an argument."
428
+ end
429
+
430
+ ret = use_unpatched_symbol do
431
+ call_with_hooks(*args)
432
+ end
433
+ command_options[:keep_retval] ? ret : void
434
+ end
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
+
372
444
  # Pass a block argument to a command.
373
445
  # @param [String] arg_string The arguments (as a string) passed to the command.
374
446
  # We inspect these for a '| do' or a '| {' and if we find it we use it
@@ -380,18 +452,19 @@ class Pry
380
452
  # Workaround for weird JRuby bug where rindex in this case can return nil
381
453
  # even when there's a match.
382
454
  arg_string.scan(/\| *(?:do|\{)/)
383
- block_index = $~ && $~.offset(0)[0]
455
+ block_index = $LAST_MATCH_INFO && $LAST_MATCH_INFO.offset(0)[0]
384
456
 
385
- return if !block_index
457
+ return unless block_index
386
458
 
387
459
  block_init_string = arg_string.slice!(block_index..-1)[1..-1]
388
460
  prime_string = "proc #{block_init_string}\n"
389
461
 
390
- if !Pry::Code.complete_expression?(prime_string)
391
- block_string = _pry_.r(target, prime_string)
392
- else
393
- block_string = prime_string
394
- end
462
+ block_string =
463
+ if !Pry::Code.complete_expression?(prime_string)
464
+ pry_instance.r(target, prime_string)
465
+ else
466
+ prime_string
467
+ end
395
468
 
396
469
  begin
397
470
  self.command_block = target.eval(block_string)
@@ -400,293 +473,48 @@ class Pry
400
473
  end
401
474
  end
402
475
 
403
- private :pass_block
404
-
405
- # Run the command with the given `args`.
406
- #
407
- # This is a public wrapper around `#call` which ensures all preconditions
408
- # are met.
409
- #
410
- # @param [Array<String>] args The arguments to pass to this command.
411
- # @return [Object] The return value of the `#call` method, or
412
- # {Command::VOID_VALUE}.
413
- def call_safely(*args)
414
- unless dependencies_met?
415
- gems_needed = Array(command_options[:requires_gem])
416
- gems_not_installed = gems_needed.select { |g| !Rubygem.installed?(g) }
417
- output.puts "\nThe command '#{command_name}' is #{text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
418
- output.puts "-"
419
- output.puts "Type `install-command #{command_name}` to install the required gems and activate this command."
420
- return void
421
- end
422
-
423
- if command_options[:argument_required] && args.empty?
424
- raise CommandError, "The command '#{command_name}' requires an argument."
425
- end
426
-
427
- ret = call_with_hooks(*args)
428
- command_options[:keep_retval] ? ret : void
476
+ def find_hooks(event)
477
+ event_name = "#{event}_#{command_name}"
478
+ (hooks || Pry.hooks || self.class.hooks).get_hooks(event_name).values
429
479
  end
430
480
 
431
- # Are all the gems required to use this command installed?
432
- #
433
- # @return Boolean
434
- def dependencies_met?
435
- @dependencies_met ||= command_dependencies_met?(command_options)
481
+ def before_hooks
482
+ find_hooks('before')
436
483
  end
437
484
 
438
- # Generate completions for this command
439
- #
440
- # @param [String] search The line typed so far
441
- # @return [Array<String>] Completion words
442
- def complete(search)
443
- []
485
+ def after_hooks
486
+ find_hooks('after')
444
487
  end
445
488
 
446
- private
447
-
448
489
  # Run the `#call` method and all the registered hooks.
449
490
  # @param [Array<String>] args The arguments to `#call`
450
491
  # @return [Object] The return value from `#call`
451
492
  def call_with_hooks(*args)
452
- self.class.hooks[:before].each do |block|
453
- instance_exec(*args, &block)
454
- end
493
+ before_hooks.each { |block| instance_exec(*args, &block) }
455
494
 
456
495
  ret = call(*args)
457
496
 
458
- self.class.hooks[:after].each do |block|
497
+ after_hooks.each do |block|
459
498
  ret = instance_exec(*args, &block)
460
499
  end
461
500
 
462
501
  ret
463
502
  end
464
503
 
465
- # Fix the number of arguments we pass to a block to avoid arity warnings.
466
- # @param [Fixnum] arity The arity of the block
467
- # @param [Array] args The arguments to pass
468
- # @return [Array] A (possibly shorter) array of the arguments to pass
469
- def correct_arg_arity(arity, args)
470
- case
471
- when arity < 0
504
+ # Normalize method arguments according to its arity.
505
+ #
506
+ # @param [Integer] method
507
+ # @param [Array] args
508
+ # @return [Array] a (possibly shorter) array of the arguments to pass
509
+ def normalize_method_args(method, args)
510
+ case method.arity
511
+ when -1
472
512
  args
473
- when arity == 0
513
+ when 0
474
514
  []
475
- when arity > 0
476
- args.values_at(*(0..(arity - 1)).to_a)
477
- end
478
- end
479
- end
480
-
481
- # A super-class for Commands that are created with a single block.
482
- #
483
- # This class ensures that the block is called with the correct number of arguments
484
- # and the right context.
485
- #
486
- # Create subclasses using {Pry::CommandSet#command}.
487
- class BlockCommand < Command
488
- # backwards compatibility
489
- alias_method :opts, :context
490
-
491
- # Call the block that was registered with this command.
492
- # @param [Array<String>] args The arguments passed
493
- # @return [Object] The return value of the block
494
- def call(*args)
495
- instance_exec(*correct_arg_arity(block.arity, args), &block)
496
- end
497
-
498
- def help
499
- "#{command_options[:listing].to_s.ljust(18)} #{description}"
500
- end
501
- end
502
-
503
- # A super-class of Commands with structure.
504
- #
505
- # This class implements the bare-minimum functionality that a command should
506
- # have, namely a --help switch, and then delegates actual processing to its
507
- # subclasses.
508
- #
509
- # Create subclasses using {Pry::CommandSet#create_command}, and override the
510
- # `options(opt)` method to set up an instance of Slop, and the `process`
511
- # method to actually run the command. If necessary, you can also override
512
- # `setup` which will be called before `options`, for example to require any
513
- # gems your command needs to run, or to set up state.
514
- class ClassCommand < Command
515
- class << self
516
-
517
- # Ensure that subclasses inherit the options, description and
518
- # match from a ClassCommand super class.
519
- def inherited(klass)
520
- klass.match match
521
- klass.description description
522
- klass.command_options options
523
- end
524
-
525
- def source
526
- source_object.source
527
- end
528
-
529
- def doc
530
- new.help
531
- end
532
-
533
- def source_location
534
- source_object.source_location
535
- end
536
-
537
- def source_file
538
- source_object.source_file
539
- end
540
- alias_method :file, :source_file
541
-
542
- def source_line
543
- source_object.source_line
544
- end
545
- alias_method :line, :source_line
546
-
547
- private
548
-
549
- # The object used to extract the source for the command.
550
- #
551
- # This should be a `Pry::Method(block)` for a command made with `create_command`
552
- # and a `Pry::WrappedModule(self)` for a command that's a standard class.
553
- # @return [Pry::WrappedModule, Pry::Method]
554
- def source_object
555
- @source_object ||= if name =~ /^[A-Z]/
556
- Pry::WrappedModule(self)
557
- else
558
- Pry::Method(block)
559
- end
560
- end
561
- end
562
-
563
- attr_accessor :opts
564
- attr_accessor :args
565
-
566
- # Set up `opts` and `args`, and then call `process`.
567
- #
568
- # This method will display help if necessary.
569
- #
570
- # @param [Array<String>] args The arguments passed
571
- # @return [Object] The return value of `process` or VOID_VALUE
572
- def call(*args)
573
- setup
574
-
575
- self.opts = slop
576
- self.args = self.opts.parse!(args)
577
-
578
- if opts.present?(:help)
579
- output.puts slop.help
580
- void
581
515
  else
582
- process(*correct_arg_arity(method(:process).arity, args))
516
+ args.values_at(*(0..(method.arity - 1)).to_a)
583
517
  end
584
518
  end
585
-
586
- # Return the help generated by Slop for this command.
587
- def help
588
- slop.help
589
- end
590
-
591
- # Return an instance of Slop that can parse either subcommands or the
592
- # options that this command accepts.
593
- def slop
594
- Slop.new do |opt|
595
- opt.banner(unindent(self.class.banner))
596
- subcommands(opt)
597
- options(opt)
598
- opt.on :h, :help, 'Show this message.'
599
- end
600
- end
601
-
602
- # Generate shell completions
603
- # @param [String] search The line typed so far
604
- # @return [Array<String>] the words to complete
605
- def complete(search)
606
- slop.map do |opt|
607
- [opt.long && "--#{opt.long} " || opt.short && "-#{opt.short}"]
608
- end.flatten(1).compact + super
609
- end
610
-
611
- # A method called just before `options(opt)` as part of `call`.
612
- #
613
- # This method can be used to set up any context your command needs to run,
614
- # for example requiring gems, or setting default values for options.
615
- #
616
- # @example
617
- # def setup
618
- # require 'gist'
619
- # @action = :method
620
- # end
621
- def setup; end
622
-
623
- # A method to setup Slop commands so it can parse the subcommands your
624
- # command expects. If you need to set up default values, use `setup`
625
- # instead.
626
- #
627
- # @example A minimal example
628
- # def subcommands(cmd)
629
- # cmd.command :download do |opt|
630
- # description 'Downloads a content from a server'
631
- #
632
- # opt.on :verbose, 'Use verbose output'
633
- #
634
- # run do |options, arguments|
635
- # ContentDownloader.download(options, arguments)
636
- # end
637
- # end
638
- # end
639
- #
640
- # @example Define the invokation block anywhere you want
641
- # def subcommands(cmd)
642
- # cmd.command :download do |opt|
643
- # description 'Downloads a content from a server'
644
- #
645
- # opt.on :verbose, 'Use verbose output'
646
- # end
647
- # end
648
- #
649
- # def process
650
- # # Perform calculations...
651
- # opts.fetch_command(:download).run do |options, arguments|
652
- # ContentDownloader.download(options, arguments)
653
- # end
654
- # # More calculations...
655
- # end
656
- def subcommands(cmd); end
657
-
658
- # A method to setup Slop so it can parse the options your command expects.
659
- #
660
- # @note Please don't do anything side-effecty in the main part of this
661
- # method, as it may be called by Pry at any time for introspection reasons.
662
- # If you need to set up default values, use `setup` instead.
663
- #
664
- # @example
665
- # def options(opt)
666
- # opt.banner "Gists methods or classes"
667
- # opt.on(:c, :class, "gist a class") do
668
- # @action = :class
669
- # end
670
- # end
671
- def options(opt); end
672
-
673
- # The actual body of your command should go here.
674
- #
675
- # The `opts` mehod can be called to get the options that Slop has passed,
676
- # and `args` gives the remaining, unparsed arguments.
677
- #
678
- # The return value of this method is discarded unless the command was
679
- # created with `:keep_retval => true`, in which case it is returned to the
680
- # repl.
681
- #
682
- # @example
683
- # def process
684
- # if opts.present?(:class)
685
- # gist_class
686
- # else
687
- # gist_method
688
- # end
689
- # end
690
- def process; raise CommandError, "command '#{command_name}' not implemented" end
691
519
  end
692
520
  end