pry 0.10.0.pre4-x64-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +341 -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
@@ -0,0 +1,443 @@
|
|
1
|
+
class Pry
|
2
|
+
class NoCommandError < StandardError
|
3
|
+
def initialize(match, owner)
|
4
|
+
super "Command '#{match}' not found in command set #{owner}"
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
# This class is used to create sets of commands. Commands can be imported from
|
9
|
+
# different sets, aliased, removed, etc.
|
10
|
+
class CommandSet
|
11
|
+
include Enumerable
|
12
|
+
include Pry::Helpers::BaseHelpers
|
13
|
+
attr_reader :helper_module
|
14
|
+
|
15
|
+
# @param [Array<Commandset>] imported_sets
|
16
|
+
# Sets which will be imported automatically
|
17
|
+
# @yield Optional block run to define commands
|
18
|
+
def initialize(*imported_sets, &block)
|
19
|
+
@commands = {}
|
20
|
+
@helper_module = Module.new
|
21
|
+
import(*imported_sets)
|
22
|
+
instance_eval(&block) if block
|
23
|
+
end
|
24
|
+
|
25
|
+
# Defines a new Pry command.
|
26
|
+
# @param [String, Regexp] match The start of invocations of this command.
|
27
|
+
# @param [String] description A description of the command.
|
28
|
+
# @param [Hash] options The optional configuration parameters.
|
29
|
+
# @option options [Boolean] :keep_retval Whether or not to use return value
|
30
|
+
# of the block for return of `command` or just to return `nil`
|
31
|
+
# (the default).
|
32
|
+
# @option options [Array<String>] :requires_gem Whether the command has
|
33
|
+
# any gem dependencies, if it does and dependencies not met then
|
34
|
+
# command is disabled and a stub proc giving instructions to
|
35
|
+
# install command is provided.
|
36
|
+
# @option options [Boolean] :interpolate Whether string #{} based
|
37
|
+
# interpolation is applied to the command arguments before
|
38
|
+
# executing the command. Defaults to true.
|
39
|
+
# @option options [String] :listing The listing name of the
|
40
|
+
# command. That is the name by which the command is looked up by
|
41
|
+
# help and by show-command. Necessary for commands with regex matches.
|
42
|
+
# @option options [Boolean] :use_prefix Whether the command uses
|
43
|
+
# `Pry.config.command_prefix` prefix (if one is defined). Defaults
|
44
|
+
# to true.
|
45
|
+
# @option options [Boolean] :shellwords Whether the command's arguments
|
46
|
+
# should be split using Shellwords instead of just split on spaces.
|
47
|
+
# Defaults to true.
|
48
|
+
# @yield The action to perform. The parameters in the block
|
49
|
+
# determines the parameters the command will receive. All
|
50
|
+
# parameters passed into the block will be strings. Successive
|
51
|
+
# command parameters are separated by whitespace at the Pry prompt.
|
52
|
+
# @example
|
53
|
+
# MyCommands = Pry::CommandSet.new do
|
54
|
+
# command "greet", "Greet somebody" do |name|
|
55
|
+
# puts "Good afternoon #{name.capitalize}!"
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# # From pry:
|
60
|
+
# # pry(main)> _pry_.commands = MyCommands
|
61
|
+
# # pry(main)> greet john
|
62
|
+
# # Good afternoon John!
|
63
|
+
# # pry(main)> help greet
|
64
|
+
# # Greet somebody
|
65
|
+
# @example Regexp command
|
66
|
+
# MyCommands = Pry::CommandSet.new do
|
67
|
+
# command /number-(\d+)/, "number-N regex command", :listing => "number" do |num, name|
|
68
|
+
# puts "hello #{name}, nice number: #{num}"
|
69
|
+
# end
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# # From pry:
|
73
|
+
# # pry(main)> _pry_.commands = MyCommands
|
74
|
+
# # pry(main)> number-10 john
|
75
|
+
# # hello john, nice number: 10
|
76
|
+
# # pry(main)> help number
|
77
|
+
# # number-N regex command
|
78
|
+
def block_command(match, description="No description.", options={}, &block)
|
79
|
+
description, options = ["No description.", description] if description.is_a?(Hash)
|
80
|
+
options = Pry::Command.default_options(match).merge!(options)
|
81
|
+
|
82
|
+
@commands[match] = Pry::BlockCommand.subclass(match, description, options, helper_module, &block)
|
83
|
+
end
|
84
|
+
alias_method :command, :block_command
|
85
|
+
|
86
|
+
# Defines a new Pry command class.
|
87
|
+
#
|
88
|
+
# @param [String, Regexp] match The start of invocations of this command.
|
89
|
+
# @param [String] description A description of the command.
|
90
|
+
# @param [Hash] options The optional configuration parameters, see {#command}
|
91
|
+
# @yield The class body's definition.
|
92
|
+
#
|
93
|
+
# @example
|
94
|
+
# Pry::Commands.create_command "echo", "echo's the input", :shellwords => false do
|
95
|
+
# def options(opt)
|
96
|
+
# opt.banner "Usage: echo [-u | -d] <string to echo>"
|
97
|
+
# opt.on :u, :upcase, "ensure the output is all upper-case"
|
98
|
+
# opt.on :d, :downcase, "ensure the output is all lower-case"
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# def process
|
102
|
+
# raise Pry::CommandError, "-u and -d makes no sense" if opts.present?(:u) && opts.present?(:d)
|
103
|
+
# result = args.join(" ")
|
104
|
+
# result.downcase! if opts.present?(:downcase)
|
105
|
+
# result.upcase! if opts.present?(:upcase)
|
106
|
+
# output.puts result
|
107
|
+
# end
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
def create_command(match, description="No description.", options={}, &block)
|
111
|
+
description, options = ["No description.", description] if description.is_a?(Hash)
|
112
|
+
options = Pry::Command.default_options(match).merge!(options)
|
113
|
+
|
114
|
+
@commands[match] = Pry::ClassCommand.subclass(match, description, options, helper_module, &block)
|
115
|
+
@commands[match].class_eval(&block)
|
116
|
+
@commands[match]
|
117
|
+
end
|
118
|
+
|
119
|
+
# Execute a block of code before a command is invoked. The block also
|
120
|
+
# gets access to parameters that will be passed to the command and
|
121
|
+
# is evaluated in the same context.
|
122
|
+
# @param [String, Regexp] search The match or listing of the command.
|
123
|
+
# @yield The block to be run before the command.
|
124
|
+
# @example Display parameter before invoking command
|
125
|
+
# Pry.config.commands.before_command("whereami") do |n|
|
126
|
+
# output.puts "parameter passed was #{n}"
|
127
|
+
# end
|
128
|
+
def before_command(search, &block)
|
129
|
+
cmd = find_command_by_match_or_listing(search)
|
130
|
+
cmd.hooks[:before].unshift block
|
131
|
+
end
|
132
|
+
|
133
|
+
# Execute a block of code after a command is invoked. The block also
|
134
|
+
# gets access to parameters that will be passed to the command and
|
135
|
+
# is evaluated in the same context.
|
136
|
+
# @param [String, Regexp] search The match or listing of the command.
|
137
|
+
# @yield The block to be run after the command.
|
138
|
+
# @example Display text 'command complete' after invoking command
|
139
|
+
# Pry.config.commands.after_command("whereami") do |n|
|
140
|
+
# output.puts "command complete!"
|
141
|
+
# end
|
142
|
+
def after_command(search, &block)
|
143
|
+
cmd = find_command_by_match_or_listing(search)
|
144
|
+
cmd.hooks[:after] << block
|
145
|
+
end
|
146
|
+
|
147
|
+
def each(&block)
|
148
|
+
@commands.each(&block)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Removes some commands from the set
|
152
|
+
# @param [Array<String>] searches the matches or listings of the commands to remove
|
153
|
+
def delete(*searches)
|
154
|
+
searches.each do |search|
|
155
|
+
cmd = find_command_by_match_or_listing(search)
|
156
|
+
@commands.delete cmd.match
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# Imports all the commands from one or more sets.
|
161
|
+
# @param [Array<CommandSet>] sets Command sets, all of the commands of which
|
162
|
+
# will be imported.
|
163
|
+
# @return [Pry::CommandSet] Returns the reciever (a command set).
|
164
|
+
def import(*sets)
|
165
|
+
sets.each do |set|
|
166
|
+
@commands.merge! set.to_hash
|
167
|
+
helper_module.send :include, set.helper_module
|
168
|
+
end
|
169
|
+
self
|
170
|
+
end
|
171
|
+
|
172
|
+
# Imports some commands from a set
|
173
|
+
# @param [CommandSet] set Set to import commands from
|
174
|
+
# @param [Array<String>] matches Commands to import
|
175
|
+
# @return [Pry::CommandSet] Returns the reciever (a command set).
|
176
|
+
def import_from(set, *matches)
|
177
|
+
helper_module.send :include, set.helper_module
|
178
|
+
matches.each do |match|
|
179
|
+
cmd = set.find_command_by_match_or_listing(match)
|
180
|
+
@commands[cmd.match] = cmd
|
181
|
+
end
|
182
|
+
self
|
183
|
+
end
|
184
|
+
|
185
|
+
# @param [String, Regexp] match_or_listing The match or listing of a command.
|
186
|
+
# of the command to retrieve.
|
187
|
+
# @return [Command] The command object matched.
|
188
|
+
def find_command_by_match_or_listing(match_or_listing)
|
189
|
+
cmd = (@commands[match_or_listing] ||
|
190
|
+
Pry::Helpers::BaseHelpers.find_command(match_or_listing, @commands))
|
191
|
+
cmd or raise ArgumentError, "Cannot find a command: '#{match_or_listing}'!"
|
192
|
+
end
|
193
|
+
|
194
|
+
# Aliases a command
|
195
|
+
# @param [String, Regex] match The match of the alias (can be a regex).
|
196
|
+
# @param [String] action The action to be performed (typically
|
197
|
+
# another command).
|
198
|
+
# @param [Hash] options The optional configuration parameters,
|
199
|
+
# accepts the same as the `command` method, but also allows the
|
200
|
+
# command description to be passed this way too as `:desc`
|
201
|
+
# @example Creating an alias for `ls -M`
|
202
|
+
# Pry.config.commands.alias_command "lM", "ls -M"
|
203
|
+
# @example Pass explicit description (overriding default).
|
204
|
+
# Pry.config.commands.alias_command "lM", "ls -M", :desc => "cutiepie"
|
205
|
+
def alias_command(match, action, options={})
|
206
|
+
cmd = find_command(action) or fail "Command: `#{action}` not found"
|
207
|
+
original_options = cmd.options.dup
|
208
|
+
|
209
|
+
options = original_options.merge!({
|
210
|
+
:desc => "Alias for `#{action}`",
|
211
|
+
:listing => match
|
212
|
+
}).merge!(options)
|
213
|
+
|
214
|
+
# ensure default description is used if desc is nil
|
215
|
+
desc = options.delete(:desc).to_s
|
216
|
+
|
217
|
+
c = block_command match, desc, options do |*args|
|
218
|
+
run action, *args
|
219
|
+
end
|
220
|
+
|
221
|
+
c.class_eval do
|
222
|
+
define_method(:complete) do |input|
|
223
|
+
cmd.new(context).complete(input)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
c.group "Aliases"
|
228
|
+
|
229
|
+
c
|
230
|
+
end
|
231
|
+
|
232
|
+
# Rename a command. Accepts either match or listing for the search.
|
233
|
+
#
|
234
|
+
# @param [String, Regexp] new_match The new match for the command.
|
235
|
+
# @param [String, Regexp] search The command's current match or listing.
|
236
|
+
# @param [Hash] options The optional configuration parameters,
|
237
|
+
# accepts the same as the `command` method, but also allows the
|
238
|
+
# command description to be passed this way too.
|
239
|
+
# @example Renaming the `ls` command and changing its description.
|
240
|
+
# Pry.config.commands.rename "dir", "ls", :description => "DOS friendly ls"
|
241
|
+
def rename_command(new_match, search, options={})
|
242
|
+
cmd = find_command_by_match_or_listing(search)
|
243
|
+
|
244
|
+
options = {
|
245
|
+
:listing => new_match,
|
246
|
+
:description => cmd.description
|
247
|
+
}.merge!(options)
|
248
|
+
|
249
|
+
@commands[new_match] = cmd.dup
|
250
|
+
@commands[new_match].match = new_match
|
251
|
+
@commands[new_match].description = options.delete(:description)
|
252
|
+
@commands[new_match].options.merge!(options)
|
253
|
+
@commands.delete(cmd.match)
|
254
|
+
end
|
255
|
+
|
256
|
+
def disabled_command(name_of_disabled_command, message, matcher=name_of_disabled_command)
|
257
|
+
create_command name_of_disabled_command do
|
258
|
+
match matcher
|
259
|
+
description ""
|
260
|
+
|
261
|
+
define_method(:process) do
|
262
|
+
output.puts "DISABLED: #{message}"
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# Sets or gets the description for a command (replacing the old
|
268
|
+
# description). Returns current description if no description
|
269
|
+
# parameter provided.
|
270
|
+
# @param [String, Regexp] search The command match.
|
271
|
+
# @param [String?] description (nil) The command description.
|
272
|
+
# @example Setting
|
273
|
+
# MyCommands = Pry::CommandSet.new do
|
274
|
+
# desc "help", "help description"
|
275
|
+
# end
|
276
|
+
# @example Getting
|
277
|
+
# Pry.config.commands.desc "amend-line"
|
278
|
+
def desc(search, description=nil)
|
279
|
+
cmd = find_command_by_match_or_listing(search)
|
280
|
+
return cmd.description if !description
|
281
|
+
|
282
|
+
cmd.description = description
|
283
|
+
end
|
284
|
+
|
285
|
+
# Defines helpers methods for this command sets.
|
286
|
+
# Those helpers are only defined in this command set.
|
287
|
+
#
|
288
|
+
# @yield A block defining helper methods
|
289
|
+
# @example
|
290
|
+
# helpers do
|
291
|
+
# def hello
|
292
|
+
# puts "Hello!"
|
293
|
+
# end
|
294
|
+
#
|
295
|
+
# include OtherModule
|
296
|
+
# end
|
297
|
+
def helpers(&block)
|
298
|
+
helper_module.class_eval(&block)
|
299
|
+
end
|
300
|
+
|
301
|
+
|
302
|
+
# @return [Array]
|
303
|
+
# The list of commands provided by the command set.
|
304
|
+
def list_commands
|
305
|
+
@commands.keys
|
306
|
+
end
|
307
|
+
alias_method :keys, :list_commands
|
308
|
+
|
309
|
+
def to_hash
|
310
|
+
@commands.dup
|
311
|
+
end
|
312
|
+
alias_method :to_h, :to_hash
|
313
|
+
|
314
|
+
# Find a command that matches the given line
|
315
|
+
# @param [String] pattern The line that might be a command invocation
|
316
|
+
# @return [Pry::Command, nil]
|
317
|
+
def [](pattern)
|
318
|
+
@commands.values.select do |command|
|
319
|
+
command.matches?(pattern)
|
320
|
+
end.sort_by do |command|
|
321
|
+
command.match_score(pattern)
|
322
|
+
end.last
|
323
|
+
end
|
324
|
+
alias_method :find_command, :[]
|
325
|
+
|
326
|
+
#
|
327
|
+
# Re-assign the command found at _pattern_ with _command_.
|
328
|
+
#
|
329
|
+
# @param [Regexp, String] pattern
|
330
|
+
# The command to add or replace(found at _pattern_).
|
331
|
+
#
|
332
|
+
# @param [Pry::Command] command
|
333
|
+
# The command to add.
|
334
|
+
#
|
335
|
+
# @return [Pry::Command]
|
336
|
+
# Returns the new command (matched with "pattern".)
|
337
|
+
#
|
338
|
+
# @example
|
339
|
+
# Pry.config.commands["help"] = MyHelpCommand
|
340
|
+
#
|
341
|
+
def []=(pattern, command)
|
342
|
+
if command.equal?(nil)
|
343
|
+
return @commands.delete(pattern)
|
344
|
+
end
|
345
|
+
unless Class === command && command < Pry::Command
|
346
|
+
raise TypeError, "command is not a subclass of Pry::Command"
|
347
|
+
end
|
348
|
+
bind_command_to_pattern = pattern != command.match
|
349
|
+
if bind_command_to_pattern
|
350
|
+
command_copy = command.dup
|
351
|
+
command_copy.match = pattern
|
352
|
+
@commands[pattern] = command_copy
|
353
|
+
else
|
354
|
+
@commands[pattern] = command
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
#
|
359
|
+
# Add a command to set.
|
360
|
+
#
|
361
|
+
# @param [Command] command
|
362
|
+
# a subclass of Pry::Command.
|
363
|
+
#
|
364
|
+
def add_command(command)
|
365
|
+
self[command.match] = command
|
366
|
+
end
|
367
|
+
|
368
|
+
# Find the command that the user might be trying to refer to.
|
369
|
+
# @param [String] search The user's search.
|
370
|
+
# @return [Pry::Command?]
|
371
|
+
def find_command_for_help(search)
|
372
|
+
find_command(search) || (begin
|
373
|
+
find_command_by_match_or_listing(search)
|
374
|
+
rescue ArgumentError
|
375
|
+
nil
|
376
|
+
end)
|
377
|
+
end
|
378
|
+
|
379
|
+
# Is the given line a command invocation?
|
380
|
+
# @param [String] val
|
381
|
+
# @return [Boolean]
|
382
|
+
def valid_command?(val)
|
383
|
+
!!find_command(val)
|
384
|
+
end
|
385
|
+
|
386
|
+
# Process the given line to see whether it needs executing as a command.
|
387
|
+
# @param [String] val The line to execute
|
388
|
+
# @param [Hash] context The context to execute the commands with
|
389
|
+
# @return [CommandSet::Result]
|
390
|
+
def process_line(val, context={})
|
391
|
+
if command = find_command(val)
|
392
|
+
context = context.merge(:command_set => self)
|
393
|
+
retval = command.new(context).process_line(val)
|
394
|
+
Result.new(true, retval)
|
395
|
+
else
|
396
|
+
Result.new(false)
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
# @private (used for testing)
|
401
|
+
def run_command(context, match, *args)
|
402
|
+
command = @commands[match] or raise NoCommandError.new(match, self)
|
403
|
+
command.new(context).call_safely(*args)
|
404
|
+
end
|
405
|
+
|
406
|
+
# Generate completions for the user's search.
|
407
|
+
# @param [String] search The line to search for
|
408
|
+
# @param [Hash] context The context to create the command with
|
409
|
+
# @return [Array<String>]
|
410
|
+
def complete(search, context={})
|
411
|
+
if command = find_command(search)
|
412
|
+
command.new(context).complete(search)
|
413
|
+
else
|
414
|
+
@commands.keys.select do |key|
|
415
|
+
String === key && key.start_with?(search)
|
416
|
+
end.map{ |key| key + " " }
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
# Wraps the return result of process_commands, indicates if the
|
422
|
+
# result IS a command and what kind of command (e.g void)
|
423
|
+
class Result
|
424
|
+
attr_reader :retval
|
425
|
+
|
426
|
+
def initialize(is_command, retval = nil)
|
427
|
+
@is_command, @retval = is_command, retval
|
428
|
+
end
|
429
|
+
|
430
|
+
# Is the result a command?
|
431
|
+
# @return [Boolean]
|
432
|
+
def command?
|
433
|
+
@is_command
|
434
|
+
end
|
435
|
+
|
436
|
+
# Is the result a command and if it is, is it a void command?
|
437
|
+
# (one that does not return a value)
|
438
|
+
# @return [Boolean]
|
439
|
+
def void_command?
|
440
|
+
retval == Command::VOID_VALUE
|
441
|
+
end
|
442
|
+
end
|
443
|
+
end
|
data/lib/pry/commands.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
class Pry
|
2
|
+
class Command::AmendLine < Pry::ClassCommand
|
3
|
+
match(/amend-line(?: (-?\d+)(?:\.\.(-?\d+))?)?/)
|
4
|
+
group 'Editing'
|
5
|
+
description 'Amend a line of input in multi-line mode.'
|
6
|
+
command_options :interpolate => false, :listing => 'amend-line'
|
7
|
+
|
8
|
+
banner <<-'BANNER'
|
9
|
+
Amend a line of input in multi-line mode. `amend-line N`, where the N represents
|
10
|
+
line to replace. Can also specify a range of lines using `amend-line N..M`
|
11
|
+
syntax. Passing "!" as replacement content deletes the line(s) instead.
|
12
|
+
|
13
|
+
amend-line 1 puts 'new' # replace line 1
|
14
|
+
amend-line 1..4 ! # delete lines 1..4
|
15
|
+
amend-line 3 >puts 'bye' # insert before line 3
|
16
|
+
amend-line puts 'appended' # no line number modifies immediately preceding line
|
17
|
+
BANNER
|
18
|
+
|
19
|
+
def process
|
20
|
+
raise CommandError, "No input to amend." if eval_string.empty?
|
21
|
+
|
22
|
+
eval_string.replace amended_input(eval_string)
|
23
|
+
run "fix-indent"
|
24
|
+
run "show-input"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# @param [String] string The string to amend.
|
30
|
+
# @return [String] A new string with the amendments applied to it.
|
31
|
+
def amended_input(string)
|
32
|
+
input_array = eval_string.each_line.to_a
|
33
|
+
|
34
|
+
if arg_string == "!"
|
35
|
+
delete_from_array(input_array, line_range)
|
36
|
+
elsif arg_string.start_with?(">")
|
37
|
+
insert_into_array(input_array, line_range)
|
38
|
+
else
|
39
|
+
replace_in_array(input_array, line_range)
|
40
|
+
end
|
41
|
+
|
42
|
+
input_array.join
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete_from_array(array, range)
|
46
|
+
array.slice!(range)
|
47
|
+
end
|
48
|
+
|
49
|
+
def insert_into_array(array, range)
|
50
|
+
insert_slot = Array(range).first
|
51
|
+
array.insert(insert_slot, arg_string[1..-1] << "\n")
|
52
|
+
end
|
53
|
+
|
54
|
+
def replace_in_array(array, range)
|
55
|
+
array[range] = arg_string + "\n"
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Fixnum] The number of lines currently in `eval_string` (the input buffer).
|
59
|
+
def line_count
|
60
|
+
eval_string.lines.count
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the (one-indexed) start and end lines given by the user.
|
64
|
+
# The lines in this range will be affected by the `amend-line`.
|
65
|
+
# Returns `nil` if no lines were specified by the user.
|
66
|
+
# @return [Array<Fixnum>, nil]
|
67
|
+
def start_and_end_line_number
|
68
|
+
start_line_number, end_line_number = args
|
69
|
+
end_line_number ||= start_line_number.to_i
|
70
|
+
|
71
|
+
[start_line_number.to_i, end_line_number.to_i] if start_line_number
|
72
|
+
end
|
73
|
+
|
74
|
+
# Takes two numbers that are 1-indexed, and returns a range (or
|
75
|
+
# number) that is 0-indexed. 1-indexed means the first element is
|
76
|
+
# indentified by 1 rather than by 0 (as is the case for Ruby arrays).
|
77
|
+
# @param [Fixnum] start_line_number One-indexed number.
|
78
|
+
# @param [Fixnum] end_line_number One-indexed number.
|
79
|
+
# @return [Range] The zero-indexed range.
|
80
|
+
def zero_indexed_range_from_one_indexed_numbers(start_line_number, end_line_number)
|
81
|
+
# FIXME: one_index_number is a horrible name for this method
|
82
|
+
one_index_number(start_line_number)..one_index_number(end_line_number)
|
83
|
+
end
|
84
|
+
|
85
|
+
# The lines (or line) that will be modified by the `amend-line`.
|
86
|
+
# @return [Range, Fixnum] The lines or line.
|
87
|
+
def line_range
|
88
|
+
start_line_number, end_line_number = start_and_end_line_number
|
89
|
+
if start_line_number
|
90
|
+
zero_indexed_range_from_one_indexed_numbers(start_line_number,
|
91
|
+
end_line_number)
|
92
|
+
else
|
93
|
+
line_count - 1
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
Pry::Commands.add_command(Pry::Command::AmendLine)
|
99
|
+
end
|