mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
142 lines
4.6 KiB
Ruby
142 lines
4.6 KiB
Ruby
require 'forwardable'
|
|
|
|
class Pry
|
|
class CommandProcessor
|
|
extend Forwardable
|
|
|
|
attr_accessor :pry_instance
|
|
|
|
def initialize(pry_instance)
|
|
@pry_instance = pry_instance
|
|
end
|
|
|
|
def_delegators :@pry_instance, :commands, :nesting, :output
|
|
|
|
# Is the string a valid command?
|
|
# @param [String] val The string passed in from the Pry prompt.
|
|
# @param [Binding] target The context where the string should be
|
|
# interpolated in.
|
|
# @return [Boolean] Whether the string is a valid command.
|
|
def valid_command?(val, target=binding)
|
|
!!(command_matched(val, target)[0])
|
|
end
|
|
|
|
# Convert the object to a form that can be interpolated into a
|
|
# Regexp cleanly.
|
|
# @return [String] The string to interpolate into a Regexp
|
|
def convert_to_regex(obj)
|
|
case obj
|
|
when String
|
|
Regexp.escape(obj)
|
|
else
|
|
obj
|
|
end
|
|
end
|
|
|
|
# Revaluate the string (str) and perform interpolation.
|
|
# @param [String] str The string to reevaluate with interpolation.
|
|
# @param [Binding] target The context where the string should be
|
|
# interpolated in.
|
|
# @return [String] The reevaluated string with interpolations
|
|
# applied (if any).
|
|
def interpolate_string(str, target)
|
|
dumped_str = str.dump
|
|
dumped_str.gsub!(/\\\#\{/, '#{')
|
|
target.eval(dumped_str)
|
|
end
|
|
|
|
# Determine whether a Pry command was matched and return command data
|
|
# and argument string.
|
|
# This method should not need to be invoked directly.
|
|
# @param [String] val The line of input.
|
|
# @param [Binding] target The binding to perform string
|
|
# interpolation against.
|
|
# @return [Array] The command data and arg string pair
|
|
def command_matched(val, target)
|
|
_, cmd_data = commands.commands.find do |name, data|
|
|
|
|
prefix = Regexp.escape(Pry.config.command_prefix)
|
|
prefix = "(?:#{prefix})?" unless data.options[:use_prefix]
|
|
|
|
command_regex = /^#{prefix}#{convert_to_regex(name)}(?!\S)/
|
|
|
|
if data.options[:interpolate]
|
|
# If interpolation fails then the command cannot be matched,
|
|
# so early exit.
|
|
begin
|
|
interp_val = interpolate_string(val, target)
|
|
rescue Exception
|
|
next
|
|
end
|
|
|
|
val.replace interp_val if command_regex =~ interp_val
|
|
else
|
|
command_regex =~ val
|
|
end
|
|
end
|
|
|
|
[cmd_data, (Regexp.last_match ? Regexp.last_match.captures : nil), (Regexp.last_match ? Regexp.last_match.end(0) : nil)]
|
|
end
|
|
|
|
# Process Pry commands. Pry commands are not Ruby methods and are evaluated
|
|
# prior to Ruby expressions.
|
|
# Commands can be modified/configured by the user: see `Pry::Commands`
|
|
# This method should not need to be invoked directly - it is called
|
|
# by `Pry#r`.
|
|
# @param [String] val The current line of input.
|
|
# @param [String] eval_string The cumulative lines of input for
|
|
# multi-line input.
|
|
# @param [Binding] target The receiver of the commands.
|
|
def process_commands(val, eval_string, target)
|
|
|
|
# no command was matched, so return to caller
|
|
command, captures, pos = command_matched(val, target)
|
|
return if !command
|
|
arg_string = val[pos..-1]
|
|
|
|
# remove the one leading space if it exists
|
|
arg_string.slice!(0) if arg_string.start_with?(" ")
|
|
|
|
args = arg_string ? Shellwords.shellwords(arg_string) : []
|
|
|
|
options = {
|
|
:val => val,
|
|
:arg_string => arg_string,
|
|
:eval_string => eval_string,
|
|
:nesting => nesting,
|
|
:commands => commands.commands,
|
|
:captures => captures
|
|
}
|
|
|
|
execute_command(target, command.name, options, *(captures + args))
|
|
end
|
|
|
|
# Execute a Pry command.
|
|
# This method should not need to be invoked directly.
|
|
# @param [Binding] target The target of the Pry session.
|
|
# @param [String] command The name of the command to be run.
|
|
# @param [Hash] options The options to set on the Commands object.
|
|
# @param [Array] args The command arguments.
|
|
def execute_command(target, command, options, *args)
|
|
context = CommandContext.new
|
|
|
|
# set some useful methods to be used by the action blocks
|
|
context.opts = options
|
|
context.target = target
|
|
context.output = output
|
|
context.captures = options[:captures]
|
|
context.eval_string = options[:eval_string]
|
|
context.arg_string = options[:arg_string]
|
|
context.command_set = commands
|
|
|
|
context.command_processor = self
|
|
|
|
ret = commands.run_command(context, command, *args)
|
|
|
|
# Tick, tock, im getting rid of this shit soon.
|
|
options[:val].replace("")
|
|
|
|
ret
|
|
end
|
|
end
|
|
end
|