pry 0.10.0.pre4-x64-mingw32

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 (131) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +702 -0
  3. data/LICENSE +25 -0
  4. data/README.md +406 -0
  5. data/bin/pry +16 -0
  6. data/lib/pry.rb +161 -0
  7. data/lib/pry/cli.rb +220 -0
  8. data/lib/pry/code.rb +341 -0
  9. data/lib/pry/code/code_file.rb +103 -0
  10. data/lib/pry/code/code_range.rb +71 -0
  11. data/lib/pry/code/loc.rb +92 -0
  12. data/lib/pry/code_object.rb +172 -0
  13. data/lib/pry/color_printer.rb +55 -0
  14. data/lib/pry/command.rb +692 -0
  15. data/lib/pry/command_set.rb +443 -0
  16. data/lib/pry/commands.rb +6 -0
  17. data/lib/pry/commands/amend_line.rb +99 -0
  18. data/lib/pry/commands/bang.rb +20 -0
  19. data/lib/pry/commands/bang_pry.rb +17 -0
  20. data/lib/pry/commands/cat.rb +62 -0
  21. data/lib/pry/commands/cat/abstract_formatter.rb +27 -0
  22. data/lib/pry/commands/cat/exception_formatter.rb +77 -0
  23. data/lib/pry/commands/cat/file_formatter.rb +67 -0
  24. data/lib/pry/commands/cat/input_expression_formatter.rb +43 -0
  25. data/lib/pry/commands/cd.rb +41 -0
  26. data/lib/pry/commands/change_inspector.rb +27 -0
  27. data/lib/pry/commands/change_prompt.rb +26 -0
  28. data/lib/pry/commands/code_collector.rb +165 -0
  29. data/lib/pry/commands/disable_pry.rb +27 -0
  30. data/lib/pry/commands/disabled_commands.rb +2 -0
  31. data/lib/pry/commands/easter_eggs.rb +112 -0
  32. data/lib/pry/commands/edit.rb +195 -0
  33. data/lib/pry/commands/edit/exception_patcher.rb +25 -0
  34. data/lib/pry/commands/edit/file_and_line_locator.rb +36 -0
  35. data/lib/pry/commands/exit.rb +42 -0
  36. data/lib/pry/commands/exit_all.rb +29 -0
  37. data/lib/pry/commands/exit_program.rb +23 -0
  38. data/lib/pry/commands/find_method.rb +193 -0
  39. data/lib/pry/commands/fix_indent.rb +19 -0
  40. data/lib/pry/commands/gem_cd.rb +26 -0
  41. data/lib/pry/commands/gem_install.rb +32 -0
  42. data/lib/pry/commands/gem_list.rb +33 -0
  43. data/lib/pry/commands/gem_open.rb +29 -0
  44. data/lib/pry/commands/gist.rb +101 -0
  45. data/lib/pry/commands/help.rb +164 -0
  46. data/lib/pry/commands/hist.rb +180 -0
  47. data/lib/pry/commands/import_set.rb +22 -0
  48. data/lib/pry/commands/install_command.rb +53 -0
  49. data/lib/pry/commands/jump_to.rb +29 -0
  50. data/lib/pry/commands/list_inspectors.rb +35 -0
  51. data/lib/pry/commands/list_prompts.rb +35 -0
  52. data/lib/pry/commands/ls.rb +114 -0
  53. data/lib/pry/commands/ls/constants.rb +47 -0
  54. data/lib/pry/commands/ls/formatter.rb +49 -0
  55. data/lib/pry/commands/ls/globals.rb +48 -0
  56. data/lib/pry/commands/ls/grep.rb +21 -0
  57. data/lib/pry/commands/ls/instance_vars.rb +39 -0
  58. data/lib/pry/commands/ls/interrogatable.rb +18 -0
  59. data/lib/pry/commands/ls/jruby_hacks.rb +49 -0
  60. data/lib/pry/commands/ls/local_names.rb +35 -0
  61. data/lib/pry/commands/ls/local_vars.rb +39 -0
  62. data/lib/pry/commands/ls/ls_entity.rb +70 -0
  63. data/lib/pry/commands/ls/methods.rb +57 -0
  64. data/lib/pry/commands/ls/methods_helper.rb +46 -0
  65. data/lib/pry/commands/ls/self_methods.rb +32 -0
  66. data/lib/pry/commands/nesting.rb +25 -0
  67. data/lib/pry/commands/play.rb +103 -0
  68. data/lib/pry/commands/pry_backtrace.rb +25 -0
  69. data/lib/pry/commands/pry_version.rb +17 -0
  70. data/lib/pry/commands/raise_up.rb +32 -0
  71. data/lib/pry/commands/reload_code.rb +62 -0
  72. data/lib/pry/commands/reset.rb +18 -0
  73. data/lib/pry/commands/ri.rb +60 -0
  74. data/lib/pry/commands/save_file.rb +61 -0
  75. data/lib/pry/commands/shell_command.rb +48 -0
  76. data/lib/pry/commands/shell_mode.rb +25 -0
  77. data/lib/pry/commands/show_doc.rb +83 -0
  78. data/lib/pry/commands/show_info.rb +195 -0
  79. data/lib/pry/commands/show_input.rb +17 -0
  80. data/lib/pry/commands/show_source.rb +50 -0
  81. data/lib/pry/commands/simple_prompt.rb +22 -0
  82. data/lib/pry/commands/stat.rb +40 -0
  83. data/lib/pry/commands/switch_to.rb +23 -0
  84. data/lib/pry/commands/toggle_color.rb +24 -0
  85. data/lib/pry/commands/watch_expression.rb +105 -0
  86. data/lib/pry/commands/watch_expression/expression.rb +38 -0
  87. data/lib/pry/commands/whereami.rb +190 -0
  88. data/lib/pry/commands/wtf.rb +57 -0
  89. data/lib/pry/config.rb +24 -0
  90. data/lib/pry/config/behavior.rb +139 -0
  91. data/lib/pry/config/convenience.rb +26 -0
  92. data/lib/pry/config/default.rb +165 -0
  93. data/lib/pry/core_extensions.rb +131 -0
  94. data/lib/pry/editor.rb +133 -0
  95. data/lib/pry/exceptions.rb +77 -0
  96. data/lib/pry/helpers.rb +5 -0
  97. data/lib/pry/helpers/base_helpers.rb +113 -0
  98. data/lib/pry/helpers/command_helpers.rb +156 -0
  99. data/lib/pry/helpers/documentation_helpers.rb +75 -0
  100. data/lib/pry/helpers/options_helpers.rb +27 -0
  101. data/lib/pry/helpers/table.rb +109 -0
  102. data/lib/pry/helpers/text.rb +107 -0
  103. data/lib/pry/history.rb +125 -0
  104. data/lib/pry/history_array.rb +121 -0
  105. data/lib/pry/hooks.rb +230 -0
  106. data/lib/pry/indent.rb +406 -0
  107. data/lib/pry/input_completer.rb +242 -0
  108. data/lib/pry/input_lock.rb +132 -0
  109. data/lib/pry/inspector.rb +27 -0
  110. data/lib/pry/last_exception.rb +61 -0
  111. data/lib/pry/method.rb +546 -0
  112. data/lib/pry/method/disowned.rb +53 -0
  113. data/lib/pry/method/patcher.rb +125 -0
  114. data/lib/pry/method/weird_method_locator.rb +186 -0
  115. data/lib/pry/module_candidate.rb +136 -0
  116. data/lib/pry/object_path.rb +82 -0
  117. data/lib/pry/output.rb +50 -0
  118. data/lib/pry/pager.rb +234 -0
  119. data/lib/pry/plugins.rb +103 -0
  120. data/lib/pry/prompt.rb +26 -0
  121. data/lib/pry/pry_class.rb +375 -0
  122. data/lib/pry/pry_instance.rb +654 -0
  123. data/lib/pry/rbx_path.rb +22 -0
  124. data/lib/pry/repl.rb +202 -0
  125. data/lib/pry/repl_file_loader.rb +74 -0
  126. data/lib/pry/rubygem.rb +82 -0
  127. data/lib/pry/terminal.rb +79 -0
  128. data/lib/pry/test/helper.rb +170 -0
  129. data/lib/pry/version.rb +3 -0
  130. data/lib/pry/wrapped_module.rb +373 -0
  131. metadata +248 -0
