pry--pry/lib/pry/command_base.rb

203 lines
6.9 KiB
Ruby
Raw Normal View History

require 'rubygems/dependency_installer'
require "pry/command_base_helpers"
class Pry
# Basic command functionality. All user-defined commands must
# inherit from this class. It provides the `command` method.
class CommandBase
class << self
include CommandBaseHelpers
2011-04-18 21:31:39 +00:00
attr_accessor :commands
attr_accessor :opts, :output, :target
# private because we want to force function style invocation. We require
# that the location where the block is defined has the `opts`
# method in scope.
private
2011-04-18 21:31:39 +00:00
# Defines a new Pry command.
# @param [String, Array] names The name of the command (or array of
# command name aliases).
2011-01-18 03:40:28 +00:00
# @param [String] description A description of the command.
# @param [Hash] options The optional configuration parameters.
# @option options [Boolean] :keep_retval Whether or not to use return value
# of the block for return of `command` or just to return `nil`
# (the default).
2011-01-18 03:40:28 +00:00
# @yield The action to perform. The parameters in the block
# determines the parameters the command will receive. All
# parameters passed into the block will be strings. Successive
# command parameters are separated by whitespace at the Pry prompt.
# @example
# class MyCommands < Pry::CommandBase
# command "greet", "Greet somebody" do |name|
# puts "Good afternoon #{name.capitalize}!"
# end
# end
#
# # From pry:
# # pry(main)> _pry_.commands = MyCommands
# # pry(main)> greet john
# # Good afternoon John!
# # pry(main)> help greet
# # Greet somebody
def command(names, description="No description.", options={}, &block)
options = {
:keep_retval => false,
:requires_gem => nil
}.merge!(options)
2011-04-18 21:31:39 +00:00
@commands ||= {}
if command_dependencies_met?(options)
Array(names).each do |name|
commands[name] = {
:description => description,
:action => block,
:keep_retval => options[:keep_retval]
}
end
else
create_command_stub(names, description, options, block)
end
end
# Delete a command or an array of commands.
# Useful when inheriting from another command set and pruning
# those commands down to the ones you want.
# @param [Array<String>] names The command name or array
# of command names you want to delete
# @example Deleteing inherited commands
# class MyCommands < Pry::Commands
# delete "show_method", "show_imethod", "show_doc", "show_idoc"
# end
# Pry.commands = MyCommands
def delete(*names)
names.each { |name| commands.delete(name) }
end
# Execute a command (this enables commands to call other commands).
# @param [String] name The command to execute
# @param [Array] args The parameters to pass to the command.
# @example Wrap one command with another
# class MyCommands < Pry::Commands
# command "ls2" do
# output.puts "before ls"
# run "ls"
# output.puts "after ls"
# end
# end
def run(name, *args)
command_processor = CommandProcessor.new(target.eval('_pry_'))
2011-04-18 21:31:39 +00:00
if command_processor.system_command?(name)
command_processor.execute_system_command("#{name} #{args.join(' ')}", target)
else
raise "#{name.inspect} is not a valid pry command." unless opts[:commands].include? name
action = opts[:commands][name][:action]
instance_exec(*args, &action)
end
end
# Import commands from another command object.
# @param [Pry::CommandBase] klass The class to import from (must
# be a subclass of `Pry::CommandBase`)
# @param [Array<String>] names The commands to import.
# @example
# class MyCommands < Pry::CommandBase
# import_from Pry::Commands, "ls", "show_method", "cd"
# end
def import_from(klass, *names)
imported_hash = Hash[klass.commands.select { |k, v| names.include?(k) }]
commands.merge!(imported_hash)
end
# Create an alias for a command.
# @param [String] new_command The alias name.
# @param [String] orig_command The original command name.
2011-01-27 19:55:37 +00:00
# @param [String] desc The optional description.
# @example
# class MyCommands < Pry::CommandBase
# alias_command "help_alias", "help"
2011-01-27 19:55:37 +00:00
# end
def alias_command(new_command_name, orig_command_name, desc=nil)
commands[new_command_name] = commands[orig_command_name].dup
commands[new_command_name][:description] = desc if desc
end
# Set the description for a command (replacing the old
# description.)
# @param [String] name The command name.
# @param [String] description The command description.
# @example
# class MyCommands < Pry::CommandBase
# desc "help", "help description"
# end
def desc(name, description)
commands[name][:description] = description
end
end
2011-04-18 21:31:39 +00:00
command "help", "This menu." do |cmd|
command_info = opts[:commands]
if !cmd
output.puts
2011-04-18 21:31:39 +00:00
help_text = heading("Command List:") + "\n"
command_info.each do |k, data|
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
if !data[:stub_info]
help_text << ("#{k}".ljust(18) + data[:description] + "\n") if !data[:description].empty?
else
help_text << (bold("#{k}".ljust(18) + data[:description] + "\n")) if !data[:description].empty?
end
end
stagger_output(help_text)
else
if command_info[cmd]
output.puts command_info[cmd][:description]
else
output.puts "No info for command: #{cmd}"
end
end
end
command "install", "Install a disabled command." do |name|
stub_info = commands[name][:stub_info]
if !stub_info
output.puts "Not a command stub. Nothing to do."
next
end
output.puts "Attempting to install `#{name}` command..."
gems_to_install = Array(stub_info[:requires_gem])
gem_install_failed = false
gems_to_install.each do |g|
next if gem_installed?(g)
output.puts "Installing `#{g}` gem..."
begin
2011-04-18 21:31:39 +00:00
Gem::DependencyInstaller.new.install(g)
rescue Gem::GemNotFoundException
output.puts "Required Gem: `#{g}` not found. Aborting command installation."
gem_install_failed = true
next
end
end
next if gem_install_failed
2011-04-18 21:31:39 +00:00
Gem.refresh
load "#{File.dirname(__FILE__)}/commands.rb"
output.puts "Installation of `#{name}` successful! Type `help #{name}` for information"
end
2011-01-18 03:40:28 +00:00
# Ensures that commands can be inherited
def self.inherited(klass)
klass.commands = commands.dup
end
2011-04-18 21:31:39 +00:00
end
end