pry 0.10.3 → 0.14.2

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 (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