pry 0.10.0.pre2-universal-mswin32
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +702 -0
- data/LICENSE +25 -0
- data/README.md +406 -0
- data/bin/pry +16 -0
- data/lib/pry.rb +161 -0
- data/lib/pry/cli.rb +220 -0
- data/lib/pry/code.rb +346 -0
- data/lib/pry/code/code_file.rb +103 -0
- data/lib/pry/code/code_range.rb +71 -0
- data/lib/pry/code/loc.rb +92 -0
- data/lib/pry/code_object.rb +172 -0
- data/lib/pry/color_printer.rb +55 -0
- data/lib/pry/command.rb +692 -0
- data/lib/pry/command_set.rb +443 -0
- data/lib/pry/commands.rb +6 -0
- data/lib/pry/commands/amend_line.rb +99 -0
- data/lib/pry/commands/bang.rb +20 -0
- data/lib/pry/commands/bang_pry.rb +17 -0
- data/lib/pry/commands/cat.rb +62 -0
- data/lib/pry/commands/cat/abstract_formatter.rb +27 -0
- data/lib/pry/commands/cat/exception_formatter.rb +77 -0
- data/lib/pry/commands/cat/file_formatter.rb +67 -0
- data/lib/pry/commands/cat/input_expression_formatter.rb +43 -0
- data/lib/pry/commands/cd.rb +41 -0
- data/lib/pry/commands/change_inspector.rb +27 -0
- data/lib/pry/commands/change_prompt.rb +26 -0
- data/lib/pry/commands/code_collector.rb +165 -0
- data/lib/pry/commands/disable_pry.rb +27 -0
- data/lib/pry/commands/disabled_commands.rb +2 -0
- data/lib/pry/commands/easter_eggs.rb +112 -0
- data/lib/pry/commands/edit.rb +195 -0
- data/lib/pry/commands/edit/exception_patcher.rb +25 -0
- data/lib/pry/commands/edit/file_and_line_locator.rb +36 -0
- data/lib/pry/commands/exit.rb +42 -0
- data/lib/pry/commands/exit_all.rb +29 -0
- data/lib/pry/commands/exit_program.rb +23 -0
- data/lib/pry/commands/find_method.rb +193 -0
- data/lib/pry/commands/fix_indent.rb +19 -0
- data/lib/pry/commands/gem_cd.rb +26 -0
- data/lib/pry/commands/gem_install.rb +32 -0
- data/lib/pry/commands/gem_list.rb +33 -0
- data/lib/pry/commands/gem_open.rb +29 -0
- data/lib/pry/commands/gist.rb +101 -0
- data/lib/pry/commands/help.rb +164 -0
- data/lib/pry/commands/hist.rb +180 -0
- data/lib/pry/commands/import_set.rb +22 -0
- data/lib/pry/commands/install_command.rb +53 -0
- data/lib/pry/commands/jump_to.rb +29 -0
- data/lib/pry/commands/list_inspectors.rb +35 -0
- data/lib/pry/commands/list_prompts.rb +35 -0
- data/lib/pry/commands/ls.rb +114 -0
- data/lib/pry/commands/ls/constants.rb +47 -0
- data/lib/pry/commands/ls/formatter.rb +49 -0
- data/lib/pry/commands/ls/globals.rb +48 -0
- data/lib/pry/commands/ls/grep.rb +21 -0
- data/lib/pry/commands/ls/instance_vars.rb +39 -0
- data/lib/pry/commands/ls/interrogatable.rb +18 -0
- data/lib/pry/commands/ls/jruby_hacks.rb +49 -0
- data/lib/pry/commands/ls/local_names.rb +35 -0
- data/lib/pry/commands/ls/local_vars.rb +39 -0
- data/lib/pry/commands/ls/ls_entity.rb +70 -0
- data/lib/pry/commands/ls/methods.rb +57 -0
- data/lib/pry/commands/ls/methods_helper.rb +46 -0
- data/lib/pry/commands/ls/self_methods.rb +32 -0
- data/lib/pry/commands/nesting.rb +25 -0
- data/lib/pry/commands/play.rb +103 -0
- data/lib/pry/commands/pry_backtrace.rb +25 -0
- data/lib/pry/commands/pry_version.rb +17 -0
- data/lib/pry/commands/raise_up.rb +32 -0
- data/lib/pry/commands/reload_code.rb +62 -0
- data/lib/pry/commands/reset.rb +18 -0
- data/lib/pry/commands/ri.rb +60 -0
- data/lib/pry/commands/save_file.rb +61 -0
- data/lib/pry/commands/shell_command.rb +48 -0
- data/lib/pry/commands/shell_mode.rb +25 -0
- data/lib/pry/commands/show_doc.rb +83 -0
- data/lib/pry/commands/show_info.rb +195 -0
- data/lib/pry/commands/show_input.rb +17 -0
- data/lib/pry/commands/show_source.rb +50 -0
- data/lib/pry/commands/simple_prompt.rb +22 -0
- data/lib/pry/commands/stat.rb +40 -0
- data/lib/pry/commands/switch_to.rb +23 -0
- data/lib/pry/commands/toggle_color.rb +24 -0
- data/lib/pry/commands/watch_expression.rb +105 -0
- data/lib/pry/commands/watch_expression/expression.rb +38 -0
- data/lib/pry/commands/whereami.rb +190 -0
- data/lib/pry/commands/wtf.rb +57 -0
- data/lib/pry/config.rb +24 -0
- data/lib/pry/config/behavior.rb +139 -0
- data/lib/pry/config/convenience.rb +26 -0
- data/lib/pry/config/default.rb +165 -0
- data/lib/pry/core_extensions.rb +131 -0
- data/lib/pry/editor.rb +133 -0
- data/lib/pry/exceptions.rb +77 -0
- data/lib/pry/helpers.rb +5 -0
- data/lib/pry/helpers/base_helpers.rb +113 -0
- data/lib/pry/helpers/command_helpers.rb +156 -0
- data/lib/pry/helpers/documentation_helpers.rb +75 -0
- data/lib/pry/helpers/options_helpers.rb +27 -0
- data/lib/pry/helpers/table.rb +109 -0
- data/lib/pry/helpers/text.rb +107 -0
- data/lib/pry/history.rb +125 -0
- data/lib/pry/history_array.rb +121 -0
- data/lib/pry/hooks.rb +230 -0
- data/lib/pry/indent.rb +406 -0
- data/lib/pry/input_completer.rb +242 -0
- data/lib/pry/input_lock.rb +132 -0
- data/lib/pry/inspector.rb +27 -0
- data/lib/pry/last_exception.rb +61 -0
- data/lib/pry/method.rb +546 -0
- data/lib/pry/method/disowned.rb +53 -0
- data/lib/pry/method/patcher.rb +125 -0
- data/lib/pry/method/weird_method_locator.rb +186 -0
- data/lib/pry/module_candidate.rb +136 -0
- data/lib/pry/object_path.rb +82 -0
- data/lib/pry/output.rb +50 -0
- data/lib/pry/pager.rb +234 -0
- data/lib/pry/plugins.rb +103 -0
- data/lib/pry/prompt.rb +26 -0
- data/lib/pry/pry_class.rb +375 -0
- data/lib/pry/pry_instance.rb +654 -0
- data/lib/pry/rbx_path.rb +22 -0
- data/lib/pry/repl.rb +202 -0
- data/lib/pry/repl_file_loader.rb +74 -0
- data/lib/pry/rubygem.rb +82 -0
- data/lib/pry/terminal.rb +79 -0
- data/lib/pry/test/helper.rb +170 -0
- data/lib/pry/version.rb +3 -0
- data/lib/pry/wrapped_module.rb +373 -0
- metadata +248 -0
data/lib/pry/command.rb
ADDED
@@ -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
|