pry 0.10.3 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +439 -16
- data/LICENSE +1 -1
- data/README.md +362 -302
- data/bin/pry +4 -7
- data/lib/pry/basic_object.rb +10 -0
- data/lib/pry/block_command.rb +22 -0
- data/lib/pry/class_command.rb +194 -0
- data/lib/pry/cli.rb +84 -97
- data/lib/pry/code/code_file.rb +37 -26
- data/lib/pry/code/code_range.rb +7 -5
- data/lib/pry/code/loc.rb +26 -13
- data/lib/pry/code.rb +42 -31
- data/lib/pry/code_object.rb +53 -28
- data/lib/pry/color_printer.rb +46 -35
- data/lib/pry/command.rb +197 -369
- data/lib/pry/command_set.rb +89 -114
- data/lib/pry/command_state.rb +31 -0
- data/lib/pry/commands/amend_line.rb +86 -82
- data/lib/pry/commands/bang.rb +18 -14
- data/lib/pry/commands/bang_pry.rb +15 -11
- data/lib/pry/commands/cat/abstract_formatter.rb +23 -18
- data/lib/pry/commands/cat/exception_formatter.rb +85 -72
- data/lib/pry/commands/cat/file_formatter.rb +56 -46
- data/lib/pry/commands/cat/input_expression_formatter.rb +35 -30
- data/lib/pry/commands/cat.rb +62 -54
- data/lib/pry/commands/cd.rb +40 -35
- data/lib/pry/commands/change_inspector.rb +29 -22
- data/lib/pry/commands/change_prompt.rb +48 -23
- data/lib/pry/commands/clear_screen.rb +20 -0
- data/lib/pry/commands/code_collector.rb +148 -131
- data/lib/pry/commands/disable_pry.rb +23 -19
- data/lib/pry/commands/easter_eggs.rb +23 -34
- data/lib/pry/commands/edit/exception_patcher.rb +21 -17
- data/lib/pry/commands/edit/file_and_line_locator.rb +34 -23
- data/lib/pry/commands/edit.rb +185 -157
- data/lib/pry/commands/exit.rb +40 -35
- data/lib/pry/commands/exit_all.rb +24 -20
- data/lib/pry/commands/exit_program.rb +20 -16
- data/lib/pry/commands/find_method.rb +168 -162
- data/lib/pry/commands/fix_indent.rb +16 -12
- data/lib/pry/commands/help.rb +140 -133
- data/lib/pry/commands/hist.rb +151 -149
- data/lib/pry/commands/import_set.rb +20 -15
- data/lib/pry/commands/jump_to.rb +25 -21
- data/lib/pry/commands/list_inspectors.rb +35 -28
- data/lib/pry/commands/ls/constants.rb +59 -31
- data/lib/pry/commands/ls/formatter.rb +42 -36
- data/lib/pry/commands/ls/globals.rb +38 -36
- data/lib/pry/commands/ls/grep.rb +17 -15
- data/lib/pry/commands/ls/instance_vars.rb +29 -28
- data/lib/pry/commands/ls/interrogatable.rb +18 -12
- data/lib/pry/commands/ls/jruby_hacks.rb +47 -41
- data/lib/pry/commands/ls/local_names.rb +26 -24
- data/lib/pry/commands/ls/local_vars.rb +38 -30
- data/lib/pry/commands/ls/ls_entity.rb +47 -52
- data/lib/pry/commands/ls/methods.rb +49 -51
- data/lib/pry/commands/ls/methods_helper.rb +46 -42
- data/lib/pry/commands/ls/self_methods.rb +23 -21
- data/lib/pry/commands/ls.rb +124 -103
- data/lib/pry/commands/nesting.rb +21 -17
- data/lib/pry/commands/play.rb +92 -82
- data/lib/pry/commands/pry_backtrace.rb +22 -17
- data/lib/pry/commands/pry_version.rb +15 -11
- data/lib/pry/commands/raise_up.rb +33 -27
- data/lib/pry/commands/reload_code.rb +60 -48
- data/lib/pry/commands/reset.rb +16 -12
- data/lib/pry/commands/ri.rb +57 -42
- data/lib/pry/commands/save_file.rb +45 -43
- data/lib/pry/commands/shell_command.rb +56 -29
- data/lib/pry/commands/shell_mode.rb +22 -18
- data/lib/pry/commands/show_doc.rb +80 -70
- data/lib/pry/commands/show_info.rb +194 -155
- data/lib/pry/commands/show_input.rb +16 -11
- data/lib/pry/commands/show_source.rb +110 -42
- data/lib/pry/commands/stat.rb +35 -31
- data/lib/pry/commands/switch_to.rb +21 -15
- data/lib/pry/commands/toggle_color.rb +20 -16
- data/lib/pry/commands/watch_expression/expression.rb +32 -27
- data/lib/pry/commands/watch_expression.rb +89 -84
- data/lib/pry/commands/whereami.rb +156 -141
- data/lib/pry/commands/wtf.rb +78 -40
- data/lib/pry/config/attributable.rb +22 -0
- data/lib/pry/config/lazy_value.rb +29 -0
- data/lib/pry/config/memoized_value.rb +34 -0
- data/lib/pry/config/value.rb +24 -0
- data/lib/pry/config.rb +310 -20
- data/lib/pry/control_d_handler.rb +28 -0
- data/lib/pry/core_extensions.rb +22 -9
- data/lib/pry/editor.rb +56 -34
- data/lib/pry/env.rb +18 -0
- data/lib/pry/exception_handler.rb +43 -0
- data/lib/pry/exceptions.rb +13 -18
- data/lib/pry/forwardable.rb +27 -0
- data/lib/pry/helpers/base_helpers.rb +20 -62
- data/lib/pry/helpers/command_helpers.rb +52 -62
- data/lib/pry/helpers/documentation_helpers.rb +21 -12
- data/lib/pry/helpers/options_helpers.rb +15 -8
- data/lib/pry/helpers/platform.rb +55 -0
- data/lib/pry/helpers/table.rb +44 -32
- data/lib/pry/helpers/text.rb +96 -85
- data/lib/pry/helpers.rb +3 -0
- data/lib/pry/history.rb +81 -55
- data/lib/pry/hooks.rb +60 -110
- data/lib/pry/indent.rb +74 -68
- data/lib/pry/input_completer.rb +199 -158
- data/lib/pry/input_lock.rb +7 -10
- data/lib/pry/inspector.rb +36 -24
- data/lib/pry/last_exception.rb +45 -45
- data/lib/pry/method/disowned.rb +19 -5
- data/lib/pry/method/patcher.rb +14 -8
- data/lib/pry/method/weird_method_locator.rb +79 -45
- data/lib/pry/method.rb +178 -124
- data/lib/pry/object_path.rb +37 -28
- data/lib/pry/output.rb +102 -16
- data/lib/pry/pager.rb +187 -174
- data/lib/pry/prompt.rb +213 -25
- data/lib/pry/pry_class.rb +119 -98
- data/lib/pry/pry_instance.rb +261 -224
- data/lib/pry/repl.rb +83 -29
- data/lib/pry/repl_file_loader.rb +27 -22
- data/lib/pry/ring.rb +89 -0
- data/lib/pry/slop/LICENSE +20 -0
- data/lib/pry/slop/commands.rb +190 -0
- data/lib/pry/slop/option.rb +210 -0
- data/lib/pry/slop.rb +672 -0
- data/lib/pry/syntax_highlighter.rb +26 -0
- data/lib/pry/system_command_handler.rb +17 -0
- data/lib/pry/testable/evalable.rb +24 -0
- data/lib/pry/testable/mockable.rb +22 -0
- data/lib/pry/testable/pry_tester.rb +88 -0
- data/lib/pry/testable/utility.rb +34 -0
- data/lib/pry/testable/variables.rb +52 -0
- data/lib/pry/testable.rb +68 -0
- data/lib/pry/version.rb +3 -1
- data/lib/pry/warning.rb +20 -0
- data/lib/pry/{module_candidate.rb → wrapped_module/candidate.rb} +35 -32
- data/lib/pry/wrapped_module.rb +68 -63
- data/lib/pry.rb +133 -149
- metadata +58 -69
- data/lib/pry/commands/disabled_commands.rb +0 -2
- data/lib/pry/commands/gem_cd.rb +0 -26
- data/lib/pry/commands/gem_install.rb +0 -32
- data/lib/pry/commands/gem_list.rb +0 -33
- data/lib/pry/commands/gem_open.rb +0 -29
- data/lib/pry/commands/gist.rb +0 -101
- data/lib/pry/commands/install_command.rb +0 -53
- data/lib/pry/commands/list_prompts.rb +0 -35
- data/lib/pry/commands/simple_prompt.rb +0 -22
- data/lib/pry/commands.rb +0 -6
- data/lib/pry/config/behavior.rb +0 -139
- data/lib/pry/config/convenience.rb +0 -25
- data/lib/pry/config/default.rb +0 -161
- data/lib/pry/history_array.rb +0 -121
- data/lib/pry/plugins.rb +0 -103
- data/lib/pry/rbx_path.rb +0 -22
- data/lib/pry/rubygem.rb +0 -82
- data/lib/pry/terminal.rb +0 -79
- data/lib/pry/test/helper.rb +0 -170
data/lib/pry/command.rb
CHANGED
@@ -1,20 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'delegate'
|
2
|
-
require '
|
4
|
+
require 'shellwords'
|
3
5
|
|
4
6
|
class Pry
|
5
|
-
|
6
7
|
# The super-class of all commands, new commands should be created by calling
|
7
|
-
# {Pry::CommandSet#command} which creates a BlockCommand or
|
8
|
-
# which creates a ClassCommand. Please don't
|
8
|
+
# {Pry::CommandSet#command} which creates a BlockCommand or
|
9
|
+
# {Pry::CommandSet#create_command} which creates a ClassCommand. Please don't
|
10
|
+
# use this class directly.
|
9
11
|
class Command
|
10
12
|
extend Helpers::DocumentationHelpers
|
11
13
|
extend CodeObject::Helpers
|
12
14
|
|
15
|
+
include Pry::Helpers::BaseHelpers
|
16
|
+
include Pry::Helpers::CommandHelpers
|
17
|
+
include Pry::Helpers::Text
|
18
|
+
|
13
19
|
# represents a void return value for a command
|
14
20
|
VOID_VALUE = Object.new
|
15
21
|
|
16
22
|
# give it a nice inspect
|
17
|
-
def VOID_VALUE.inspect
|
23
|
+
def VOID_VALUE.inspect
|
24
|
+
"void"
|
25
|
+
end
|
18
26
|
|
19
27
|
# Properties of the command itself (as passed as arguments to
|
20
28
|
# {CommandSet#command} or {CommandSet#create_command}).
|
@@ -24,7 +32,7 @@ class Pry
|
|
24
32
|
attr_writer :command_options
|
25
33
|
attr_writer :match
|
26
34
|
|
27
|
-
def match(arg=nil)
|
35
|
+
def match(arg = nil)
|
28
36
|
if arg
|
29
37
|
@command_options ||= default_options(arg)
|
30
38
|
@command_options[:listing] = arg.is_a?(String) ? arg : arg.inspect
|
@@ -34,25 +42,25 @@ class Pry
|
|
34
42
|
end
|
35
43
|
|
36
44
|
# Define or get the command's description
|
37
|
-
def description(arg=nil)
|
45
|
+
def description(arg = nil)
|
38
46
|
@description = arg if arg
|
39
47
|
@description ||= nil
|
40
48
|
end
|
41
49
|
|
42
50
|
# Define or get the command's options
|
43
|
-
def command_options(arg=nil)
|
51
|
+
def command_options(arg = nil)
|
44
52
|
@command_options ||= default_options(match)
|
45
53
|
@command_options.merge!(arg) if arg
|
46
54
|
@command_options
|
47
55
|
end
|
48
56
|
# backward compatibility
|
49
|
-
|
50
|
-
|
57
|
+
alias options command_options
|
58
|
+
alias options= command_options=
|
51
59
|
|
52
60
|
# Define or get the command's banner
|
53
|
-
def banner(arg=nil)
|
61
|
+
def banner(arg = nil)
|
54
62
|
@banner = arg if arg
|
55
|
-
@banner
|
63
|
+
@banner ||= description
|
56
64
|
end
|
57
65
|
|
58
66
|
def block
|
@@ -68,45 +76,28 @@ class Pry
|
|
68
76
|
new.help
|
69
77
|
end
|
70
78
|
|
71
|
-
def source_location
|
72
|
-
block.source_location
|
73
|
-
end
|
74
|
-
|
75
79
|
def source_file
|
76
80
|
Array(block.source_location).first
|
77
81
|
end
|
78
|
-
|
82
|
+
alias file source_file
|
79
83
|
|
80
84
|
def source_line
|
81
85
|
Array(block.source_location).last
|
82
86
|
end
|
83
|
-
|
87
|
+
alias line source_line
|
84
88
|
|
85
89
|
def default_options(match)
|
86
90
|
{
|
87
|
-
:
|
88
|
-
:
|
89
|
-
:
|
90
|
-
:
|
91
|
-
:
|
92
|
-
:
|
93
|
-
:
|
94
|
-
:takes_block => false
|
91
|
+
keep_retval: false,
|
92
|
+
argument_required: false,
|
93
|
+
interpolate: true,
|
94
|
+
shellwords: true,
|
95
|
+
listing: (match.is_a?(String) ? match : match.inspect),
|
96
|
+
use_prefix: true,
|
97
|
+
takes_block: false
|
95
98
|
}
|
96
99
|
end
|
97
|
-
end
|
98
100
|
|
99
|
-
# Make those properties accessible to instances
|
100
|
-
def name; self.class.name; end
|
101
|
-
def match; self.class.match; end
|
102
|
-
def description; self.class.description; end
|
103
|
-
def block; self.class.block; end
|
104
|
-
def command_options; self.class.options; end
|
105
|
-
def command_name; self.class.command_name; end
|
106
|
-
def source; self.class.source; end
|
107
|
-
def source_location; self.class.source_location; end
|
108
|
-
|
109
|
-
class << self
|
110
101
|
def name
|
111
102
|
super.to_s == "" ? "#<class(Pry::Command #{match.inspect})>" : super
|
112
103
|
end
|
@@ -116,7 +107,7 @@ class Pry
|
|
116
107
|
end
|
117
108
|
|
118
109
|
def command_name
|
119
|
-
|
110
|
+
options[:listing]
|
120
111
|
end
|
121
112
|
|
122
113
|
# Create a new command with the given properties.
|
@@ -161,25 +152,21 @@ class Pry
|
|
161
152
|
# @return [Fixnum]
|
162
153
|
def match_score(val)
|
163
154
|
if command_regex =~ val
|
164
|
-
Regexp.last_match.size > 1
|
155
|
+
if Regexp.last_match.size > 1
|
156
|
+
Regexp.last_match.begin(1)
|
157
|
+
else
|
158
|
+
Regexp.last_match.end(0)
|
159
|
+
end
|
165
160
|
else
|
166
161
|
-1
|
167
162
|
end
|
168
163
|
end
|
169
164
|
|
170
|
-
# Store hooks to be run before or after the command body.
|
171
|
-
# @see {Pry::CommandSet#before_command}
|
172
|
-
# @see {Pry::CommandSet#after_command}
|
173
|
-
def hooks
|
174
|
-
@hooks ||= {:before => [], :after => []}
|
175
|
-
end
|
176
|
-
|
177
165
|
def command_regex
|
178
|
-
|
179
|
-
prefix = convert_to_regex(pr)
|
166
|
+
prefix = convert_to_regex(Pry.config.command_prefix)
|
180
167
|
prefix = "(?:#{prefix})?" unless options[:use_prefix]
|
181
168
|
|
182
|
-
|
169
|
+
/\A#{prefix}#{convert_to_regex(match)}(?!\S)/
|
183
170
|
end
|
184
171
|
|
185
172
|
def convert_to_regex(obj)
|
@@ -195,22 +182,25 @@ class Pry
|
|
195
182
|
# This is usually auto-generated from directory naming, but it can be
|
196
183
|
# manually overridden if necessary.
|
197
184
|
# Group should not be changed once it is initialized.
|
198
|
-
def group(name=nil)
|
199
|
-
@group ||=
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
185
|
+
def group(name = nil)
|
186
|
+
@group ||= begin
|
187
|
+
name || case Pry::Method(block).source_file
|
188
|
+
when %r{/pry/.*_commands/(.*).rb}
|
189
|
+
Regexp.last_match(1).capitalize.tr('_', " ")
|
190
|
+
when /(pry-\w+)-([\d\.]+([\w\.]+)?)/
|
191
|
+
name = Regexp.last_match(1)
|
192
|
+
version = Regexp.last_match(2)
|
193
|
+
"#{name} (v#{version})"
|
194
|
+
when /pryrc/
|
195
|
+
"pryrc"
|
196
|
+
else
|
197
|
+
"(other)"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def state
|
203
|
+
Pry::CommandState.default.state_for(match)
|
214
204
|
end
|
215
205
|
end
|
216
206
|
|
@@ -223,7 +213,9 @@ class Pry
|
|
223
213
|
attr_accessor :arg_string
|
224
214
|
attr_accessor :context
|
225
215
|
attr_accessor :command_set
|
226
|
-
attr_accessor :
|
216
|
+
attr_accessor :hooks
|
217
|
+
attr_accessor :pry_instance
|
218
|
+
alias _pry_= pry_instance=
|
227
219
|
|
228
220
|
# The block we pass *into* a command so long as `:takes_block` is
|
229
221
|
# not equal to `false`
|
@@ -233,6 +225,47 @@ class Pry
|
|
233
225
|
# end
|
234
226
|
attr_accessor :command_block
|
235
227
|
|
228
|
+
# Instantiate a command, in preparation for calling it.
|
229
|
+
# @param [Hash] context The runtime context to use with this command.
|
230
|
+
def initialize(context = {})
|
231
|
+
self.context = context
|
232
|
+
self.target = context[:target]
|
233
|
+
self.output = context[:output]
|
234
|
+
self.eval_string = context[:eval_string]
|
235
|
+
self.command_set = context[:command_set]
|
236
|
+
self.hooks = context[:hooks]
|
237
|
+
self.pry_instance = context[:pry_instance]
|
238
|
+
end
|
239
|
+
|
240
|
+
# Make those properties accessible to instances
|
241
|
+
def name
|
242
|
+
self.class.name
|
243
|
+
end
|
244
|
+
|
245
|
+
def match
|
246
|
+
self.class.match
|
247
|
+
end
|
248
|
+
|
249
|
+
def description
|
250
|
+
self.class.description
|
251
|
+
end
|
252
|
+
|
253
|
+
def block
|
254
|
+
self.class.block
|
255
|
+
end
|
256
|
+
|
257
|
+
def command_options
|
258
|
+
self.class.options
|
259
|
+
end
|
260
|
+
|
261
|
+
def command_name
|
262
|
+
self.class.command_name
|
263
|
+
end
|
264
|
+
|
265
|
+
def source
|
266
|
+
self.class.source
|
267
|
+
end
|
268
|
+
|
236
269
|
# Run a command from another command.
|
237
270
|
# @param [String] command_string The string that invokes the command
|
238
271
|
# @param [Array] args Further arguments to pass to the command
|
@@ -243,8 +276,8 @@ class Pry
|
|
243
276
|
# @example
|
244
277
|
# run "amend-line", "5", 'puts "hello world"'
|
245
278
|
def run(command_string, *args)
|
246
|
-
command_string =
|
247
|
-
complete_string = "#{command_string} #{args.join(
|
279
|
+
command_string = pry_instance.config.command_prefix.to_s + command_string
|
280
|
+
complete_string = "#{command_string} #{args.join(' ')}".rstrip
|
248
281
|
command_set.process_line(complete_string, context)
|
249
282
|
end
|
250
283
|
|
@@ -252,30 +285,19 @@ class Pry
|
|
252
285
|
command_set.to_hash
|
253
286
|
end
|
254
287
|
|
255
|
-
def text
|
256
|
-
Pry::Helpers::Text
|
257
|
-
end
|
258
|
-
|
259
288
|
def void
|
260
289
|
VOID_VALUE
|
261
290
|
end
|
262
291
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
# Instantiate a command, in preparation for calling it.
|
267
|
-
# @param [Hash] context The runtime context to use with this command.
|
268
|
-
def initialize(context={})
|
269
|
-
self.context = context
|
270
|
-
self.target = context[:target]
|
271
|
-
self.output = context[:output]
|
272
|
-
self.eval_string = context[:eval_string]
|
273
|
-
self.command_set = context[:command_set]
|
274
|
-
self._pry_ = context[:pry_instance]
|
292
|
+
def _pry_
|
293
|
+
Pry::Warning.warn('_pry_ is deprecated, use pry_instance instead')
|
294
|
+
pry_instance
|
275
295
|
end
|
276
296
|
|
277
297
|
# @return [Object] The value of `self` inside the `target` binding.
|
278
|
-
def target_self
|
298
|
+
def target_self
|
299
|
+
target.eval('self')
|
300
|
+
end
|
279
301
|
|
280
302
|
# @return [Hash] Pry commands can store arbitrary state
|
281
303
|
# here. This state persists between subsequent command invocations.
|
@@ -285,7 +307,7 @@ class Pry
|
|
285
307
|
# state.my_state = "my state" # this will not conflict with any
|
286
308
|
# # `state.my_state` used in another command.
|
287
309
|
def state
|
288
|
-
|
310
|
+
self.class.state
|
289
311
|
end
|
290
312
|
|
291
313
|
# Revaluate the string (str) and perform interpolation.
|
@@ -306,12 +328,15 @@ class Pry
|
|
306
328
|
# the current scope.
|
307
329
|
def check_for_command_collision(command_match, arg_string)
|
308
330
|
collision_type = target.eval("defined?(#{command_match})")
|
309
|
-
collision_type ||= 'local-variable' if arg_string
|
331
|
+
collision_type ||= 'local-variable' if arg_string =~ %r{\A\s*[-+*/%&|^]*=}
|
310
332
|
|
311
333
|
if collision_type
|
312
|
-
output.puts
|
334
|
+
output.puts(
|
335
|
+
"#{Helpers::Text.bold('WARNING:')} Calling Pry command '#{command_match}', " \
|
336
|
+
"which conflicts with a #{collision_type}.\n\n"
|
337
|
+
)
|
313
338
|
end
|
314
|
-
rescue Pry::RescuableException
|
339
|
+
rescue Pry::RescuableException # rubocop:disable Lint/HandleExceptions
|
315
340
|
end
|
316
341
|
|
317
342
|
# Extract necessary information from a line that Command.matches? this
|
@@ -329,12 +354,15 @@ class Pry
|
|
329
354
|
# @param [String] val The line of input
|
330
355
|
# @return [Array]
|
331
356
|
def tokenize(val)
|
332
|
-
val
|
357
|
+
val = interpolate_string(val) if command_options[:interpolate]
|
333
358
|
|
334
359
|
self.class.command_regex =~ val
|
335
360
|
|
336
361
|
# please call Command.matches? before Command#call_safely
|
337
|
-
|
362
|
+
unless Regexp.last_match
|
363
|
+
raise CommandError, "fatal: called a command which didn't match?!"
|
364
|
+
end
|
365
|
+
|
338
366
|
captures = Regexp.last_match.captures
|
339
367
|
pos = Regexp.last_match.end(0)
|
340
368
|
|
@@ -346,11 +374,16 @@ class Pry
|
|
346
374
|
# process and pass a block if one is found
|
347
375
|
pass_block(arg_string) if command_options[:takes_block]
|
348
376
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
377
|
+
args =
|
378
|
+
if arg_string
|
379
|
+
if command_options[:shellwords]
|
380
|
+
Shellwords.shellwords(arg_string)
|
381
|
+
else
|
382
|
+
arg_string.split(" ")
|
383
|
+
end
|
384
|
+
else
|
385
|
+
[]
|
386
|
+
end
|
354
387
|
|
355
388
|
[val[0..pos].rstrip, arg_string, captures, args]
|
356
389
|
end
|
@@ -361,7 +394,9 @@ class Pry
|
|
361
394
|
def process_line(line)
|
362
395
|
command_match, arg_string, captures, args = tokenize(line)
|
363
396
|
|
364
|
-
|
397
|
+
if Pry.config.collision_warning
|
398
|
+
check_for_command_collision(command_match, arg_string)
|
399
|
+
end
|
365
400
|
|
366
401
|
self.arg_string = arg_string
|
367
402
|
self.captures = captures
|
@@ -369,6 +404,43 @@ class Pry
|
|
369
404
|
call_safely(*(captures + args))
|
370
405
|
end
|
371
406
|
|
407
|
+
# Generate completions for this command
|
408
|
+
#
|
409
|
+
# @param [String] _search The line typed so far
|
410
|
+
# @return [Array<String>] Completion words
|
411
|
+
def complete(_search)
|
412
|
+
[]
|
413
|
+
end
|
414
|
+
|
415
|
+
private
|
416
|
+
|
417
|
+
# Run the command with the given `args`.
|
418
|
+
#
|
419
|
+
# This is a public wrapper around `#call` which ensures all preconditions
|
420
|
+
# are met.
|
421
|
+
#
|
422
|
+
# @param [Array<String>] args The arguments to pass to this command.
|
423
|
+
# @return [Object] The return value of the `#call` method, or
|
424
|
+
# {Command::VOID_VALUE}.
|
425
|
+
def call_safely(*args)
|
426
|
+
if command_options[:argument_required] && args.empty?
|
427
|
+
raise CommandError, "The command '#{command_name}' requires an argument."
|
428
|
+
end
|
429
|
+
|
430
|
+
ret = use_unpatched_symbol do
|
431
|
+
call_with_hooks(*args)
|
432
|
+
end
|
433
|
+
command_options[:keep_retval] ? ret : void
|
434
|
+
end
|
435
|
+
|
436
|
+
def use_unpatched_symbol
|
437
|
+
call_method = Symbol.method_defined?(:call) && Symbol.instance_method(:call)
|
438
|
+
Symbol.class_eval { undef :call } if call_method
|
439
|
+
yield
|
440
|
+
ensure
|
441
|
+
Symbol.instance_eval { define_method(:call, call_method) } if call_method
|
442
|
+
end
|
443
|
+
|
372
444
|
# Pass a block argument to a command.
|
373
445
|
# @param [String] arg_string The arguments (as a string) passed to the command.
|
374
446
|
# We inspect these for a '| do' or a '| {' and if we find it we use it
|
@@ -380,18 +452,19 @@ class Pry
|
|
380
452
|
# Workaround for weird JRuby bug where rindex in this case can return nil
|
381
453
|
# even when there's a match.
|
382
454
|
arg_string.scan(/\| *(?:do|\{)/)
|
383
|
-
block_index =
|
455
|
+
block_index = $LAST_MATCH_INFO && $LAST_MATCH_INFO.offset(0)[0]
|
384
456
|
|
385
|
-
return
|
457
|
+
return unless block_index
|
386
458
|
|
387
459
|
block_init_string = arg_string.slice!(block_index..-1)[1..-1]
|
388
460
|
prime_string = "proc #{block_init_string}\n"
|
389
461
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
462
|
+
block_string =
|
463
|
+
if !Pry::Code.complete_expression?(prime_string)
|
464
|
+
pry_instance.r(target, prime_string)
|
465
|
+
else
|
466
|
+
prime_string
|
467
|
+
end
|
395
468
|
|
396
469
|
begin
|
397
470
|
self.command_block = target.eval(block_string)
|
@@ -400,293 +473,48 @@ class Pry
|
|
400
473
|
end
|
401
474
|
end
|
402
475
|
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
#
|
407
|
-
# This is a public wrapper around `#call` which ensures all preconditions
|
408
|
-
# are met.
|
409
|
-
#
|
410
|
-
# @param [Array<String>] args The arguments to pass to this command.
|
411
|
-
# @return [Object] The return value of the `#call` method, or
|
412
|
-
# {Command::VOID_VALUE}.
|
413
|
-
def call_safely(*args)
|
414
|
-
unless dependencies_met?
|
415
|
-
gems_needed = Array(command_options[:requires_gem])
|
416
|
-
gems_not_installed = gems_needed.select { |g| !Rubygem.installed?(g) }
|
417
|
-
output.puts "\nThe command '#{command_name}' is #{text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
|
418
|
-
output.puts "-"
|
419
|
-
output.puts "Type `install-command #{command_name}` to install the required gems and activate this command."
|
420
|
-
return void
|
421
|
-
end
|
422
|
-
|
423
|
-
if command_options[:argument_required] && args.empty?
|
424
|
-
raise CommandError, "The command '#{command_name}' requires an argument."
|
425
|
-
end
|
426
|
-
|
427
|
-
ret = call_with_hooks(*args)
|
428
|
-
command_options[:keep_retval] ? ret : void
|
476
|
+
def find_hooks(event)
|
477
|
+
event_name = "#{event}_#{command_name}"
|
478
|
+
(hooks || Pry.hooks || self.class.hooks).get_hooks(event_name).values
|
429
479
|
end
|
430
480
|
|
431
|
-
|
432
|
-
|
433
|
-
# @return Boolean
|
434
|
-
def dependencies_met?
|
435
|
-
@dependencies_met ||= command_dependencies_met?(command_options)
|
481
|
+
def before_hooks
|
482
|
+
find_hooks('before')
|
436
483
|
end
|
437
484
|
|
438
|
-
|
439
|
-
|
440
|
-
# @param [String] search The line typed so far
|
441
|
-
# @return [Array<String>] Completion words
|
442
|
-
def complete(search)
|
443
|
-
[]
|
485
|
+
def after_hooks
|
486
|
+
find_hooks('after')
|
444
487
|
end
|
445
488
|
|
446
|
-
private
|
447
|
-
|
448
489
|
# Run the `#call` method and all the registered hooks.
|
449
490
|
# @param [Array<String>] args The arguments to `#call`
|
450
491
|
# @return [Object] The return value from `#call`
|
451
492
|
def call_with_hooks(*args)
|
452
|
-
|
453
|
-
instance_exec(*args, &block)
|
454
|
-
end
|
493
|
+
before_hooks.each { |block| instance_exec(*args, &block) }
|
455
494
|
|
456
495
|
ret = call(*args)
|
457
496
|
|
458
|
-
|
497
|
+
after_hooks.each do |block|
|
459
498
|
ret = instance_exec(*args, &block)
|
460
499
|
end
|
461
500
|
|
462
501
|
ret
|
463
502
|
end
|
464
503
|
|
465
|
-
#
|
466
|
-
#
|
467
|
-
# @param [
|
468
|
-
# @
|
469
|
-
|
470
|
-
|
471
|
-
|
504
|
+
# Normalize method arguments according to its arity.
|
505
|
+
#
|
506
|
+
# @param [Integer] method
|
507
|
+
# @param [Array] args
|
508
|
+
# @return [Array] a (possibly shorter) array of the arguments to pass
|
509
|
+
def normalize_method_args(method, args)
|
510
|
+
case method.arity
|
511
|
+
when -1
|
472
512
|
args
|
473
|
-
when
|
513
|
+
when 0
|
474
514
|
[]
|
475
|
-
when arity > 0
|
476
|
-
args.values_at(*(0..(arity - 1)).to_a)
|
477
|
-
end
|
478
|
-
end
|
479
|
-
end
|
480
|
-
|
481
|
-
# A super-class for Commands that are created with a single block.
|
482
|
-
#
|
483
|
-
# This class ensures that the block is called with the correct number of arguments
|
484
|
-
# and the right context.
|
485
|
-
#
|
486
|
-
# Create subclasses using {Pry::CommandSet#command}.
|
487
|
-
class BlockCommand < Command
|
488
|
-
# backwards compatibility
|
489
|
-
alias_method :opts, :context
|
490
|
-
|
491
|
-
# Call the block that was registered with this command.
|
492
|
-
# @param [Array<String>] args The arguments passed
|
493
|
-
# @return [Object] The return value of the block
|
494
|
-
def call(*args)
|
495
|
-
instance_exec(*correct_arg_arity(block.arity, args), &block)
|
496
|
-
end
|
497
|
-
|
498
|
-
def help
|
499
|
-
"#{command_options[:listing].to_s.ljust(18)} #{description}"
|
500
|
-
end
|
501
|
-
end
|
502
|
-
|
503
|
-
# A super-class of Commands with structure.
|
504
|
-
#
|
505
|
-
# This class implements the bare-minimum functionality that a command should
|
506
|
-
# have, namely a --help switch, and then delegates actual processing to its
|
507
|
-
# subclasses.
|
508
|
-
#
|
509
|
-
# Create subclasses using {Pry::CommandSet#create_command}, and override the
|
510
|
-
# `options(opt)` method to set up an instance of Slop, and the `process`
|
511
|
-
# method to actually run the command. If necessary, you can also override
|
512
|
-
# `setup` which will be called before `options`, for example to require any
|
513
|
-
# gems your command needs to run, or to set up state.
|
514
|
-
class ClassCommand < Command
|
515
|
-
class << self
|
516
|
-
|
517
|
-
# Ensure that subclasses inherit the options, description and
|
518
|
-
# match from a ClassCommand super class.
|
519
|
-
def inherited(klass)
|
520
|
-
klass.match match
|
521
|
-
klass.description description
|
522
|
-
klass.command_options options
|
523
|
-
end
|
524
|
-
|
525
|
-
def source
|
526
|
-
source_object.source
|
527
|
-
end
|
528
|
-
|
529
|
-
def doc
|
530
|
-
new.help
|
531
|
-
end
|
532
|
-
|
533
|
-
def source_location
|
534
|
-
source_object.source_location
|
535
|
-
end
|
536
|
-
|
537
|
-
def source_file
|
538
|
-
source_object.source_file
|
539
|
-
end
|
540
|
-
alias_method :file, :source_file
|
541
|
-
|
542
|
-
def source_line
|
543
|
-
source_object.source_line
|
544
|
-
end
|
545
|
-
alias_method :line, :source_line
|
546
|
-
|
547
|
-
private
|
548
|
-
|
549
|
-
# The object used to extract the source for the command.
|
550
|
-
#
|
551
|
-
# This should be a `Pry::Method(block)` for a command made with `create_command`
|
552
|
-
# and a `Pry::WrappedModule(self)` for a command that's a standard class.
|
553
|
-
# @return [Pry::WrappedModule, Pry::Method]
|
554
|
-
def source_object
|
555
|
-
@source_object ||= if name =~ /^[A-Z]/
|
556
|
-
Pry::WrappedModule(self)
|
557
|
-
else
|
558
|
-
Pry::Method(block)
|
559
|
-
end
|
560
|
-
end
|
561
|
-
end
|
562
|
-
|
563
|
-
attr_accessor :opts
|
564
|
-
attr_accessor :args
|
565
|
-
|
566
|
-
# Set up `opts` and `args`, and then call `process`.
|
567
|
-
#
|
568
|
-
# This method will display help if necessary.
|
569
|
-
#
|
570
|
-
# @param [Array<String>] args The arguments passed
|
571
|
-
# @return [Object] The return value of `process` or VOID_VALUE
|
572
|
-
def call(*args)
|
573
|
-
setup
|
574
|
-
|
575
|
-
self.opts = slop
|
576
|
-
self.args = self.opts.parse!(args)
|
577
|
-
|
578
|
-
if opts.present?(:help)
|
579
|
-
output.puts slop.help
|
580
|
-
void
|
581
515
|
else
|
582
|
-
|
516
|
+
args.values_at(*(0..(method.arity - 1)).to_a)
|
583
517
|
end
|
584
518
|
end
|
585
|
-
|
586
|
-
# Return the help generated by Slop for this command.
|
587
|
-
def help
|
588
|
-
slop.help
|
589
|
-
end
|
590
|
-
|
591
|
-
# Return an instance of Slop that can parse either subcommands or the
|
592
|
-
# options that this command accepts.
|
593
|
-
def slop
|
594
|
-
Slop.new do |opt|
|
595
|
-
opt.banner(unindent(self.class.banner))
|
596
|
-
subcommands(opt)
|
597
|
-
options(opt)
|
598
|
-
opt.on :h, :help, 'Show this message.'
|
599
|
-
end
|
600
|
-
end
|
601
|
-
|
602
|
-
# Generate shell completions
|
603
|
-
# @param [String] search The line typed so far
|
604
|
-
# @return [Array<String>] the words to complete
|
605
|
-
def complete(search)
|
606
|
-
slop.map do |opt|
|
607
|
-
[opt.long && "--#{opt.long} " || opt.short && "-#{opt.short}"]
|
608
|
-
end.flatten(1).compact + super
|
609
|
-
end
|
610
|
-
|
611
|
-
# A method called just before `options(opt)` as part of `call`.
|
612
|
-
#
|
613
|
-
# This method can be used to set up any context your command needs to run,
|
614
|
-
# for example requiring gems, or setting default values for options.
|
615
|
-
#
|
616
|
-
# @example
|
617
|
-
# def setup
|
618
|
-
# require 'gist'
|
619
|
-
# @action = :method
|
620
|
-
# end
|
621
|
-
def setup; end
|
622
|
-
|
623
|
-
# A method to setup Slop commands so it can parse the subcommands your
|
624
|
-
# command expects. If you need to set up default values, use `setup`
|
625
|
-
# instead.
|
626
|
-
#
|
627
|
-
# @example A minimal example
|
628
|
-
# def subcommands(cmd)
|
629
|
-
# cmd.command :download do |opt|
|
630
|
-
# description 'Downloads a content from a server'
|
631
|
-
#
|
632
|
-
# opt.on :verbose, 'Use verbose output'
|
633
|
-
#
|
634
|
-
# run do |options, arguments|
|
635
|
-
# ContentDownloader.download(options, arguments)
|
636
|
-
# end
|
637
|
-
# end
|
638
|
-
# end
|
639
|
-
#
|
640
|
-
# @example Define the invokation block anywhere you want
|
641
|
-
# def subcommands(cmd)
|
642
|
-
# cmd.command :download do |opt|
|
643
|
-
# description 'Downloads a content from a server'
|
644
|
-
#
|
645
|
-
# opt.on :verbose, 'Use verbose output'
|
646
|
-
# end
|
647
|
-
# end
|
648
|
-
#
|
649
|
-
# def process
|
650
|
-
# # Perform calculations...
|
651
|
-
# opts.fetch_command(:download).run do |options, arguments|
|
652
|
-
# ContentDownloader.download(options, arguments)
|
653
|
-
# end
|
654
|
-
# # More calculations...
|
655
|
-
# end
|
656
|
-
def subcommands(cmd); end
|
657
|
-
|
658
|
-
# A method to setup Slop so it can parse the options your command expects.
|
659
|
-
#
|
660
|
-
# @note Please don't do anything side-effecty in the main part of this
|
661
|
-
# method, as it may be called by Pry at any time for introspection reasons.
|
662
|
-
# If you need to set up default values, use `setup` instead.
|
663
|
-
#
|
664
|
-
# @example
|
665
|
-
# def options(opt)
|
666
|
-
# opt.banner "Gists methods or classes"
|
667
|
-
# opt.on(:c, :class, "gist a class") do
|
668
|
-
# @action = :class
|
669
|
-
# end
|
670
|
-
# end
|
671
|
-
def options(opt); end
|
672
|
-
|
673
|
-
# The actual body of your command should go here.
|
674
|
-
#
|
675
|
-
# The `opts` mehod can be called to get the options that Slop has passed,
|
676
|
-
# and `args` gives the remaining, unparsed arguments.
|
677
|
-
#
|
678
|
-
# The return value of this method is discarded unless the command was
|
679
|
-
# created with `:keep_retval => true`, in which case it is returned to the
|
680
|
-
# repl.
|
681
|
-
#
|
682
|
-
# @example
|
683
|
-
# def process
|
684
|
-
# if opts.present?(:class)
|
685
|
-
# gist_class
|
686
|
-
# else
|
687
|
-
# gist_method
|
688
|
-
# end
|
689
|
-
# end
|
690
|
-
def process; raise CommandError, "command '#{command_name}' not implemented" end
|
691
519
|
end
|
692
520
|
end
|