@@ -0,0 +1,692 @@
1
+ require 'delegate'
2
+ require 'pry/helpers/documentation_helpers'
3
+
4
+ class Pry
5
+
6
+ # 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.
9
+ class Command
10
+ extend Helpers::DocumentationHelpers
11
+ extend CodeObject::Helpers
12
+
13
+ # represents a void return value for a command
14
+ VOID_VALUE = Object.new
15
+
16
+ # give it a nice inspect
17
+ def VOID_VALUE.inspect() "void" end
18
+
19
+ # Properties of the command itself (as passed as arguments to
20
+ # {CommandSet#command} or {CommandSet#create_command}).
21
+ class << self
22
+ attr_writer :block
23
+ attr_writer :description
24
+ attr_writer :command_options
25
+ attr_writer :match
26
+
27
+ def match(arg=nil)
28
+ if arg
29
+ @command_options ||= default_options(arg)
30
+ @command_options[:listing] = arg.is_a?(String) ? arg : arg.inspect
31
+ @match = arg
32
+ end
33
+ @match ||= nil
34
+ end
35
+
36
+ # Define or get the command's description
37
+ def description(arg=nil)
38
+ @description = arg if arg
39
+ @description ||= nil
40
+ end
41
+
42
+ # Define or get the command's options
43
+ def command_options(arg=nil)
44
+ @command_options ||= default_options(match)
45
+ @command_options.merge!(arg) if arg
46
+ @command_options
47
+ end
48
+ # backward compatibility
49
+ alias_method :options, :command_options
50
+ alias_method :options=, :command_options=
51
+
52
+ # Define or get the command's banner
53
+ def banner(arg=nil)
54
+ @banner = arg if arg
55
+ @banner || description
56
+ end
57
+
58
+ def block
59
+ @block || instance_method(:process)
60
+ end
61
+
62
+ def source
63
+ file, line = block.source_location
64
+ strip_leading_whitespace(Pry::Code.from_file(file).expression_at(line))
65
+ end
66
+
67
+ def doc
68
+ new.help
69
+ end
70
+
71
+ def source_location
72
+ block.source_location
73
+ end
74
+
75
+ def source_file
76
+ Array(block.source_location).first
77
+ end
78
+ alias_method :file, :source_file
79
+
80
+ def source_line
81
+ Array(block.source_location).last
82
+ end
83
+ alias_method :line, :source_line
84
+
85
+ def default_options(match)
86
+ {
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
95
+ }
96
+ end
97
+ end
98
+
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
+ def name
111
+ super.to_s == "" ? "#<class(Pry::Command #{match.inspect})>" : super
112
+ end
113
+
114
+ def inspect
115
+ name
116
+ end
117
+
118
+ def command_name
119
+ self.options[:listing]
120
+ end
121
+
122
+ # Create a new command with the given properties.
123
+ # @param [String, Regex] match The thing that triggers this command
124
+ # @param [String] description The description to appear in `help`
125
+ # @param [Hash] options Behavioral options (see {Pry::CommandSet#command})
126
+ # @param [Module] helpers A module of helper functions to be included.
127
+ # @yield optional, used for BlockCommands
128
+ # @return [Class] (a subclass of {Pry::Command})
129
+ def subclass(match, description, options, helpers, &block)
130
+ klass = Class.new(self)
131
+ klass.send(:include, helpers)
132
+ klass.match = match
133
+ klass.description = description
134
+ klass.command_options = options
135
+ klass.block = block
136
+ klass
137
+ end
138
+
139
+ # Should this command be called for the given line?
140
+ # @param [String] val A line input at the REPL
141
+ # @return [Boolean]
142
+ def matches?(val)
143
+ command_regex =~ val
144
+ end
145
+
146
+ # How well does this command match the given line?
147
+ #
148
+ # Higher scores are better because they imply that this command matches
149
+ # the line more closely.
150
+ #
151
+ # The score is calculated by taking the number of characters at the start
152
+ # of the string that are used only to identify the command, not as part of
153
+ # the arguments.
154
+ #
155
+ # @example
156
+ # /\.(.*)/.match_score(".foo") #=> 1
157
+ # /\.*(.*)/.match_score("...foo") #=> 3
158
+ # 'hi'.match_score("hi there") #=> 2
159
+ #
160
+ # @param [String] val A line input at the REPL
161
+ # @return [Fixnum]
162
+ def match_score(val)
163
+ if command_regex =~ val
164
+ Regexp.last_match.size > 1 ? Regexp.last_match.begin(1) : Regexp.last_match.end(0)
165
+ else
166
+ -1
167
+ end
168
+ end
169
+
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
+ def command_regex
178
+ pr = Pry.respond_to?(:config) ? Pry.config.command_prefix : ""
179
+ prefix = convert_to_regex(pr)
180
+ prefix = "(?:#{prefix})?" unless options[:use_prefix]
181
+
182
+ /^#{prefix}#{convert_to_regex(match)}(?!\S)/
183
+ end
184
+
185
+ def convert_to_regex(obj)
186
+ case obj
187
+ when String
188
+ Regexp.escape(obj)
189
+ else
190
+ obj
191
+ end
192
+ end
193
+
194
+ # The group in which the command should be displayed in "help" output.
195
+ # This is usually auto-generated from directory naming, but it can be
196
+ # manually overridden if necessary.
197
+ # 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
214
+ end
215
+ end
216
+
217
+ # Properties of one execution of a command (passed by {Pry#run_command} as a hash of
218
+ # context and expanded in `#initialize`
219
+ attr_accessor :output
220
+ attr_accessor :target
221
+ attr_accessor :captures
222
+ attr_accessor :eval_string
223
+ attr_accessor :arg_string
224
+ attr_accessor :context
225
+ attr_accessor :command_set
226
+ attr_accessor :_pry_
227
+
228
+ # The block we pass *into* a command so long as `:takes_block` is
229
+ # not equal to `false`
230
+ # @example
231
+ # my-command | do
232
+ # puts "block content"
233
+ # end
234
+ attr_accessor :command_block
235
+
236
+ # Run a command from another command.
237
+ # @param [String] command_string The string that invokes the command
238
+ # @param [Array] args Further arguments to pass to the command
239
+ # @example
240
+ # run "show-input"
241
+ # @example
242
+ # run ".ls"
243
+ # @example
244
+ # run "amend-line", "5", 'puts "hello world"'
245
+ def run(command_string, *args)
246
+ command_string = _pry_.config.command_prefix.to_s + command_string
247
+ complete_string = "#{command_string} #{args.join(" ")}".rstrip
248
+ command_set.process_line(complete_string, context)
249
+ end
250
+
251
+ def commands
252
+ command_set.to_hash
253
+ end
254
+
255
+ def text
256
+ Pry::Helpers::Text
257
+ end
258
+
259
+ def void
260
+ VOID_VALUE
261
+ end
262
+
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]
275
+ end
276
+
277
+ # @return [Object] The value of `self` inside the `target` binding.
278
+ def target_self; target.eval('self'); end
279
+
280
+ # @return [Hash] Pry commands can store arbitrary state
281
+ # here. This state persists between subsequent command invocations.
282
+ # All state saved here is unique to the command, it does not
283
+ # need to be namespaced.
284
+ # @example
285
+ # state.my_state = "my state" # this will not conflict with any
286
+ # # `state.my_state` used in another command.
287
+ def state
288
+ _pry_.command_state[match] ||= Pry::Config.from_hash({})
289
+ end
290
+
291
+ # Revaluate the string (str) and perform interpolation.
292
+ # @param [String] str The string to reevaluate with interpolation.
293
+ #
294
+ # @return [String] The reevaluated string with interpolations
295
+ # applied (if any).
296
+ def interpolate_string(str)
297
+ dumped_str = str.dump
298
+ if dumped_str.gsub!(/\\\#\{/, '#{')
299
+ target.eval(dumped_str)
300
+ else
301
+ str
302
+ end
303
+ end
304
+
305
+ # Display a warning if a command collides with a local/method in
306
+ # the current scope.
307
+ def check_for_command_collision(command_match, arg_string)
308
+ collision_type = target.eval("defined?(#{command_match})")
309
+ collision_type ||= 'local-variable' if arg_string.match(%r{\A\s*[-+*/%&|^]*=})
310
+
311
+ if collision_type
312
+ output.puts "#{text.bold('WARNING:')} Calling Pry command '#{command_match}', which conflicts with a #{collision_type}.\n\n"
313
+ end
314
+ rescue Pry::RescuableException
315
+ end
316
+
317
+ # Extract necessary information from a line that Command.matches? this
318
+ # command.
319
+ #
320
+ # Returns an array of four elements:
321
+ #
322
+ # ```
323
+ # [String] the portion of the line that matched with the Command match
324
+ # [String] a string of all the arguments (i.e. everything but the match)
325
+ # [Array] the captures caught by the command_regex
326
+ # [Array] the arguments obtained by splitting the arg_string
327
+ # ```
328
+ #
329
+ # @param [String] val The line of input
330
+ # @return [Array]
331
+ def tokenize(val)
332
+ val.replace(interpolate_string(val)) if command_options[:interpolate]
333
+
334
+ self.class.command_regex =~ val
335
+
336
+ # please call Command.matches? before Command#call_safely
337
+ raise CommandError, "fatal: called a command which didn't match?!" unless Regexp.last_match
338
+ captures = Regexp.last_match.captures
339
+ pos = Regexp.last_match.end(0)
340
+
341
+ arg_string = val[pos..-1]
342
+
343
+ # remove the one leading space if it exists
344
+ arg_string.slice!(0) if arg_string.start_with?(" ")
345
+
346
+ # process and pass a block if one is found
347
+ pass_block(arg_string) if command_options[:takes_block]
348
+
349
+ if arg_string
350
+ args = command_options[:shellwords] ? Shellwords.shellwords(arg_string) : arg_string.split(" ")
351
+ else
352
+ args = []
353
+ end
354
+
355
+ [val[0..pos].rstrip, arg_string, captures, args]
356
+ end
357
+
358
+ # Process a line that Command.matches? this command.
359
+ # @param [String] line The line to process
360
+ # @return [Object, Command::VOID_VALUE]
361
+ def process_line(line)
362
+ command_match, arg_string, captures, args = tokenize(line)
363
+
364
+ check_for_command_collision(command_match, arg_string) if Pry.config.collision_warning
365
+
366
+ self.arg_string = arg_string
367
+ self.captures = captures
368
+
369
+ call_safely(*(captures + args))
370
+ end
371
+
372
+ # Pass a block argument to a command.
373
+ # @param [String] arg_string The arguments (as a string) passed to the command.
374
+ # We inspect these for a '| do' or a '| {' and if we find it we use it
375
+ # to start a block input sequence. Once we have a complete
376
+ # block, we save it to an accessor that can be retrieved from the command context.
377
+ # Note that if we find the '| do' or '| {' we delete this and the
378
+ # elements following it from `arg_string`.
379
+ def pass_block(arg_string)
380
+ # Workaround for weird JRuby bug where rindex in this case can return nil
381
+ # even when there's a match.
382
+ arg_string.scan(/\| *(?:do|\{)/)
383
+ block_index = $~ && $~.offset(0)[0]
384
+
385
+ return if !block_index
386
+
387
+ block_init_string = arg_string.slice!(block_index..-1)[1..-1]
388
+ prime_string = "proc #{block_init_string}\n"
389
+
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
395
+
396
+ begin
397
+ self.command_block = target.eval(block_string)
398
+ rescue Pry::RescuableException
399
+ raise CommandError, "Incomplete block definition."
400
+ end
401
+ end
402
+
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
429
+ end
430
+
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)
436
+ end
437
+
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
+ []
444
+ end
445
+
446
+ private
447
+
448
+ # Run the `#call` method and all the registered hooks.
449
+ # @param [Array<String>] args The arguments to `#call`
450
+ # @return [Object] The return value from `#call`
451
+ def call_with_hooks(*args)
452
+ self.class.hooks[:before].each do |block|
453
+ instance_exec(*args, &block)
454
+ end
455
+
456
+ ret = call(*args)
457
+
458
+ self.class.hooks[:after].each do |block|
459
+ ret = instance_exec(*args, &block)
460
+ end
461
+
462
+ ret
463
+ end
464
+
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
472
+ args
473
+ when arity == 0
474
+ []
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
+ else
582
+ process(*correct_arg_arity(method(:process).arity, args))
583
+ end
584
+ 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
+ end
692
+ end