pry 0.9.7.4-i386-mingw32 → 0.9.8-i386-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -3
- data/CHANGELOG +43 -0
- data/README.markdown +3 -1
- data/Rakefile +51 -32
- data/bin/pry +2 -80
- data/lib/pry.rb +33 -26
- data/lib/pry/cli.rb +152 -0
- data/lib/pry/code.rb +351 -0
- data/lib/pry/command.rb +422 -0
- data/lib/pry/command_set.rb +259 -129
- data/lib/pry/commands.rb +0 -1
- data/lib/pry/config.rb +43 -9
- data/lib/pry/default_commands/context.rb +109 -92
- data/lib/pry/default_commands/documentation.rb +174 -63
- data/lib/pry/default_commands/easter_eggs.rb +26 -2
- data/lib/pry/default_commands/gems.rb +65 -37
- data/lib/pry/default_commands/input.rb +175 -243
- data/lib/pry/default_commands/introspection.rb +173 -112
- data/lib/pry/default_commands/ls.rb +96 -114
- data/lib/pry/default_commands/shell.rb +175 -70
- data/lib/pry/helpers/base_helpers.rb +7 -2
- data/lib/pry/helpers/command_helpers.rb +71 -77
- data/lib/pry/helpers/options_helpers.rb +10 -41
- data/lib/pry/helpers/text.rb +24 -4
- data/lib/pry/history.rb +55 -17
- data/lib/pry/history_array.rb +2 -0
- data/lib/pry/hooks.rb +252 -0
- data/lib/pry/indent.rb +9 -5
- data/lib/pry/method.rb +149 -50
- data/lib/pry/plugins.rb +12 -4
- data/lib/pry/pry_class.rb +69 -26
- data/lib/pry/pry_instance.rb +187 -115
- data/lib/pry/version.rb +1 -1
- data/lib/pry/wrapped_module.rb +73 -0
- data/man/pry.1 +195 -0
- data/man/pry.1.html +204 -0
- data/man/pry.1.ronn +141 -0
- data/pry.gemspec +29 -32
- data/test/helper.rb +32 -36
- data/test/test_cli.rb +78 -0
- data/test/test_code.rb +201 -0
- data/test/test_command.rb +327 -0
- data/test/test_command_integration.rb +512 -0
- data/test/test_command_set.rb +338 -12
- data/test/test_completion.rb +1 -1
- data/test/test_default_commands.rb +1 -2
- data/test/test_default_commands/test_context.rb +27 -5
- data/test/test_default_commands/test_documentation.rb +20 -8
- data/test/test_default_commands/test_input.rb +84 -45
- data/test/test_default_commands/test_introspection.rb +74 -17
- data/test/test_default_commands/test_ls.rb +9 -36
- data/test/test_default_commands/test_shell.rb +240 -13
- data/test/test_hooks.rb +490 -0
- data/test/test_indent.rb +2 -0
- data/test/test_method.rb +60 -0
- data/test/test_pry.rb +29 -904
- data/test/test_pry_defaults.rb +380 -0
- data/test/test_pry_history.rb +24 -24
- data/test/test_syntax_checking.rb +63 -0
- data/test/test_wrapped_module.rb +71 -0
- metadata +50 -39
- data/lib/pry/command_context.rb +0 -53
- data/lib/pry/command_processor.rb +0 -181
- data/lib/pry/extended_commands/user_command_api.rb +0 -65
- data/test/test_command_processor.rb +0 -176
data/lib/pry/command_set.rb
CHANGED
@@ -8,41 +8,6 @@ class Pry
|
|
8
8
|
# This class is used to create sets of commands. Commands can be imported from
|
9
9
|
# different sets, aliased, removed, etc.
|
10
10
|
class CommandSet
|
11
|
-
class Command < Struct.new(:name, :description, :options, :block)
|
12
|
-
|
13
|
-
def call(context, *args)
|
14
|
-
context.command_name = options[:listing]
|
15
|
-
|
16
|
-
if stub_block = options[:stub_info]
|
17
|
-
context.instance_eval(&stub_block)
|
18
|
-
else
|
19
|
-
ret = context.instance_exec(*correct_arg_arity(block.arity, args), &block)
|
20
|
-
if options[:keep_retval]
|
21
|
-
ret
|
22
|
-
else
|
23
|
-
Pry::CommandContext::VOID_VALUE
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
def correct_arg_arity(arity, args)
|
30
|
-
case arity <=> 0
|
31
|
-
when -1
|
32
|
-
args
|
33
|
-
when 0
|
34
|
-
[]
|
35
|
-
when 1
|
36
|
-
# another jruby hack
|
37
|
-
if Pry::Helpers::BaseHelpers.jruby?
|
38
|
-
args[0..(arity - 1)]
|
39
|
-
else
|
40
|
-
args.values_at 0..(arity - 1)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
11
|
include Enumerable
|
47
12
|
include Pry::Helpers::BaseHelpers
|
48
13
|
|
@@ -116,30 +81,74 @@ class Pry
|
|
116
81
|
# # hello john, nice number: 10
|
117
82
|
# # pry(main)> help number
|
118
83
|
# # number-N regex command
|
119
|
-
def
|
84
|
+
def block_command(name, description="No description.", options={}, &block)
|
85
|
+
description, options = ["No description.", description] if description.is_a?(Hash)
|
86
|
+
options = default_options(name).merge!(options)
|
120
87
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
88
|
+
commands[name] = Pry::BlockCommand.subclass(name, description, options, helper_module, &block)
|
89
|
+
end
|
90
|
+
alias_method :command, :block_command
|
91
|
+
|
92
|
+
# Defines a new Pry command class.
|
93
|
+
#
|
94
|
+
# @param [String, Regexp] name The name of the command. Can be
|
95
|
+
# Regexp as well as String.
|
96
|
+
# @param [String] description A description of the command.
|
97
|
+
# @param [Hash] options The optional configuration parameters, see {#command}
|
98
|
+
# @param &Block The class body's definition.
|
99
|
+
#
|
100
|
+
# @example
|
101
|
+
# Pry::Commands.create_command "echo", "echo's the input", :shellwords => false do
|
102
|
+
# def options(opt)
|
103
|
+
# opt.banner "Usage: echo [-u | -d] <string to echo>"
|
104
|
+
# opt.on :u, :upcase, "ensure the output is all upper-case"
|
105
|
+
# opt.on :d, :downcase, "ensure the output is all lower-case"
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# def process
|
109
|
+
# raise Pry::CommandError, "-u and -d makes no sense" if opts.present?(:u) && opts.present?(:d)
|
110
|
+
# result = args.join(" ")
|
111
|
+
# result.downcase! if opts.present?(:downcase)
|
112
|
+
# result.upcase! if opts.present?(:upcase)
|
113
|
+
# output.puts result
|
114
|
+
# end
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
def create_command(name, description="No description.", options={}, &block)
|
118
|
+
description, options = ["No description.", description] if description.is_a?(Hash)
|
119
|
+
options = default_options(name).merge!(options)
|
130
120
|
|
131
|
-
|
132
|
-
|
133
|
-
|
121
|
+
commands[name] = Pry::ClassCommand.subclass(name, description, options, helper_module, &block)
|
122
|
+
commands[name].class_eval(&block)
|
123
|
+
commands[name]
|
124
|
+
end
|
134
125
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
126
|
+
# Execute a block of code before a command is invoked. The block also
|
127
|
+
# gets access to parameters that will be passed to the command and
|
128
|
+
# is evaluated in the same context.
|
129
|
+
# @param [String, Regexp] name The name of the command.
|
130
|
+
# @yield The block to be run before the command.
|
131
|
+
# @example Display parameter before invoking command
|
132
|
+
# Pry.commands.before_command("whereami") do |n|
|
133
|
+
# output.puts "parameter passed was #{n}"
|
134
|
+
# end
|
135
|
+
def before_command(name, &block)
|
136
|
+
cmd = find_command_by_name_or_listing(name)
|
137
|
+
cmd.hooks[:before].unshift block
|
138
|
+
end
|
141
139
|
|
142
|
-
|
140
|
+
# Execute a block of code after a command is invoked. The block also
|
141
|
+
# gets access to parameters that will be passed to the command and
|
142
|
+
# is evaluated in the same context.
|
143
|
+
# @param [String, Regexp] name The name of the command.
|
144
|
+
# @yield The block to be run after the command.
|
145
|
+
# @example Display text 'command complete' after invoking command
|
146
|
+
# Pry.commands.after_command("whereami") do |n|
|
147
|
+
# output.puts "command complete!"
|
148
|
+
# end
|
149
|
+
def after_command(name, &block)
|
150
|
+
cmd = find_command_by_name_or_listing(name)
|
151
|
+
cmd.hooks[:after] << block
|
143
152
|
end
|
144
153
|
|
145
154
|
def each &block
|
@@ -149,7 +158,10 @@ class Pry
|
|
149
158
|
# Removes some commands from the set
|
150
159
|
# @param [Array<String>] names name of the commands to remove
|
151
160
|
def delete(*names)
|
152
|
-
names.each
|
161
|
+
names.each do |name|
|
162
|
+
cmd = find_command_by_name_or_listing(name)
|
163
|
+
commands.delete cmd.name
|
164
|
+
end
|
153
165
|
end
|
154
166
|
|
155
167
|
# Imports all the commands from one or more sets.
|
@@ -167,50 +179,79 @@ class Pry
|
|
167
179
|
# @param [Array<String>] names Commands to import
|
168
180
|
def import_from(set, *names)
|
169
181
|
helper_module.send :include, set.helper_module
|
170
|
-
names.each
|
182
|
+
names.each do |name|
|
183
|
+
cmd = set.find_command_by_name_or_listing(name)
|
184
|
+
commands[cmd.name] = cmd
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# @param [String, Regexp] name_or_listing The name or listing name
|
189
|
+
# of the command to retrieve.
|
190
|
+
# @return [Command] The command object matched.
|
191
|
+
def find_command_by_name_or_listing(name_or_listing)
|
192
|
+
if commands[name_or_listing]
|
193
|
+
cmd = commands[name_or_listing]
|
194
|
+
else
|
195
|
+
_, cmd = commands.find { |name, command| command.options[:listing] == name_or_listing }
|
196
|
+
end
|
197
|
+
|
198
|
+
raise ArgumentError, "Cannot find a command with name: '#{name_or_listing}'!" if !cmd
|
199
|
+
cmd
|
171
200
|
end
|
201
|
+
protected :find_command_by_name_or_listing
|
172
202
|
|
173
203
|
# Aliases a command
|
174
204
|
# @param [String] new_name New name of the command.
|
175
205
|
# @param [String] old_name Old name of the command.
|
176
206
|
# @param [String, nil] desc New description of the command.
|
177
207
|
def alias_command(new_name, old_name, desc="")
|
178
|
-
|
208
|
+
orig_command = find_command_by_name_or_listing(old_name)
|
209
|
+
commands[new_name] = orig_command.dup
|
179
210
|
commands[new_name].name = new_name
|
180
211
|
commands[new_name].description = desc
|
181
212
|
end
|
182
213
|
|
183
|
-
#
|
184
|
-
#
|
185
|
-
#
|
186
|
-
# @param [String] name
|
187
|
-
# @param [
|
188
|
-
# @
|
189
|
-
|
190
|
-
|
191
|
-
|
214
|
+
# Rename a command. Accepts either actual name or listing name for
|
215
|
+
# the `old_name`.
|
216
|
+
# `new_name` must be the actual name of the new command.
|
217
|
+
# @param [String, Regexp] new_name The new name for the command.
|
218
|
+
# @param [String, Regexp] old_name The command's current name.
|
219
|
+
# @param [Hash] options The optional configuration parameters,
|
220
|
+
# accepts the same as the `command` method, but also allows the
|
221
|
+
# command description to be passed this way too.
|
222
|
+
# @example Renaming the `ls` command and changing its description.
|
223
|
+
# Pry.config.commands.rename "dir", "ls", :description => "DOS friendly ls"
|
224
|
+
def rename_command(new_name, old_name, options={})
|
225
|
+
cmd = find_command_by_name_or_listing(old_name)
|
192
226
|
|
193
|
-
|
194
|
-
|
195
|
-
|
227
|
+
options = {
|
228
|
+
:listing => new_name,
|
229
|
+
:description => cmd.description
|
230
|
+
}.merge!(options)
|
196
231
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
232
|
+
commands[new_name] = cmd.dup
|
233
|
+
commands[new_name].name = new_name
|
234
|
+
commands[new_name].description = options.delete(:description)
|
235
|
+
commands[new_name].options.merge!(options)
|
236
|
+
commands.delete(cmd.name)
|
202
237
|
end
|
203
238
|
|
204
|
-
# Sets the description for a command (replacing the old
|
205
|
-
# description.
|
206
|
-
#
|
239
|
+
# Sets or gets the description for a command (replacing the old
|
240
|
+
# description). Returns current description if no description
|
241
|
+
# parameter provided.
|
242
|
+
# @param [String, Regexp] name The command name.
|
207
243
|
# @param [String] description The command description.
|
208
|
-
# @example
|
244
|
+
# @example Setting
|
209
245
|
# MyCommands = Pry::CommandSet.new do
|
210
246
|
# desc "help", "help description"
|
211
247
|
# end
|
212
|
-
|
213
|
-
|
248
|
+
# @example Getting
|
249
|
+
# Pry.config.commands.desc "amend-line"
|
250
|
+
def desc(name, description=nil)
|
251
|
+
cmd = find_command_by_name_or_listing(name)
|
252
|
+
return cmd.description if !description
|
253
|
+
|
254
|
+
cmd.description = description
|
214
255
|
end
|
215
256
|
|
216
257
|
# Defines helpers methods for this command sets.
|
@@ -235,72 +276,161 @@ class Pry
|
|
235
276
|
commands.keys
|
236
277
|
end
|
237
278
|
|
279
|
+
# Find a command that matches the given line
|
280
|
+
#
|
281
|
+
# @param [String] the line that may be a command invocation
|
282
|
+
# @return [Pry::Command, nil]
|
283
|
+
def find_command(val)
|
284
|
+
commands.values.detect{ |c| c.matches?(val) }
|
285
|
+
end
|
286
|
+
|
287
|
+
# Is the given line a command invocation?
|
288
|
+
#
|
289
|
+
# @param [String]
|
290
|
+
# @return [Boolean]
|
291
|
+
def valid_command?(val)
|
292
|
+
!!find_command(val)
|
293
|
+
end
|
294
|
+
|
295
|
+
# Process the given line to see whether it needs executing as a command.
|
296
|
+
#
|
297
|
+
# @param String the line to execute
|
298
|
+
# @param Hash the context to execute the commands with
|
299
|
+
# @return CommandSet::Result
|
300
|
+
#
|
301
|
+
def process_line(val, context={})
|
302
|
+
if command = find_command(val)
|
303
|
+
context = context.merge(:command_set => self)
|
304
|
+
retval = command.new(context).process_line(val)
|
305
|
+
Result.new(true, retval)
|
306
|
+
else
|
307
|
+
Result.new(false)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
# @nodoc used for testing
|
312
|
+
def run_command(context, name, *args)
|
313
|
+
command = commands[name] or raise NoCommandError.new(name, self)
|
314
|
+
command.new(context).call_safely(*args)
|
315
|
+
end
|
316
|
+
|
238
317
|
private
|
318
|
+
|
319
|
+
def default_options(name)
|
320
|
+
{
|
321
|
+
:requires_gem => [],
|
322
|
+
:keep_retval => false,
|
323
|
+
:argument_required => false,
|
324
|
+
:interpolate => true,
|
325
|
+
:shellwords => true,
|
326
|
+
:listing => name,
|
327
|
+
:use_prefix => true
|
328
|
+
}
|
329
|
+
end
|
330
|
+
|
239
331
|
def define_default_commands
|
240
332
|
|
241
|
-
|
242
|
-
|
243
|
-
output.puts
|
244
|
-
help_text = heading("Command List: ") + "\n"
|
333
|
+
create_command "help" do |cmd|
|
334
|
+
description "Show a list of commands, or help for one command"
|
245
335
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
336
|
+
banner <<-BANNER
|
337
|
+
Usage: help [ COMMAND ]
|
338
|
+
|
339
|
+
With no arguments, help lists all the available commands in the current
|
340
|
+
command-set along with their description.
|
341
|
+
|
342
|
+
When given a command name as an argument, shows the help for that command.
|
343
|
+
BANNER
|
251
344
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
345
|
+
def process
|
346
|
+
if cmd = args.first
|
347
|
+
if command = find_command(cmd)
|
348
|
+
output.puts command.new.help
|
349
|
+
else
|
350
|
+
output.puts "No info for command: #{cmd}"
|
351
|
+
end
|
256
352
|
else
|
257
|
-
output.puts
|
353
|
+
output.puts
|
354
|
+
help_text = heading("Command List: ") + "\n"
|
355
|
+
|
356
|
+
help_text << commands.map do |key, command|
|
357
|
+
if command.description && !command.description.empty?
|
358
|
+
"#{command.options[:listing].to_s.ljust(18)} #{command.description}"
|
359
|
+
end
|
360
|
+
end.compact.sort.join("\n")
|
361
|
+
|
362
|
+
stagger_output(help_text)
|
258
363
|
end
|
259
364
|
end
|
260
365
|
end
|
261
366
|
|
262
|
-
|
263
|
-
require 'rubygems/dependency_installer' unless defined? Gem::DependencyInstaller
|
264
|
-
command = find_command(name)
|
265
|
-
stub_info = command.options[:stub_info]
|
367
|
+
create_command "install-command", "Install a disabled command." do |name|
|
266
368
|
|
267
|
-
|
268
|
-
|
269
|
-
next
|
270
|
-
end
|
369
|
+
banner <<-BANNER
|
370
|
+
Usage: install-command COMMAND
|
271
371
|
|
272
|
-
|
273
|
-
|
372
|
+
Installs the gems necessary to run the given COMMAND. You will generally not
|
373
|
+
need to run this unless told to by an error message.
|
374
|
+
BANNER
|
274
375
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
output.puts "Installing `#{g}` gem..."
|
376
|
+
def process(name)
|
377
|
+
require 'rubygems/dependency_installer' unless defined? Gem::DependencyInstaller
|
378
|
+
command = find_command(name)
|
279
379
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
output.puts "Required Gem: `#{g}` not found. Aborting command installation."
|
284
|
-
gem_install_failed = true
|
285
|
-
next
|
380
|
+
if command_dependencies_met?(command.options)
|
381
|
+
output.puts "Dependencies for #{command.name} are met. Nothing to do."
|
382
|
+
return
|
286
383
|
end
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
384
|
+
|
385
|
+
output.puts "Attempting to install `#{name}` command..."
|
386
|
+
gems_to_install = Array(command.options[:requires_gem])
|
387
|
+
|
388
|
+
gems_to_install.each do |g|
|
389
|
+
next if gem_installed?(g)
|
390
|
+
output.puts "Installing `#{g}` gem..."
|
391
|
+
|
392
|
+
begin
|
393
|
+
Gem::DependencyInstaller.new.install(g)
|
394
|
+
rescue Gem::GemNotFoundException
|
395
|
+
raise CommandError, "Required Gem: `#{g}` not found. Aborting command installation."
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
Gem.refresh
|
400
|
+
gems_to_install.each do |g|
|
401
|
+
begin
|
402
|
+
require g
|
403
|
+
rescue LoadError
|
404
|
+
raise CommandError, "Required Gem: `#{g}` installed but not found?!. Aborting command installation."
|
405
|
+
end
|
297
406
|
end
|
298
|
-
end
|
299
|
-
next if gem_install_failed
|
300
407
|
|
301
|
-
|
302
|
-
|
408
|
+
output.puts "Installation of `#{name}` successful! Type `help #{name}` for information"
|
409
|
+
end
|
303
410
|
end
|
304
411
|
end
|
305
412
|
end
|
413
|
+
|
414
|
+
# Wraps the return result of process_commands, indicates if the
|
415
|
+
# result IS a command and what kind of command (e.g void)
|
416
|
+
class Result
|
417
|
+
attr_reader :retval
|
418
|
+
|
419
|
+
def initialize(is_command, retval = nil)
|
420
|
+
@is_command, @retval = is_command, retval
|
421
|
+
end
|
422
|
+
|
423
|
+
# Is the result a command?
|
424
|
+
# @return [Boolean]
|
425
|
+
def command?
|
426
|
+
@is_command
|
427
|
+
end
|
428
|
+
|
429
|
+
# Is the result a command and if it is, is it a void command?
|
430
|
+
# (one that does not return a value)
|
431
|
+
# @return [Boolean]
|
432
|
+
def void_command?
|
433
|
+
retval == Command::VOID_VALUE
|
434
|
+
end
|
435
|
+
end
|
306
436
|
end
|