Class: Pry::Command

Inherits:
Object show all
Includes:
Helpers::BaseHelpers, Helpers::CommandHelpers
Defined in:
lib/pry/command.rb

Overview

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.

Direct Known Subclasses

BlockCommand, ClassCommand

Constant Summary collapse

VOID_VALUE =

represents a void return value for a command

Object.new

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers::CommandHelpers

absolute_index_number, #absolute_index_number, absolute_index_range, #absolute_index_range, #blocking_flag_for_editor, blocking_flag_for_editor, command_error, #command_error, #editor_name, editor_name, file_and_line_from_binding, #file_and_line_from_binding, #get_method_or_raise, get_method_or_raise, #internal_binding?, internal_binding?, #invoke_editor, invoke_editor, #make_header, make_header, #one_index_number, one_index_number, one_index_range, #one_index_range, #one_index_range_or_number, one_index_range_or_number, render_output, #render_output, #restrict_to_lines, restrict_to_lines, #start_line_syntax_for_editor, start_line_syntax_for_editor, temp_file, #temp_file, #unindent, unindent

Methods included from Helpers::OptionsHelpers

#method_object, method_object, method_options, #method_options

Methods included from Helpers::BaseHelpers

colorize_code, #colorize_code, #command_dependencies_met?, command_dependencies_met?, #create_command_stub, create_command_stub, find_command, #find_command, gem_installed?, #gem_installed?, heading, #heading, #highlight, highlight, #jruby?, jruby?, #lesspipe, lesspipe, mri_18?, #mri_18?, #mri_19?, mri_19?, #not_a_real_file?, not_a_real_file?, #page_size, page_size, #rbx?, rbx?, #set_file_and_dir_locals, set_file_and_dir_locals, silence_warnings, #silence_warnings, #simple_pager, simple_pager, stagger_output, #stagger_output, #stub_proc, stub_proc, #use_ansi_codes?, use_ansi_codes?, #windows?, windows?, #windows_ansi?, windows_ansi?

Constructor Details

#initialize(context = {}) ⇒ Command

Instantiate a command, in preparation for calling it.

Parameters:

  • context (Hash) (defaults to: {})

    The runtime context to use with this command.



215
216
217
218
219
220
221
222
# File 'lib/pry/command.rb', line 215

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._pry_        = context[:pry_instance]
end

Class Attribute Details

.blockObject



49
50
51
# File 'lib/pry/command.rb', line 49

def block
  @block || instance_method(:process) && instance_method(:process)
end

.command_options(arg = nil) ⇒ Object

Define or get the command's options



34
35
36
37
38
# File 'lib/pry/command.rb', line 34

def command_options(arg=nil)
  @command_options ||= {}
  @command_options.merge!(arg) if arg
  @command_options
end

.description(arg = nil) ⇒ Object

Define or get the command's description



28
29
30
31
# File 'lib/pry/command.rb', line 28

def description(arg=nil)
  @description = arg if arg
  @description
end

.match(arg = nil) ⇒ Object



22
23
24
25
# File 'lib/pry/command.rb', line 22

def match(arg=nil)
  @match = arg if arg
  @match
end

Instance Attribute Details

#_pry_Object

Returns the value of attribute pry.



173
174
175
# File 'lib/pry/command.rb', line 173

def _pry_
  @_pry_
end

#arg_stringObject

Returns the value of attribute arg_string.



170
171
172
# File 'lib/pry/command.rb', line 170

def arg_string
  @arg_string
end

#capturesObject

Returns the value of attribute captures.



168
169
170
# File 'lib/pry/command.rb', line 168

def captures
  @captures
end

#command_blockObject

The block we pass into a command so long as :takes_block is not equal to false

Examples:

my-command | do
  puts "block content"
end


181
182
183
# File 'lib/pry/command.rb', line 181

def command_block
  @command_block
end

#command_setObject

Returns the value of attribute command_set.



172
173
174
# File 'lib/pry/command.rb', line 172

