pry--pry/lib/pry/command_processor.rb

165 lines
5.4 KiB
Ruby
Raw Normal View History

require 'forwardable'
class Pry
class CommandProcessor
SYSTEM_COMMAND_DELIMITER = "."
SYSTEM_COMMAND_REGEX = /^#{Regexp.escape(SYSTEM_COMMAND_DELIMITER)}(.*)/
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 command valid?
# @param [String] val The string passed in from the Pry prompt.
# @return [Boolean] Whether the string is a valid command.
def valid_command?(val)
system_command?(val) || pry_command?(val)
end
# Is the string a valid system command?
# @param [String] val The string passed in from the Pry prompt.
# @return [Boolean] Whether the string is a valid system command.
def system_command?(val)
!!(SYSTEM_COMMAND_REGEX =~ val)
end
# Is the string a valid pry command?
# A Pry command is a command that is not a system command.
# @param [String] val The string passed in from the Pry prompt.
# @return [Boolean] Whether the string is a valid Pry command.
def pry_command?(val)
!!command_matched(val).first
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
# reevaluated 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
# Execute a given system command.
# The commands first have interpolation applied against the
# `target` context.
# All system command are forwarded to a shell. Note that the `cd`
# command is special-cased and is converted internallly to a `Dir.chdir`
# @param [String] val The system command to execute.
# @param [Binding] target The context in which to perform string interpolation.
def execute_system_command(val, target)
SYSTEM_COMMAND_REGEX =~ val
cmd = interpolate_string($1, target)
if cmd =~ /^cd\s+(.+)/i
begin
Dir.chdir(File.expand_path($1))
rescue Errno::ENOENT
output.puts "No such directory: #{$1}"
end
else
system(cmd)
end
added highlighting to disabled commands in GNU bash, version 4.1.5(1)-release (i486-pc-linux-gnu) These shell commands are defined internally. Type `help' to see this list. Type `help name' to find out more about the function `name'. Use `info bash' to find out more about the shell in general. Use `man -k' or `info' to find out more about commands not in this list. A star (*) next to a name means that the command is disabled. job_spec [&] history [-c] [-d offset] [n] or history -anrw [filename] o> (( expression )) if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS> . filename [arguments] jobs [-lnprs] [jobspec ...] or jobs -x command [args] : kill [-s sigspec | -n signum | -sigspec] pid | jobspec ...> [ arg... ] let arg [arg ...] [[ expression ]] local [option] name[=value] ... alias [-p] [name[=value] ... ] logout [n] bg [job_spec ...] mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C> bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-u nam> popd [-n] [+N | -N] break [n] printf [-v var] format [arguments] builtin [shell-builtin [arg ...]] pushd [-n] [+N | -N | dir] caller [expr] pwd [-LP] case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-> cd [-L|-P] [dir] readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [> command [-pVv] command [arg ...] readonly [-af] [name[=value] ...] or readonly -p compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpa> return [n] complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action> select NAME [in WORDS ... ;] do COMMANDS; done compopt [-o|+o option] [-DE] [name ...] set [--abefhkmnptuvxBCHP] [-o option-name] [arg ...] continue [n] shift [n] coproc [NAME] command [redirections] shopt [-pqsu] [-o] [optname ...] declare [-aAfFilrtux] [-p] [name[=value] ...] source filename [arguments] dirs [-clpv] [+N] [-N] suspend [-f] disown [-h] [-ar] [jobspec ...] test [expr] echo [-neE] [arg ...] time [-p] pipeline enable [-a] [-dnps] [-f filename] [name ...] times eval [arg ...] trap [-lp] [[arg] signal_spec ...] exec [-cl] [-a name] [command [arguments ...]] [redirection> true exit [n] type [-afptP] name [name ...] export [-fn] [name[=value] ...] or export -p typeset [-aAfFilrtux] [-p] name[=value] ... false ulimit [-SHacdefilmnpqrstuvx] [limit] fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [com> umask [-p] [-S] [mode] fg [job_spec] unalias [-a] name [name ...] for NAME [in WORDS ... ] ; do COMMANDS; done unset [-f] [-v] [name ...] for (( exp1; exp2; exp3 )); do COMMANDS; done until COMMANDS; do COMMANDS; done function name { COMMANDS ; } or name () { COMMANDS ; } variables - Names and meanings of some shell variables getopts optstring name [arg] wait [id] hash [-lr] [-p pathname] [-dt] [name ...] while COMMANDS; do COMMANDS; done help [-dms] [pattern ...] { COMMANDS ; }
2011-04-13 11:49:45 +00:00
# Tick, tock, im getting rid of this shit soon.
val.replace("")
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.
# @return [Array] The command data and arg string pair
def command_matched(val)
_, cmd_data = commands.commands.find do |name, cmd_data|
/^#{Regexp.escape(name)}(?!\S)(?:\s+(.+))?/ =~ val
end
[cmd_data, $1]
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)
def val.clear() replace("") end
def eval_string.clear() replace("") end
if system_command?(val)
execute_system_command(val, target)
return
end
# no command was matched, so return to caller
return if !pry_command?(val)
val.replace interpolate_string(val, target)
cmd_data, args_string = command_matched(val)
args = args_string ? Shellwords.shellwords(args_string) : []
action = cmd_data[:action]
keep_retval = cmd_data[:keep_retval]
options = {
:val => val,
:eval_string => eval_string,
:nesting => nesting,
:commands => commands.commands
}
ret_value = execute_command(target, action, options, *args)
# return value of block only if :keep_retval is true
ret_value if keep_retval
end
# Execute a Pry command.
# This method should not need to be invoked directly.
# @param [Binding] target The target of the Pry session.
# @param [Proc] action The proc that implements the command.
# @param [Hash] options The options to set on the Commands object.
# @param [Array] args The command arguments.
def execute_command(target, action, options, *args)
# set some useful methods to be used by the action blocks
commands.opts = options
commands.target = target
commands.output = output
case action.arity <=> 0
when -1
# Use instance_exec() to make the `opts` method, etc available
ret_val = commands.instance_exec(*args, &action)
when 1, 0
# ensure that we get the right number of parameters
# since 1.8.7 complains about incorrect arity (1.9.2
# doesn't care)
args_with_corrected_arity = args.values_at *0..(action.arity - 1)
ret_val = commands.instance_exec(*args_with_corrected_arity, &action)
end
added highlighting to disabled commands in GNU bash, version 4.1.5(1)-release (i486-pc-linux-gnu) These shell commands are defined internally. Type `help' to see this list. Type `help name' to find out more about the function `name'. Use `info bash' to find out more about the shell in general. Use `man -k' or `info' to find out more about commands not in this list. A star (*) next to a name means that the command is disabled. job_spec [&] history [-c] [-d offset] [n] or history -anrw [filename] o> (( expression )) if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS> . filename [arguments] jobs [-lnprs] [jobspec ...] or jobs -x command [args] : kill [-s sigspec | -n signum | -sigspec] pid | jobspec ...> [ arg... ] let arg [arg ...] [[ expression ]] local [option] name[=value] ... alias [-p] [name[=value] ... ] logout [n] bg [job_spec ...] mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C> bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-u nam> popd [-n] [+N | -N] break [n] printf [-v var] format [arguments] builtin [shell-builtin [arg ...]] pushd [-n] [+N | -N | dir] caller [expr] pwd [-LP] case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-> cd [-L|-P] [dir] readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [> command [-pVv] command [arg ...] readonly [-af] [name[=value] ...] or readonly -p compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpa> return [n] complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action> select NAME [in WORDS ... ;] do COMMANDS; done compopt [-o|+o option] [-DE] [name ...] set [--abefhkmnptuvxBCHP] [-o option-name] [arg ...] continue [n] shift [n] coproc [NAME] command [redirections] shopt [-pqsu] [-o] [optname ...] declare [-aAfFilrtux] [-p] [name[=value] ...] source filename [arguments] dirs [-clpv] [+N] [-N] suspend [-f] disown [-h] [-ar] [jobspec ...] test [expr] echo [-neE] [arg ...] time [-p] pipeline enable [-a] [-dnps] [-f filename] [name ...] times eval [arg ...] trap [-lp] [[arg] signal_spec ...] exec [-cl] [-a name] [command [arguments ...]] [redirection> true exit [n] type [-afptP] name [name ...] export [-fn] [name[=value] ...] or export -p typeset [-aAfFilrtux] [-p] name[=value] ... false ulimit [-SHacdefilmnpqrstuvx] [limit] fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [com> umask [-p] [-S] [mode] fg [job_spec] unalias [-a] name [name ...] for NAME [in WORDS ... ] ; do COMMANDS; done unset [-f] [-v] [name ...] for (( exp1; exp2; exp3 )); do COMMANDS; done until COMMANDS; do COMMANDS; done function name { COMMANDS ; } or name () { COMMANDS ; } variables - Names and meanings of some shell variables getopts optstring name [arg] wait [id] hash [-lr] [-p pathname] [-dt] [name ...] while COMMANDS; do COMMANDS; done help [-dms] [pattern ...] { COMMANDS ; }
2011-04-13 11:49:45 +00:00
# Tick, tock, im getting rid of this shit soon.
options[:val].clear
ret_val
end
end
end