pry 0.9.8.4 → 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/CHANGELOG +26 -0
- data/README.markdown +3 -3
- data/lib/pry.rb +9 -1
- data/lib/pry/code.rb +93 -0
- data/lib/pry/command.rb +35 -22
- data/lib/pry/command_set.rb +97 -67
- data/lib/pry/config.rb +63 -10
- data/lib/pry/core_extensions.rb +24 -18
- data/lib/pry/default_commands/context.rb +72 -12
- data/lib/pry/default_commands/easter_eggs.rb +4 -0
- data/lib/pry/default_commands/editing.rb +43 -15
- data/lib/pry/default_commands/find_method.rb +171 -0
- data/lib/pry/default_commands/hist.rb +10 -6
- data/lib/pry/default_commands/introspection.rb +183 -30
- data/lib/pry/default_commands/ls.rb +77 -7
- data/lib/pry/default_commands/misc.rb +1 -0
- data/lib/pry/default_commands/navigating_pry.rb +1 -8
- data/lib/pry/helpers/base_helpers.rb +10 -2
- data/lib/pry/helpers/command_helpers.rb +23 -40
- data/lib/pry/helpers/documentation_helpers.rb +65 -0
- data/lib/pry/indent.rb +17 -4
- data/lib/pry/method.rb +61 -45
- data/lib/pry/pry_class.rb +9 -3
- data/lib/pry/pry_instance.rb +99 -65
- data/lib/pry/rbx_method.rb +2 -9
- data/lib/pry/version.rb +1 -1
- data/lib/pry/wrapped_module.rb +236 -1
- data/pry.gemspec +5 -5
- data/test/helper.rb +22 -0
- data/test/test_command.rb +29 -0
- data/test/test_command_integration.rb +193 -10
- data/test/test_command_set.rb +82 -17
- data/test/test_default_commands/test_cd.rb +16 -0
- data/test/test_default_commands/test_context.rb +61 -0
- data/test/test_default_commands/test_documentation.rb +163 -43
- data/test/test_default_commands/test_find_method.rb +42 -0
- data/test/test_default_commands/test_input.rb +32 -0
- data/test/test_default_commands/test_introspection.rb +50 -197
- data/test/test_default_commands/test_ls.rb +22 -0
- data/test/test_default_commands/test_show_source.rb +306 -0
- data/test/test_pry.rb +3 -3
- data/test/test_pry_defaults.rb +21 -0
- data/test/test_sticky_locals.rb +81 -1
- data/test/test_syntax_checking.rb +7 -6
- metadata +22 -14
data/.gitignore
CHANGED
data/CHANGELOG
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
18/4/2012 version 0.9.9
|
2
|
+
|
3
|
+
MAJOR NEW FEATURES
|
4
|
+
* lines of input are syntax highlighted upon 'enter' keypress
|
5
|
+
* show-source command can now show class/module sourcecode (use -a to see all monkeypatches). Hard dependency on ruby18_source_location gem in MRI 1.8
|
6
|
+
* show-doc command can show class/module docs (use -a to see docs for all monkeypatches) Hard dependency on ruby18_source_location gem in MRI 1.8.
|
7
|
+
* new `find-method` command, performs a recursive search in a namespace for the existence of methods. Can find methods whose names match a regex or methods which contain provided CODE! This command is like a ruby-aware 'grep', very cool (thanks swarley)
|
8
|
+
* pry-coolline now works properly with Pry (https://github.com/pry/pry-coolline)
|
9
|
+
* alias_command method now much more powerful, e.g: alias_command "lM", "ls -M"
|
10
|
+
* `whereami` is now more intelligent, automatically showing entire sourcecode of current method if current context is a method (thanks robgleeson).
|
11
|
+
|
12
|
+
remaining items:
|
13
|
+
* fixed windows crashing bug when paging
|
14
|
+
* lines ending with \ are incomplete (kudos to fowl)
|
15
|
+
* `edit-method -n` no longer blocks (thanks misfo)s
|
16
|
+
* show instance methods of modules by default in ls
|
17
|
+
* docs for REPL defined methods can now be displayed using show-doc
|
18
|
+
* autoload ruby18_source_location on mri18, when available (https://github.com/conradirwin/ruby18_source_location)
|
19
|
+
* tab completion should work on first line now (historic bug fixed)
|
20
|
+
* :quiet => true option added to `Pry.start`, turns off whereami
|
21
|
+
* another easter egg added
|
22
|
+
* show unloaded constants in yellow for ls
|
23
|
+
* improved documentation for Pry.config options
|
24
|
+
* improved auto indentation
|
25
|
+
* JRuby: heuristics used to clean up 'ls' output (less internal methods polluting output)
|
26
|
+
|
1
27
|
6/3/2012 version 0.9.8.4 major bugfix
|
2
28
|
* ~/.pry_history wasnt being created (if it did not exist)! FIXED
|
3
29
|
* `hist --save` saved colors! FIXED
|
data/README.markdown
CHANGED
@@ -33,9 +33,9 @@ these include:
|
|
33
33
|
* Gist integration
|
34
34
|
* Navigation around state (`cd`, `ls` and friends)
|
35
35
|
* Runtime invocation (use Pry as a developer console or debugger)
|
36
|
-
* Exotic object support (BasicObject
|
37
|
-
*
|
38
|
-
*
|
36
|
+
* Exotic object support (BasicObject instances, IClasses, ...)
|
37
|
+
* A Powerful and flexible command system
|
38
|
+
* Ability to view and replay history
|
39
39
|
|
40
40
|
* Many convenience commands inspired by IPython, Smalltalk and other advanced REPLs
|
41
41
|
* A wide-range number of [plugins](https://github.com/pry/pry/wiki/Available-plugins) that provide remote sessions, full debugging functionality, and more.
|
data/lib/pry.rb
CHANGED
@@ -9,12 +9,13 @@ require 'pry/hooks'
|
|
9
9
|
class Pry
|
10
10
|
# The default hooks - display messages when beginning and ending Pry sessions.
|
11
11
|
DEFAULT_HOOKS = Pry::Hooks.new.add_hook(:before_session, :default) do |out, target, _pry_|
|
12
|
+
next if _pry_.quiet?
|
12
13
|
# ensure we're actually in a method
|
13
14
|
file = target.eval('__FILE__')
|
14
15
|
|
15
16
|
# /unknown/ for rbx
|
16
17
|
if file !~ /(\(.*\))|<.*>/ && file !~ /__unknown__/ && file != "" && file != "-e" || file == Pry.eval_path
|
17
|
-
_pry_.run_command("whereami
|
18
|
+
_pry_.run_command("whereami", "", target)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
@@ -158,6 +159,13 @@ class Pry
|
|
158
159
|
end
|
159
160
|
end
|
160
161
|
|
162
|
+
if Pry::Helpers::BaseHelpers.mri_18?
|
163
|
+
begin
|
164
|
+
require 'ruby18_source_location'
|
165
|
+
rescue LoadError
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
161
169
|
require "method_source"
|
162
170
|
require 'shellwords'
|
163
171
|
require "readline"
|
data/lib/pry/code.rb
CHANGED
@@ -27,6 +27,72 @@ class Pry
|
|
27
27
|
# object.
|
28
28
|
class Code
|
29
29
|
class << self
|
30
|
+
|
31
|
+
# Determine if a string of code is a complete Ruby expression.
|
32
|
+
# @param [String] code The code to validate.
|
33
|
+
# @return [Boolean] Whether or not the code is a complete Ruby expression.
|
34
|
+
# @raise [SyntaxError] Any SyntaxError that does not represent incompleteness.
|
35
|
+
# @example
|
36
|
+
# complete_expression?("class Hello") #=> false
|
37
|
+
# complete_expression?("class Hello; end") #=> true
|
38
|
+
def complete_expression?(str)
|
39
|
+
if defined?(Rubinius::Melbourne19) && RUBY_VERSION =~ /^1\.9/
|
40
|
+
Rubinius::Melbourne19.parse_string(str, Pry.eval_path)
|
41
|
+
elsif defined?(Rubinius::Melbourne)
|
42
|
+
Rubinius::Melbourne.parse_string(str, Pry.eval_path)
|
43
|
+
else
|
44
|
+
catch(:valid) do
|
45
|
+
Helpers::BaseHelpers.silence_warnings do
|
46
|
+
eval("BEGIN{throw :valid}\n#{str}", binding, Pry.eval_path)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Assert that a line which ends with a , or \ is incomplete.
|
52
|
+
str !~ /[,\\]\s*\z/
|
53
|
+
rescue SyntaxError => e
|
54
|
+
if incomplete_user_input_exception?(e)
|
55
|
+
false
|
56
|
+
else
|
57
|
+
raise e
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Check whether the exception indicates that the user should input more.
|
62
|
+
#
|
63
|
+
# @param [SyntaxError] the exception object that was raised.
|
64
|
+
# @param [Array<String>] The stack frame of the function that executed eval.
|
65
|
+
# @return [Boolean]
|
66
|
+
#
|
67
|
+
def incomplete_user_input_exception?(ex)
|
68
|
+
case ex.message
|
69
|
+
when /unexpected (\$end|end-of-file|END_OF_FILE)/, # mri, jruby, ironruby
|
70
|
+
/unterminated (quoted string|string|regexp) meets end of file/, # "quoted string" is ironruby
|
71
|
+
/missing 'end' for/, /: expecting '[})\]]'$/, /can't find string ".*" anywhere before EOF/, /: expecting keyword_end/, /expecting kWHEN/ # rbx
|
72
|
+
true
|
73
|
+
else
|
74
|
+
false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
private :incomplete_user_input_exception?
|
78
|
+
|
79
|
+
# Retrieve the first complete expression from the passed string.
|
80
|
+
#
|
81
|
+
# @param [String, Array<String>] str The string (or array of lines) to extract the complete
|
82
|
+
# expression from.
|
83
|
+
# @return [String, nil] The first complete expression, or `nil` if
|
84
|
+
# none found.
|
85
|
+
def retrieve_complete_expression_from(str_or_lines)
|
86
|
+
lines = str_or_lines.is_a?(Array) ? str_or_lines : str_or_lines.each_line.to_a
|
87
|
+
|
88
|
+
code = ""
|
89
|
+
lines.each do |v|
|
90
|
+
code << v
|
91
|
+
return code if complete_expression?(code)
|
92
|
+
end
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
|
30
96
|
# Instantiate a `Code` object containing code loaded from a file or
|
31
97
|
# Pry's line buffer.
|
32
98
|
#
|
@@ -63,6 +129,16 @@ class Pry
|
|
63
129
|
new(meth.source, start_line, meth.source_type)
|
64
130
|
end
|
65
131
|
|
132
|
+
# Attempt to extract the source code for module (or class) `mod`.
|
133
|
+
#
|
134
|
+
# @param [Module, Class] mod The module (or class) of interest.
|
135
|
+
# @return [Code]
|
136
|
+
def from_module(mod, start_line=nil)
|
137
|
+
mod = Pry::WrappedModule(mod)
|
138
|
+
start_line ||= mod.source_line || 1
|
139
|
+
new(mod.source, start_line, :ruby)
|
140
|
+
end
|
141
|
+
|
66
142
|
protected
|
67
143
|
# Guess the CodeRay type of a file from its extension, or nil if
|
68
144
|
# unknown.
|
@@ -173,6 +249,23 @@ class Pry
|
|
173
249
|
end
|
174
250
|
end
|
175
251
|
|
252
|
+
# Take `num_lines` from `start_line`, forward or backwards
|
253
|
+
#
|
254
|
+
# @param [Fixnum] start_line
|
255
|
+
# @param [Fixnum] num_lines
|
256
|
+
# @return [Code]
|
257
|
+
def take_lines(start_line, num_lines)
|
258
|
+
if start_line >= 0
|
259
|
+
start_idx = @lines.index { |l| l.last >= start_line } || @lines.length
|
260
|
+
else
|
261
|
+
start_idx = @lines.length + start_line
|
262
|
+
end
|
263
|
+
|
264
|
+
alter do
|
265
|
+
@lines = @lines.slice(start_idx, num_lines)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
176
269
|
# Remove all lines except for the `lines` up to and excluding `line_num`.
|
177
270
|
#
|
178
271
|
# @param [Fixnum] line_num
|
data/lib/pry/command.rb
CHANGED
@@ -14,10 +14,15 @@ class Pry
|
|
14
14
|
# Properties of the command itself (as passed as arguments to
|
15
15
|
# {CommandSet#command} or {CommandSet#create_command}).
|
16
16
|
class << self
|
17
|
-
|
18
|
-
attr_accessor :name
|
17
|
+
attr_writer :block
|
19
18
|
attr_writer :description
|
20
19
|
attr_writer :command_options
|
20
|
+
attr_writer :match
|
21
|
+
|
22
|
+
def match(arg=nil)
|
23
|
+
@match = arg if arg
|
24
|
+
@match
|
25
|
+
end
|
21
26
|
|
22
27
|
# Define or get the command's description
|
23
28
|
def description(arg=nil)
|
@@ -40,24 +45,31 @@ class Pry
|
|
40
45
|
@banner = arg if arg
|
41
46
|
@banner || description
|
42
47
|
end
|
43
|
-
end
|
44
48
|
|
49
|
+
def block
|
50
|
+
@block || instance_method(:process) && instance_method(:process)
|
51
|
+
end
|
52
|
+
end
|
45
53
|
|
46
54
|
# Make those properties accessible to instances
|
47
55
|
def name; self.class.name; end
|
56
|
+
def match; self.class.match; end
|
48
57
|
def description; self.class.description; end
|
49
58
|
def block; self.class.block; end
|
50
59
|
def command_options; self.class.options; end
|
51
60
|
def command_name; command_options[:listing]; end
|
52
61
|
|
53
62
|
class << self
|
63
|
+
def name
|
64
|
+
super.to_s == "" ? "#<class(Pry::Command #{match.inspect})>" : super
|
65
|
+
end
|
54
66
|
def inspect
|
55
|
-
|
67
|
+
name
|
56
68
|
end
|
57
69
|
|
58
70
|
# Create a new command with the given properties.
|
59
71
|
#
|
60
|
-
# @param String
|
72
|
+
# @param String/Regex match the thing that triggers this command
|
61
73
|
# @param String description the description to appear in {help}
|
62
74
|
# @param Hash options behavioural options (@see {Pry::CommandSet#command})
|
63
75
|
# @param Module helpers a module of helper functions to be included.
|
@@ -65,10 +77,10 @@ class Pry
|
|
65
77
|
#
|
66
78
|
# @return Class (a subclass of Pry::Command)
|
67
79
|
#
|
68
|
-
def subclass(
|
80
|
+
def subclass(match, description, options, helpers, &block)
|
69
81
|
klass = Class.new(self)
|
70
82
|
klass.send(:include, helpers)
|
71
|
-
klass.
|
83
|
+
klass.match = match
|
72
84
|
klass.description = description
|
73
85
|
klass.command_options = options
|
74
86
|
klass.block = block
|
@@ -115,10 +127,11 @@ class Pry
|
|
115
127
|
end
|
116
128
|
|
117
129
|
def command_regex
|
118
|
-
|
130
|
+
pr = defined?(Pry.config.command_prefix) ? Pry.config.command_prefix : ""
|
131
|
+
prefix = convert_to_regex(pr)
|
119
132
|
prefix = "(?:#{prefix})?" unless options[:use_prefix]
|
120
133
|
|
121
|
-
/^#{prefix}#{convert_to_regex(
|
134
|
+
/^#{prefix}#{convert_to_regex(match)}(?!\S)/
|
122
135
|
end
|
123
136
|
|
124
137
|
def convert_to_regex(obj)
|
@@ -180,7 +193,7 @@ class Pry
|
|
180
193
|
# @example
|
181
194
|
# run "amend-line", "5", 'puts "hello world"'
|
182
195
|
def run(command_string, *args)
|
183
|
-
complete_string = "#{command_string} #{args.join(" ")}"
|
196
|
+
complete_string = "#{command_string} #{args.join(" ")}".rstrip
|
184
197
|
command_set.process_line(complete_string, context)
|
185
198
|
end
|
186
199
|
|
@@ -233,12 +246,12 @@ class Pry
|
|
233
246
|
# the current scope.
|
234
247
|
# @param [String] command_name_match The name of the colliding command.
|
235
248
|
# @param [Binding] target The current binding context.
|
236
|
-
def
|
237
|
-
collision_type = target.eval("defined?(#{
|
249
|
+
def check_for_command_collision(command_match, arg_string)
|
250
|
+
collision_type = target.eval("defined?(#{command_match})")
|
238
251
|
collision_type ||= 'local-variable' if arg_string.match(%r{\A\s*[-+*/%&|^]*=})
|
239
252
|
|
240
253
|
if collision_type
|
241
|
-
output.puts "#{Pry::Helpers::Text.bold('WARNING:')} Calling Pry command '#{
|
254
|
+
output.puts "#{Pry::Helpers::Text.bold('WARNING:')} Calling Pry command '#{command_match}'," +
|
242
255
|
"which conflicts with a #{collision_type}.\n\n"
|
243
256
|
end
|
244
257
|
rescue Pry::RescuableException
|
@@ -248,8 +261,8 @@ class Pry
|
|
248
261
|
#
|
249
262
|
# @param String the line of input
|
250
263
|
# @return [
|
251
|
-
# String the
|
252
|
-
# String a string of all the arguments (i.e. everything but the
|
264
|
+
# String the portion of the line that matched with the Command match
|
265
|
+
# String a string of all the arguments (i.e. everything but the match)
|
253
266
|
# Array the captures caught by the command_regex
|
254
267
|
# Array args the arguments got by splitting the arg_string
|
255
268
|
# ]
|
@@ -285,9 +298,9 @@ class Pry
|
|
285
298
|
# @param String the line to process
|
286
299
|
# @return Object or Command::VOID_VALUE
|
287
300
|
def process_line(line)
|
288
|
-
|
301
|
+
command_match, arg_string, captures, args = tokenize(line)
|
289
302
|
|
290
|
-
|
303
|
+
check_for_command_collision(command_match, arg_string) if Pry.config.collision_warning
|
291
304
|
|
292
305
|
self.arg_string = arg_string
|
293
306
|
self.captures = captures
|
@@ -310,7 +323,7 @@ class Pry
|
|
310
323
|
block_init_string = arg_string.slice!(block_index..-1)[1..-1]
|
311
324
|
prime_string = "proc #{block_init_string}\n"
|
312
325
|
|
313
|
-
if !
|
326
|
+
if !Pry::Code.complete_expression?(prime_string)
|
314
327
|
block_string = _pry_.r(target, prime_string)
|
315
328
|
else
|
316
329
|
block_string = prime_string
|
@@ -335,14 +348,14 @@ class Pry
|
|
335
348
|
unless dependencies_met?
|
336
349
|
gems_needed = Array(command_options[:requires_gem])
|
337
350
|
gems_not_installed = gems_needed.select { |g| !gem_installed?(g) }
|
338
|
-
output.puts "\nThe command '#{
|
351
|
+
output.puts "\nThe command '#{command_name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
|
339
352
|
output.puts "-"
|
340
|
-
output.puts "Type `install-command #{
|
353
|
+
output.puts "Type `install-command #{command_name}` to install the required gems and activate this command."
|
341
354
|
return void
|
342
355
|
end
|
343
356
|
|
344
357
|
if command_options[:argument_required] && args.empty?
|
345
|
-
raise CommandError, "The command '#{
|
358
|
+
raise CommandError, "The command '#{command_name}' requires an argument."
|
346
359
|
end
|
347
360
|
|
348
361
|
ret = call_with_hooks(*args)
|
@@ -507,6 +520,6 @@ class Pry
|
|
507
520
|
# gist_method
|
508
521
|
# end
|
509
522
|
# end
|
510
|
-
def process; raise CommandError, "command '#{
|
523
|
+
def process; raise CommandError, "command '#{command_name}' not implemented" end
|
511
524
|
end
|
512
525
|
end
|
data/lib/pry/command_set.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Pry
|
2
2
|
class NoCommandError < StandardError
|
3
|
-
def initialize(
|
4
|
-
super "Command '#{
|
3
|
+
def initialize(match, owner)
|
4
|
+
super "Command '#{match}' not found in command set #{owner}"
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
@@ -27,8 +27,7 @@ class Pry
|
|
27
27
|
end
|
28
28
|
|
29
29
|
# Defines a new Pry command.
|
30
|
-
# @param [String, Regexp]
|
31
|
-
# Regexp as well as String.
|
30
|
+
# @param [String, Regexp] match The start of invocations of this command.
|
32
31
|
# @param [String] description A description of the command.
|
33
32
|
# @param [Hash] options The optional configuration parameters.
|
34
33
|
# @option options [Boolean] :keep_retval Whether or not to use return value
|
@@ -43,7 +42,7 @@ class Pry
|
|
43
42
|
# executing the command. Defaults to true.
|
44
43
|
# @option options [String] :listing The listing name of the
|
45
44
|
# command. That is the name by which the command is looked up by
|
46
|
-
# help and by show-command. Necessary for regex
|
45
|
+
# help and by show-command. Necessary for commands with regex matches.
|
47
46
|
# @option options [Boolean] :use_prefix Whether the command uses
|
48
47
|
# `Pry.config.command_prefix` prefix (if one is defined). Defaults
|
49
48
|
# to true.
|
@@ -80,18 +79,17 @@ class Pry
|
|
80
79
|
# # hello john, nice number: 10
|
81
80
|
# # pry(main)> help number
|
82
81
|
# # number-N regex command
|
83
|
-
def block_command(
|
82
|
+
def block_command(match, description="No description.", options={}, &block)
|
84
83
|
description, options = ["No description.", description] if description.is_a?(Hash)
|
85
|
-
options = default_options(
|
84
|
+
options = default_options(match).merge!(options)
|
86
85
|
|
87
|
-
commands[
|
86
|
+
commands[match] = Pry::BlockCommand.subclass(match, description, options, helper_module, &block)
|
88
87
|
end
|
89
88
|
alias_method :command, :block_command
|
90
89
|
|
91
90
|
# Defines a new Pry command class.
|
92
91
|
#
|
93
|
-
# @param [String, Regexp]
|
94
|
-
# Regexp as well as String.
|
92
|
+
# @param [String, Regexp] match The start of invocations of this command.
|
95
93
|
# @param [String] description A description of the command.
|
96
94
|
# @param [Hash] options The optional configuration parameters, see {#command}
|
97
95
|
# @param &Block The class body's definition.
|
@@ -113,40 +111,40 @@ class Pry
|
|
113
111
|
# end
|
114
112
|
# end
|
115
113
|
#
|
116
|
-
def create_command(
|
114
|
+
def create_command(match, description="No description.", options={}, &block)
|
117
115
|
description, options = ["No description.", description] if description.is_a?(Hash)
|
118
|
-
options = default_options(
|
116
|
+
options = default_options(match).merge!(options)
|
119
117
|
|
120
|
-
commands[
|
121
|
-
commands[
|
122
|
-
commands[
|
118
|
+
commands[match] = Pry::ClassCommand.subclass(match, description, options, helper_module, &block)
|
119
|
+
commands[match].class_eval(&block)
|
120
|
+
commands[match]
|
123
121
|
end
|
124
122
|
|
125
123
|
# Execute a block of code before a command is invoked. The block also
|
126
124
|
# gets access to parameters that will be passed to the command and
|
127
125
|
# is evaluated in the same context.
|
128
|
-
# @param [String, Regexp]
|
126
|
+
# @param [String, Regexp] search The match or listing of the command.
|
129
127
|
# @yield The block to be run before the command.
|
130
128
|
# @example Display parameter before invoking command
|
131
129
|
# Pry.commands.before_command("whereami") do |n|
|
132
130
|
# output.puts "parameter passed was #{n}"
|
133
131
|
# end
|
134
|
-
def before_command(
|
135
|
-
cmd =
|
132
|
+
def before_command(search, &block)
|
133
|
+
cmd = find_command_by_match_or_listing(search)
|
136
134
|
cmd.hooks[:before].unshift block
|
137
135
|
end
|
138
136
|
|
139
137
|
# Execute a block of code after a command is invoked. The block also
|
140
138
|
# gets access to parameters that will be passed to the command and
|
141
139
|
# is evaluated in the same context.
|
142
|
-
# @param [String, Regexp]
|
140
|
+
# @param [String, Regexp] search The match or listing of the command.
|
143
141
|
# @yield The block to be run after the command.
|
144
142
|
# @example Display text 'command complete' after invoking command
|
145
143
|
# Pry.commands.after_command("whereami") do |n|
|
146
144
|
# output.puts "command complete!"
|
147
145
|
# end
|
148
|
-
def after_command(
|
149
|
-
cmd =
|
146
|
+
def after_command(search, &block)
|
147
|
+
cmd = find_command_by_match_or_listing(search)
|
150
148
|
cmd.hooks[:after] << block
|
151
149
|
end
|
152
150
|
|
@@ -154,91 +152,122 @@ class Pry
|
|
154
152
|
@commands.each(&block)
|
155
153
|
end
|
156
154
|
|
155
|
+
# Add a given command object to this set.
|
156
|
+
# @param Command the subclass of Pry::Command you wish to add.
|
157
|
+
def add_command(command)
|
158
|
+
commands[command.match] = command
|
159
|
+
end
|
160
|
+
|
157
161
|
# Removes some commands from the set
|
158
|
-
# @param [Array<String>]
|
159
|
-
def delete(*
|
160
|
-
|
161
|
-
cmd =
|
162
|
-
commands.delete cmd.
|
162
|
+
# @param [Array<String>] searches the matches or listings of the commands to remove
|
163
|
+
def delete(*searches)
|
164
|
+
searches.each do |search|
|
165
|
+
cmd = find_command_by_match_or_listing(search)
|
166
|
+
commands.delete cmd.match
|
163
167
|
end
|
164
168
|
end
|
165
169
|
|
166
170
|
# Imports all the commands from one or more sets.
|
167
171
|
# @param [Array<CommandSet>] sets Command sets, all of the commands of which
|
168
172
|
# will be imported.
|
173
|
+
# @return [Pry::CommandSet] Returns the reciever (a command set).
|
169
174
|
def import(*sets)
|
170
175
|
sets.each do |set|
|
171
176
|
commands.merge! set.commands
|
172
177
|
helper_module.send :include, set.helper_module
|
173
178
|
end
|
179
|
+
self
|
174
180
|
end
|
175
181
|
|
176
182
|
# Imports some commands from a set
|
177
183
|
# @param [CommandSet] set Set to import commands from
|
178
|
-
# @param [Array<String>]
|
179
|
-
|
184
|
+
# @param [Array<String>] matches Commands to import
|
185
|
+
# @return [Pry::CommandSet] Returns the reciever (a command set).
|
186
|
+
def import_from(set, *matches)
|
180
187
|
helper_module.send :include, set.helper_module
|
181
|
-
|
182
|
-
cmd = set.
|
183
|
-
commands[cmd.
|
188
|
+
matches.each do |match|
|
189
|
+
cmd = set.find_command_by_match_or_listing(match)
|
190
|
+
commands[cmd.match] = cmd
|
184
191
|
end
|
192
|
+
self
|
185
193
|
end
|
186
194
|
|
187
|
-
# @param [String, Regexp]
|
195
|
+
# @param [String, Regexp] match_or_listing The match or listing of a command.
|
188
196
|
# of the command to retrieve.
|
189
197
|
# @return [Command] The command object matched.
|
190
|
-
def
|
191
|
-
if commands[
|
192
|
-
cmd = commands[
|
198
|
+
def find_command_by_match_or_listing(match_or_listing)
|
199
|
+
if commands[match_or_listing]
|
200
|
+
cmd = commands[match_or_listing]
|
193
201
|
else
|
194
|
-
_, cmd = commands.find { |
|
202
|
+
_, cmd = commands.find { |match, command| command.options[:listing] == match_or_listing }
|
195
203
|
end
|
196
204
|
|
197
|
-
raise ArgumentError, "Cannot find a command
|
205
|
+
raise ArgumentError, "Cannot find a command: '#{match_or_listing}'!" if !cmd
|
198
206
|
cmd
|
199
207
|
end
|
200
|
-
protected :
|
208
|
+
protected :find_command_by_match_or_listing
|
201
209
|
|
202
210
|
# Aliases a command
|
203
|
-
#
|
204
|
-
#
|
205
|
-
# @param [String,
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
+
# Note that if `desc` parameter is `nil` then the default
|
212
|
+
# description is used.
|
213
|
+
# @param [String, Regex] match The match of the alias (can be a regex).
|
214
|
+
# @param [String] action The action to be performed (typically
|
215
|
+
# another command).
|
216
|
+
# @param [Hash] options The optional configuration parameters,
|
217
|
+
# accepts the same as the `command` method, but also allows the
|
218
|
+
# command description to be passed this way too as `:desc`
|
219
|
+
# @example Creating an alias for `ls -M`
|
220
|
+
# Pry.config.commands.alias_command "lM", "ls -M"
|
221
|
+
# @example Pass explicit description (overriding default).
|
222
|
+
# Pry.config.commands.alias_command "lM", "ls -M", :desc => "cutiepie"
|
223
|
+
def alias_command(match, action, options={})
|
224
|
+
original_options = find_command(action).options.dup
|
225
|
+
|
226
|
+
options = original_options.merge!({
|
227
|
+
:desc => "Alias for `#{action}`",
|
228
|
+
:listing => match
|
229
|
+
}).merge!(options)
|
230
|
+
|
231
|
+
# ensure default description is used if desc is nil
|
232
|
+
desc = options.delete(:desc).to_s
|
233
|
+
|
234
|
+
c = block_command match, desc, options do |*args|
|
235
|
+
run action, *args
|
236
|
+
end
|
237
|
+
|
238
|
+
c.group "Aliases"
|
239
|
+
|
240
|
+
c
|
211
241
|
end
|
212
242
|
|
213
|
-
# Rename a command. Accepts either
|
214
|
-
#
|
215
|
-
#
|
216
|
-
# @param [String, Regexp]
|
217
|
-
# @param [String, Regexp] old_name The command's current name.
|
243
|
+
# Rename a command. Accepts either match or listing for the search.
|
244
|
+
#
|
245
|
+
# @param [String, Regexp] new_name The new match for the command.
|
246
|
+
# @param [String, Regexp] search The command's current match or listing.
|
218
247
|
# @param [Hash] options The optional configuration parameters,
|
219
248
|
# accepts the same as the `command` method, but also allows the
|
220
249
|
# command description to be passed this way too.
|
221
250
|
# @example Renaming the `ls` command and changing its description.
|
222
251
|
# Pry.config.commands.rename "dir", "ls", :description => "DOS friendly ls"
|
223
|
-
def rename_command(
|
224
|
-
cmd =
|
252
|
+
def rename_command(new_match, search, options={})
|
253
|
+
cmd = find_command_by_match_or_listing(search)
|
225
254
|
|
226
255
|
options = {
|
227
|
-
:listing =>
|
256
|
+
:listing => new_match,
|
228
257
|
:description => cmd.description
|
229
258
|
}.merge!(options)
|
230
259
|
|
231
|
-
commands[
|
232
|
-
commands[
|
233
|
-
commands[
|
234
|
-
commands[
|
235
|
-
commands.delete(cmd.
|
260
|
+
commands[new_match] = cmd.dup
|
261
|
+
commands[new_match].match = new_match
|
262
|
+
commands[new_match].description = options.delete(:description)
|
263
|
+
commands[new_match].options.merge!(options)
|
264
|
+
commands.delete(cmd.match)
|
236
265
|
end
|
237
266
|
|
238
267
|
# Sets or gets the description for a command (replacing the old
|
239
268
|
# description). Returns current description if no description
|
240
269
|
# parameter provided.
|
241
|
-
# @param [String, Regexp]
|
270
|
+
# @param [String, Regexp] match The command match.
|
242
271
|
# @param [String] description The command description.
|
243
272
|
# @example Setting
|
244
273
|
# MyCommands = Pry::CommandSet.new do
|
@@ -246,8 +275,8 @@ class Pry
|
|
246
275
|
# end
|
247
276
|
# @example Getting
|
248
277
|
# Pry.config.commands.desc "amend-line"
|
249
|
-
def desc(
|
250
|
-
cmd =
|
278
|
+
def desc(search, description=nil)
|
279
|
+
cmd = find_command_by_match_or_listing(search)
|
251
280
|
return cmd.description if !description
|
252
281
|
|
253
282
|
cmd.description = description
|
@@ -282,6 +311,7 @@ class Pry
|
|
282
311
|
def find_command(val)
|
283
312
|
commands.values.select{ |c| c.matches?(val) }.sort_by{ |c| c.match_score(val) }.last
|
284
313
|
end
|
314
|
+
alias_method :[], :find_command
|
285
315
|
|
286
316
|
# Find the command that the user might be trying to refer to.
|
287
317
|
#
|
@@ -289,7 +319,7 @@ class Pry
|
|
289
319
|
# @return [Pry::Command, nil]
|
290
320
|
def find_command_for_help(search)
|
291
321
|
find_command(search) || (begin
|
292
|
-
|
322
|
+
find_command_by_match_or_listing(search)
|
293
323
|
rescue ArgumentError
|
294
324
|
nil
|
295
325
|
end)
|
@@ -320,21 +350,21 @@ class Pry
|
|
320
350
|
end
|
321
351
|
|
322
352
|
# @nodoc used for testing
|
323
|
-
def run_command(context,
|
324
|
-
command = commands[
|
353
|
+
def run_command(context, match, *args)
|
354
|
+
command = commands[match] or raise NoCommandError.new(match, self)
|
325
355
|
command.new(context).call_safely(*args)
|
326
356
|
end
|
327
357
|
|
328
358
|
private
|
329
359
|
|
330
|
-
def default_options(
|
360
|
+
def default_options(match)
|
331
361
|
{
|
332
362
|
:requires_gem => [],
|
333
363
|
:keep_retval => false,
|
334
364
|
:argument_required => false,
|
335
365
|
:interpolate => true,
|
336
366
|
:shellwords => true,
|
337
|
-
:listing =>
|
367
|
+
:listing => (String === match ? match : match.inspect),
|
338
368
|
:use_prefix => true,
|
339
369
|
:takes_block => false
|
340
370
|
}
|