def command_set
  @command_set
end

#contextObject

Returns the value of attribute context.



171
172
173
# File 'lib/pry/command.rb', line 171

def context
  @context
end

#eval_stringObject

Returns the value of attribute eval_string.



169
170
171
# File 'lib/pry/command.rb', line 169

def eval_string
  @eval_string
end

#outputObject

Properties of one execution of a command (passed by Pry#run_command as a hash of context and expanded in #initialize



166
167
168
# File 'lib/pry/command.rb', line 166

def output
  @output
end

#targetObject

Returns the value of attribute target.



167
168
169
# File 'lib/pry/command.rb', line 167

def target
  @target
end

Class Method Details

Define or get the command's banner



44
45
46
47
# File 'lib/pry/command.rb', line 44

def banner(arg=nil)
  @banner = arg if arg
  @banner || description
end

.command_regexObject



125
126
127
128
129
130
131
# File 'lib/pry/command.rb', line 125

def command_regex
  pr = defined?(Pry.config.command_prefix) ? Pry.config.command_prefix : ""
  prefix = convert_to_regex(pr)
  prefix = "(?:#{prefix})?" unless options[:use_prefix]

  /^#{prefix}#{convert_to_regex(match)}(?!\S)/
end

.convert_to_regex(obj) ⇒ Object



133
134
135
136
137
138
139
140
# File 'lib/pry/command.rb', line 133

def convert_to_regex(obj)
  case obj
  when String
    Regexp.escape(obj)
  else
    obj
  end
end

.group(name = nil) ⇒ Object

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.



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/pry/command.rb', line 145

def group(name=nil)
  @group ||= if name
               name
             else
               case Pry::Method(block).source_file
               when %r{/pry/.*_commands/(.*).rb}
                 $1.capitalize.gsub(/_/, " ")
               when %r{(pry-\w+)-([\d\.]+([\w\d\.]+)?)}
                 name, version = $1, $2
                 "#{name.to_s} (v#{version.to_s})"
               when /pryrc/
                 "~/.pryrc"
               else
                 "(other)"
               end
             end
end

.hooksObject

Store hooks to be run before or after the command body.

See Also:

  • {Pry{Pry::CommandSet{Pry::CommandSet#before_command}
  • {Pry{Pry::CommandSet{Pry::CommandSet#after_command}


121
122
123
# File 'lib/pry/command.rb', line 121

def hooks
  @hooks ||= {:before => [], :after => []}
end

.inspectObject



66
67
68
# File 'lib/pry/command.rb', line 66

def inspect
  name
end

.match_score(val) ⇒ Fixnum

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.

Examples:

/\.(.*)/.match_score(".foo") #=> 1
/\.*(.*)/.match_score("...foo") #=> 3
'hi'.match_score("hi there") #=> 2

Parameters:

  • val (String)

    A line input at the REPL

Returns:

  • (Fixnum)


110
111
112
113
114
115
116
# File 'lib/pry/command.rb', line 110

def match_score(val)
  if command_regex =~ val
    Regexp.last_match.size > 1 ? Regexp.last_match.begin(1) : Regexp.last_match.end(0)
  else
    -1
  end
end

.matches?(val) ⇒ Boolean

Should this command be called for the given line?

Parameters:

  • val (String)

    A line input at the REPL

Returns:

  • (Boolean)


90
91
92
# File 'lib/pry/command.rb', line 90

def matches?(val)
  command_regex =~ val
end

.nameObject



63
64
65
# File 'lib/pry/command.rb', line 63

def name
  super.to_s == "" ? "#<class(Pry::Command #{match.inspect})>" : super
end

.optionsObject

Define or get the command's options backward compatibility



40
41
42
43
44
# File 'lib/pry/command.rb', line 40

def command_options(arg=nil)
  @command_options ||= {}
  @command_options.merge!(arg) if arg
  @command_options
end

.subclass(match, description, options, helpers) { ... } ⇒ Class

Create a new command with the given properties.

Parameters:

  • match (String, Regex)

    The thing that triggers this command

  • description (String)

    The description to appear in help

  • options (Hash)

    Behavioral options (see Pry::CommandSet#command)

  • helpers (Module)

    A module of helper functions to be included.

Yields:

  • optional, used for BlockCommands

Returns:



77
78
79
80
81
82
83
84
85
# File 'lib/pry/command.rb', line 77

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

Instance Method Details

#blockObject



58
# File 'lib/pry/command.rb', line 58

def block; self.class.block; end

#call_safely(*args) ⇒ Object

Run the command with the given args.

This is a public wrapper around #call which ensures all preconditions are met.

Parameters:

  • args (Array<String>)

    The arguments to pass to this command.

Returns:



358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'lib/pry/command.rb', line 358

def call_safely(*args)
  unless dependencies_met?
    gems_needed = Array(command_options[:requires_gem])
    gems_not_installed = gems_needed.select { |g| !gem_installed?(g) }
    output.puts "\nThe command '#{command_name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
    output.puts "-"
    output.puts "Type `install-command #{command_name}` to install the required gems and activate this command."
    return void
  end

  if command_options[:argument_required] && args.empty?
    raise CommandError, "The command '#{command_name}' requires an argument."
  end

  ret = call_with_hooks(*args)
  command_options[:keep_retval] ? ret : void
end

#call_with_hooks(*args) ⇒ Object (private)

Run the #call method and all the registered hooks.

Parameters:

  • args (Array<String>)

    The arguments to #call

Returns:

  • (Object)

    The return value from #call



388
389
390
391
392
393
394
395
396
397
398
399
400
# File 'lib/pry/command.rb', line 388

def call_with_hooks(*args)
  self.class.hooks[:before].each do |block|
    instance_exec(*args, &block)
  end

  ret = call(*args)

  self.class.hooks[:after].each do |block|
    ret = instance_exec(*args, &block)
  end

  ret
end

#check_for_command_collision(command_match, arg_string) ⇒ Object

Display a warning if a command collides with a local/method in the current scope.



254
255
256
257
258
259
260
261
262
263
# File 'lib/pry/command.rb', line 254

def check_for_command_collision(command_match, arg_string)
  collision_type = target.eval("defined?(#{command_match})")
  collision_type ||= 'local-variable' if arg_string.match(%r{\A\s*[-+*/%&|^]*=})

  if collision_type
    output.puts "#{Pry::Helpers::Text.bold('WARNING:')} Calling Pry command '#{command_match}'," +
                                                      "which conflicts with a #{collision_type}.\n\n"
  end
rescue Pry::RescuableException
end

#command_nameObject



60
# File 'lib/pry/command.rb', line 60

def command_name; command_options[:listing]; end

#command_optionsObject



59
# File 'lib/pry/command.rb', line 59

def command_options; self.class.options; end

#commandsObject



197
198
199
# File 'lib/pry/command.rb', line 197

def commands
  command_set.commands
end

#correct_arg_arity(arity, args) ⇒ Array (private)

Fix the number of arguments we pass to a block to avoid arity warnings.

Parameters:

  • arity (Fixnum)

    The arity of the block

  • args (Array)

    The arguments to pass

Returns:

  • (Array)

    A (possibly shorter) array of the arguments to pass



406
407
408
409
410
411
412
413
414
415
# File 'lib/pry/command.rb', line 406

def correct_arg_arity(arity, args)
  case
  when arity < 0
    args
  when arity == 0
    []
  when arity > 0
    args.values_at(*(0..(arity - 1)).to_a)
  end
end

#dependencies_met?Boolean

Are all the gems required to use this command installed?

Returns:

  • (Boolean)

    Boolean



379
380
381
# File 'lib/pry/command.rb', line 379

def dependencies_met?
  @dependencies_met ||= command_dependencies_met?(command_options)
end

#descriptionObject



57
# File 'lib/pry/command.rb', line 57

def description; self.class.description; end

#interpolate_string(str) ⇒ String

Revaluate the string (str) and perform interpolation.

Parameters:

  • str (String)

    The string to reevaluate with interpolation.

Returns:

  • (String)

    The reevaluated string with interpolations applied (if any).



243
244
245
246
247
248
249
250
# File 'lib/pry/command.rb', line 243

def interpolate_string(str)
  dumped_str = str.dump
  if dumped_str.gsub!(/\\\#\{/, '#{')
    target.eval(dumped_str)
  else
    str
  end
end

#matchObject



56
# File 'lib/pry/command.rb', line 56

def match; self.class.match; end

#nameObject

Make those properties accessible to instances



55
# File 'lib/pry/command.rb', line 55

def name; self.class.name; end

#pass_block(arg_string) ⇒ Object (private)

Pass a block argument to a command.

Parameters:

  • arg_string (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.



327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/pry/command.rb', line 327

def pass_block(arg_string)
  block_index = arg_string.rindex(/\| *(?:do|\{)/)

  return if !block_index

  block_init_string = arg_string.slice!(block_index..-1)[1..-1]
  prime_string = "proc #{block_init_string}\n"

  if !Pry::Code.complete_expression?(prime_string)
    block_string = _pry_.r(target, prime_string)
  else
    block_string = prime_string
  end

  begin
    self.command_block = target.eval(block_string)
  rescue Pry::RescuableException
    raise CommandError, "Incomplete block definition."
  end
end

#process_line(line) ⇒ Object, Command::VOID_VALUE

Process a line that Command.matches? this command.

Parameters:

  • line (String)

    The line to process

Returns:



309
310
311
312
313
314
315
316
317
318
# File 'lib/pry/command.rb', line 309

def process_line(line)
  command_match, arg_string, captures, args = tokenize(line)

  check_for_command_collision(command_match, arg_string) if Pry.config.collision_warning

  self.arg_string = arg_string
  self.captures = captures

  call_safely(*(captures + args))
end

#run(command_string, *args) ⇒ Object

Run a command from another command.

Examples:

run "show-input"
run ".ls"
run "amend-line",  "5", 'puts "hello world"'

Parameters:

  • command_string (String)

    The string that invokes the command

  • args (Array)

    Further arguments to pass to the command



192
193
194
195
# File 'lib/pry/command.rb', line 192

def run(command_string, *args)
  complete_string = "#{command_string} #{args.join(" ")}".rstrip
  command_set.process_line(complete_string, context)
end

#stateHash

Returns 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.

Examples:

state.my_state = "my state"  # this will not conflict with any
                             # `state.my_state` used in another command.

Returns:

  • (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.



234
235
236
# File 'lib/pry/command.rb', line 234

def state
  _pry_.command_state[match] ||= OpenStruct.new
end

#target_selfObject

Returns The value of self inside the target binding.

Returns:

  • (Object)

    The value of self inside the target binding.



225
# File 'lib/pry/command.rb', line 225

def target_self; target.eval('self'); end

#textObject



201
202
203
# File 'lib/pry/command.rb', line 201

def text
  Pry::Helpers::Text
end

#tokenize(val) ⇒ Array

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

Parameters:

  • val (String)

    The line of input

Returns:

Raises:



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/pry/command.rb', line 279

def tokenize(val)
  val.replace(interpolate_string(val)) if command_options[:interpolate]

  self.class.command_regex =~ val

  # please call Command.matches? before Command#call_safely
  raise CommandError, "fatal: called a command which didn't match?!" unless Regexp.last_match
  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]

  if arg_string
    args = command_options[:shellwords] ? Shellwords.shellwords(arg_string) : arg_string.split(" ")
  else
    args = []
  end

  [val[0..pos].rstrip, arg_string, captures, args]
end

#voidObject



205
206
207
# File 'lib/pry/command.rb', line 205

def void
  VOID_VALUE
end