class Pry::Command
The super-class of all commands, new commands should be created by calling {Pry::CommandSet#command} which creates a BlockCommand
or {Pry::CommandSet#create_command} which creates a ClassCommand
. Please don’t use this class directly.
N.B. using a regular expression here so that “raise-up ‘foo’” does the right thing.
Constants
- VOID_VALUE
-
represents a void return value for a command
Attributes
The block we pass into a command so long as ‘:takes_block` is not equal to `false` @example
my-command | do puts "block content" end
Properties of one execution of a command (passed by {Pry#run_command} as a hash of context and expanded in ‘#initialize`
Public Class Methods
Source
# File lib/pry/command.rb, line 66 def block @block || instance_method(:process) end
Source
# File lib/pry/command.rb, line 51 def command_options(arg = nil) @command_options ||= default_options(match) @command_options.merge!(arg) if arg @command_options end
Define or get the command’s options
Source
# File lib/pry/command.rb, line 165 def command_regex prefix = convert_to_regex(Pry.config.command_prefix) prefix = "(?:#{prefix})?" unless options[:use_prefix] /\A#{prefix}#{convert_to_regex(match)}(?!\S)/ end
Source
# File lib/pry/command.rb, line 172 def convert_to_regex(obj) case obj when String Regexp.escape(obj) else obj end end
Source
# File lib/pry/command.rb, line 89 def default_options(match) { keep_retval: false, argument_required: false, interpolate: true, shellwords: true, listing: (match.is_a?(String) ? match : match.inspect), use_prefix: true, takes_block: false } end
Source
# File lib/pry/command.rb, line 45 def description(arg = nil) @description = arg if arg @description ||= nil end
Define or get the command’s description
Source
# File lib/pry/command.rb, line 185 def group(name = nil) @group ||= begin name || case Pry::Method(block).source_file when %r{/pry/.*_commands/(.*).rb} Regexp.last_match(1).capitalize.tr('_', " ") when /(pry-\w+)-([\d\.]+([\w\.]+)?)/ name = Regexp.last_match(1) version = Regexp.last_match(2) "#{name} (v#{version})" when /pryrc/ "pryrc" else "(other)" end end end
The group in which the command should be displayed in “help” output. This is usually auto-generated from directory naming, but it can be manually overridden if necessary. Group should not be changed once it is initialized.
Source
# File lib/pry/command.rb, line 35 def match(arg = nil) if arg @command_options ||= default_options(arg) @command_options[:listing] = arg.is_a?(String) ? arg : arg.inspect @match = arg end @match ||= nil end
Source
# File lib/pry/command.rb, line 153 def match_score(val) if command_regex =~ val if Regexp.last_match.size > 1 Regexp.last_match.begin(1) else Regexp.last_match.end(0) end else -1 end end
How well does this command match the given line?
Higher scores are better because they imply that this command matches the line more closely.
The score is calculated by taking the number of characters at the start of the string that are used only to identify the command, not as part of the arguments.
@example
/\.(.*)/.match_score(".foo") #=> 1 /\.*(.*)/.match_score("...foo") #=> 3 'hi'.match_score("hi there") #=> 2
@param [String] val A line input at the REPL
@return [Fixnum]
Source
# File lib/pry/command.rb, line 133 def matches?(val) command_regex =~ val end
Should this command be called for the given line? @param [String] val A line input at the REPL
@return [Boolean]
Source
# File lib/pry/command.rb, line 101 def name super.to_s == "" ? "#<class(Pry::Command #{match.inspect})>" : super end
Source
# File lib/pry/command.rb, line 230 def initialize(context = {}) self.context = context self.target = context[:target] self.output = context[:output] self.eval_string = context[:eval_string] self.command_set = context[:command_set] self.hooks = context[:hooks] self.pry_instance = context[:pry_instance] end
Instantiate a command, in preparation for calling it. @param [Hash] context The runtime context to use with this command.
Source
# File lib/pry/command.rb, line 70 def source file, line = block.source_location strip_leading_whitespace(Pry::Code.from_file(file).expression_at(line)) end
Source
# File lib/pry/command.rb, line 79 def source_file Array(block.source_location).first end
Source
# File lib/pry/command.rb, line 84 def source_line Array(block.source_location).last end
Source
# File lib/pry/command.rb, line 202 def state Pry::CommandState.default.state_for(self) end
Source
# File lib/pry/command.rb, line 120 def subclass(match, description, options, helpers, &block) klass = Class.new(self) klass.send(:include, helpers) klass.match = match klass.description = description klass.command_options = options klass.block = block klass end
Create a new command with the given properties. @param [String, Regex] match The thing that triggers this command @param [String] description The description to appear in ‘help` @param [Hash] options Behavioral options (see {Pry::CommandSet#command}) @param [Module] helpers A module of helper functions to be included. @yield optional, used for BlockCommands @return [Class] (a subclass of {Pry::Command})
Public Instance Methods
Source
# File lib/pry/command.rb, line 292 def _pry_ Pry::Warning.warn('_pry_ is deprecated, use pry_instance instead') pry_instance end
Source
# File lib/pry/command.rb, line 329 def check_for_command_collision(command_match, arg_string) collision_type = target.eval("defined?(#{command_match})") collision_type ||= 'local-variable' if arg_string =~ %r{\A\s*[-+*/%&|^]*=} if collision_type output.puts( "#{Helpers::Text.bold('WARNING:')} Calling Pry command '#{command_match}', " \ "which conflicts with a #{collision_type}.\n\n" ) end rescue Pry::RescuableException # rubocop:disable Lint/HandleExceptions end
Display a warning if a command collides with a local/method in the current scope.
Source
# File lib/pry/command.rb, line 261 def command_name self.class.command_name end
Source
# File lib/pry/command.rb, line 257 def command_options self.class.options end
Source
# File lib/pry/command.rb, line 411 def complete(_search) [] end
Generate completions for this command
@param [String] _search The line typed so far @return [Array<String>] Completion words
Source
# File lib/pry/command.rb, line 249 def description self.class.description end
Source
# File lib/pry/command.rb, line 318 def interpolate_string(str) dumped_str = str.dump if dumped_str.gsub!(/\\\#\{/, '#{') target.eval(dumped_str) else str end end
Revaluate the string (str) and perform interpolation. @param [String] str The string to reevaluate with interpolation.
@return [String] The reevaluated string with interpolations
applied (if any).
Source
# File lib/pry/command.rb, line 241 def name self.class.name end
Make those properties accessible to instances
Source
# File lib/pry/command.rb, line 394 def process_line(line) command_match, arg_string, captures, args = tokenize(line) if Pry.config.collision_warning check_for_command_collision(command_match, arg_string) end self.arg_string = arg_string self.captures = captures call_safely(*(captures + args)) end
Process a line that Command.matches?
this command. @param [String] line The line to process @return [Object, Command::VOID_VALUE]
Source
# File lib/pry/command.rb, line 278 def run(command_string, *args) command_string = pry_instance.config.command_prefix.to_s + command_string complete_string = "#{command_string} #{args.join(' ')}".rstrip command_set.process_line(complete_string, context) end
Run a command from another command. @param [String] command_string The string that invokes the command @param [Array] args Further arguments to pass to the command @example
run "show-input"
@example
run ".ls"
@example
run "amend-line", "5", 'puts "hello world"'
Source
# File lib/pry/command.rb, line 309 def state self.class.state end
@return [Hash] Pry
commands can store arbitrary state
here. This state persists between subsequent command invocations. All state saved here is unique to the command, it does not need to be namespaced.
@example
state.my_state = "my state" # this will not conflict with any # `state.my_state` used in another command.
Source
# File lib/pry/command.rb, line 298 def target_self target.eval('self') end
@return [Object] The value of ‘self` inside the `target` binding.
Source
# File lib/pry/command.rb, line 356 def tokenize(val) val = interpolate_string(val) if command_options[:interpolate] self.class.command_regex =~ val # please call Command.matches? before Command#call_safely unless Regexp.last_match raise CommandError, "fatal: called a command which didn't match?!" end captures = Regexp.last_match.captures pos = Regexp.last_match.end(0) arg_string = val[pos..-1] # remove the one leading space if it exists arg_string.slice!(0) if arg_string.start_with?(" ") # process and pass a block if one is found pass_block(arg_string) if command_options[:takes_block] args = if arg_string if command_options[:shellwords] Shellwords.shellwords(arg_string) else arg_string.split(" ") end else [] end [val[0..pos].rstrip, arg_string, captures, args] end
Extract necessary information from a line that Command.matches?
this command.
Returns an array of four elements:
“‘
[String] the portion of the line that matched with the Command match [String] a string of all the arguments (i.e. everything but the match) [Array] the captures caught by the command_regex [Array] the arguments obtained by splitting the arg_string
“‘
@param [String] val The line of input @return [Array]
Private Instance Methods
Source
# File lib/pry/command.rb, line 481 def before_hooks find_hooks('before') end
Source
# File lib/pry/command.rb, line 425 def call_safely(*args) if command_options[:argument_required] && args.empty? raise CommandError, "The command '#{command_name}' requires an argument." end ret = use_unpatched_symbol do call_with_hooks(*args) end command_options[:keep_retval] ? ret : void end
Run the command with the given ‘args`.
This is a public wrapper around ‘#call` which ensures all preconditions are met.
@param [Array<String>] args The arguments to pass to this command. @return [Object] The return value of the ‘#call` method, or
{Command::VOID_VALUE}.
Source
# File lib/pry/command.rb, line 492 def call_with_hooks(*args) before_hooks.each { |block| instance_exec(*args, &block) } ret = call(*args) after_hooks.each do |block| ret = instance_exec(*args, &block) end ret end
Run the ‘#call` method and all the registered hooks. @param [Array<String>] args The arguments to `#call` @return [Object] The return value from `#call`
Source
# File lib/pry/command.rb, line 476 def find_hooks(event) event_name = "#{event}_#{command_name}" (hooks || Pry.hooks || self.class.hooks).get_hooks(event_name).values end
Source
# File lib/pry/command.rb, line 509 def normalize_method_args(method, args) case method.arity when -1 args when 0 [] else args.values_at(*(0..(method.arity - 1)).to_a) end end
Normalize method arguments according to its arity.
@param [Integer] method @param [Array] args @return [Array] a (possibly shorter) array of the arguments to pass
Source
# File lib/pry/command.rb, line 451 def pass_block(arg_string) # Workaround for weird JRuby bug where rindex in this case can return nil # even when there's a match. arg_string.scan(/\| *(?:do|\{)/) block_index = $LAST_MATCH_INFO && $LAST_MATCH_INFO.offset(0)[0] return unless block_index block_init_string = arg_string.slice!(block_index..-1)[1..-1] prime_string = "proc #{block_init_string}\n" block_string = if !Pry::Code.complete_expression?(prime_string) pry_instance.r(target, prime_string) else prime_string end begin self.command_block = target.eval(block_string) rescue Pry::RescuableException raise CommandError, "Incomplete block definition." end end
Pass a block argument to a command. @param [String] arg_string
The arguments (as a string) passed to the command.
We inspect these for a '| do' or a '| {' and if we find it we use it to start a block input sequence. Once we have a complete block, we save it to an accessor that can be retrieved from the command context. Note that if we find the '| do' or '| {' we delete this and the elements following it from `arg_string`.
Source
# File lib/pry/command.rb, line 436 def use_unpatched_symbol call_method = Symbol.method_defined?(:call) && Symbol.instance_method(:call) Symbol.class_eval { undef :call } if call_method yield ensure Symbol.instance_eval { define_method(:call, call_method) } if call_method end