1
0
Fork 0
mirror of https://github.com/pry/pry.git synced 2022-11-09 12:35:05 -05:00

finished updating and improving command API; now command API is as follows: command 'blah' do |x| puts x; end where x is a parameter passed to the command from the pry prompt

This commit is contained in:
John Mair 2011-01-18 03:38:09 +13:00
parent 500456032c
commit f45e8bfbd0
7 changed files with 147 additions and 257 deletions

View file

@ -10,6 +10,7 @@ require "#{direc}/pry/input"
require "#{direc}/pry/output" require "#{direc}/pry/output"
require "#{direc}/pry/hooks" require "#{direc}/pry/hooks"
require "#{direc}/pry/print" require "#{direc}/pry/print"
require "#{direc}/pry/command_base"
require "#{direc}/pry/commands" require "#{direc}/pry/commands"
require "#{direc}/pry/prompts" require "#{direc}/pry/prompts"
require "#{direc}/pry/completion" require "#{direc}/pry/completion"

View file

@ -6,66 +6,40 @@ class Pry
class << self class << self
attr_accessor :commands attr_accessor :commands
attr_accessor :command_info attr_accessor :command_info
end attr_accessor :opts
# A class to assist in building Pry commands # private because we want to force function style invocation. We require
class Command # that the location where the block is defined has the `opts`
Elements = [:name, :describe, :pattern, :action] # method in scope.
private
Elements.each do |e|
define_method(e) { |s| instance_variable_set("@#{e}", s) }
define_method("get_#{e}") { instance_variable_get("@#{e}") }
end
# define action here since it needs to take a block.
def action(&block)
@action = block
end
end
# Ensure commands are properly constructed.
# @param [Pry::CommandBase::Command] c The command to check.
def self.check_command(c)
c.pattern(c.get_name) if !c.get_pattern
c.describe "No description." if !c.get_describe
Command::Elements.each do |e|
raise "command has no #{e}!" if !c.send("get_#{e}")
end
end
# Defines a new Pry command. # Defines a new Pry command.
# @param [String, Array] name The name of the command (or array of # @param [String, Array] name The name of the command (or array of
# command name aliases). # command name aliases).
# @yield [command] The command block. Optionally yields command if # @yield [command] The action to perform. The parameters in the block
# block arity is 1. Otherwise block is instance_eval'd. # determines the parameters the command will receive.
def self.command(name, &block) def command(name, description="No description.", &block)
@commands ||= {} @commands ||= {}
@command_info ||= {} @command_info ||= {}
c = Command.new arg_match = '(?:\s+(\S+))?' * 20
c.name name if name.is_a?(Array)
matcher = []
if block.arity == 1 name.each do |n|
yield(c) matcher << /^#{n}#{arg_match}?/
end
else else
c.instance_eval(&block) matcher = /^#{name}#{arg_match}?/
end end
check_command(c) commands[matcher] = block
command_info[name] = description
commands.merge! c.get_pattern => c.get_action
command_info.merge! c.get_name => c.get_describe
end end
end
command "help" do command "help", "This menu." do |cmd|
pattern /^help\s*(.+)?/
describe "This menu."
action do |opts|
out = opts[:output] out = opts[:output]
command_info = opts[:command_info] command_info = opts[:command_info]
param = opts[:captures].first param = cmd
if !param if !param
out.puts "Command list:" out.puts "Command list:"
@ -81,9 +55,6 @@ class Pry
out.puts "No info for command: #{param}" out.puts "No info for command: #{param}"
end end
end end
opts[:val].clear
end
end end
def self.inherited(klass) def self.inherited(klass)

View file

@ -24,30 +24,20 @@ class Pry
# Pry.commands = MyCommands # Pry.commands = MyCommands
class Commands < CommandBase class Commands < CommandBase
command "!" do command "!", "Refresh the REPL" do
describe "Refresh the REPL"
action do |opts|
opts[:output].puts "Refreshed REPL" opts[:output].puts "Refreshed REPL"
opts[:eval_string].clear opts[:eval_string].clear
end end
end
command "!pry" do command "!pry", "Start a Pry session on current self; this even works mid-expression." do
describe "Start a Pry session on current self; this even works mid-expression."
action do |opts|
Pry.start(opts[:target]) Pry.start(opts[:target])
end end
command ["exit_program", "quit_program"], "End the current program." do
exit
end end
command ["exit_program", "quit_program"] do command "nesting", "Show nesting information." do
describe "End the current program."
action { |opts| exit }
end
command "nesting" do
describe "Show nesting information."
action do |opts|
out = opts[:output] out = opts[:output]
nesting = opts[:nesting] nesting = opts[:nesting]
@ -61,12 +51,8 @@ class Pry
end end
end end
end end
end
command "status" do command "status", "Show status information." do
describe "Show status information."
action do |opts|
out = opts[:output] out = opts[:output]
nesting = opts[:nesting] nesting = opts[:nesting]
target = opts[:target] target = opts[:target]
@ -79,89 +65,47 @@ class Pry
out.puts "Pry instance: #{Pry.active_instance}" out.puts "Pry instance: #{Pry.active_instance}"
out.puts "Last result: #{Pry.view(Pry.last_result)}" out.puts "Last result: #{Pry.view(Pry.last_result)}"
end end
command "exit_all", "End all nested Pry sessions." do
throw(:breakout, 0)
end end
command "exit_all" do command "ls", "Show the list of vars in the current scope." do
describe "End all nested Pry sessions."
action { |opts| throw(:breakout, 0) }
end
command "ls" do
describe "Show the list of vars in the current scope."
action do |opts|
opts[:output].puts "#{opts[:target].eval('Pry.view(local_variables + instance_variables)')}" opts[:output].puts "#{opts[:target].eval('Pry.view(local_variables + instance_variables)')}"
end end
end
command "cat" do command "cat", "Show output of <var>.inspect." do |obj|
describe "Show output of <var>.inspect."
pattern /^cat\s+(.+)/
action do |opts|
out = opts[:output] out = opts[:output]
obj = opts[:captures].first
out.puts opts[:target].eval("#{obj}.inspect") out.puts opts[:target].eval("#{obj}.inspect")
end end
end
command "cd" do command "cd", "Start a Pry session on <var> (use `cd ..` to go back)" do |obj|
pattern /^cd\s+(.+)/
describe "Start a Pry session on <var> (use `cd ..` to go back)"
action do |opts|
obj = opts[:captures].first
throw(:breakout, opts[:nesting].level) if obj == ".." throw(:breakout, opts[:nesting].level) if obj == ".."
opts[:target].eval("#{obj}.pry") opts[:target].eval("#{obj}.pry")
end end
end
command "show_doc" do command "show_doc", "Show the comments above <methname>" do |meth_name|
pattern /^show_doc\s*(.+)/
describe "Show the comments above <methname>"
action do |opts|
meth_name = opts[:captures].first
doc = opts[:target].eval("method(:#{meth_name})").comment doc = opts[:target].eval("method(:#{meth_name})").comment
opts[:output].puts doc opts[:output].puts doc
end end
end
command "show_idoc" do command "show_idoc", "Show the comments above instance method <methname>" do |meth_name|
pattern /^show_idoc\s*(.+)/
describe "Show the comments above instance method <methname>"
action do |opts|
meth_name = opts[:captures].first
doc = opts[:target].eval("instance_method(:#{meth_name})").comment doc = opts[:target].eval("instance_method(:#{meth_name})").comment
opts[:output].puts doc opts[:output].puts doc
end end
end
command "show_method" do command "show_method", "Show sourcecode for method <methname>." do |meth_name|
pattern /^show_method\s*(.+)/
describe "Show sourcecode for method <methname>."
action do |opts|
meth_name = opts[:captures].first
doc = opts[:target].eval("method(:#{meth_name})").source doc = opts[:target].eval("method(:#{meth_name})").source
opts[:output].puts doc opts[:output].puts doc
end end
end
command "show_imethod" do command "show_imethod", "Show sourcecode for instance method <methname>." do |meth_name|
pattern /^show_imethod\s*(.+)/
describe "Show sourcecode for instance method <methname>."
action do |opts|
meth_name = opts[:captures].first
doc = opts[:target].eval("instance_method(:#{meth_name})").source doc = opts[:target].eval("instance_method(:#{meth_name})").source
opts[:output].puts doc opts[:output].puts doc
end end
end
command "jump_to" do command "jump_to", "Jump to a Pry session further up the stack, exiting all sessions below." do |break_level|
pattern /^jump_to\s*(\d*)/ break_level = break_level.to_i
describe "Jump to a Pry session further up the stack, exiting all sessions below."
action do |opts|
break_level = opts[:captures].first.to_i
nesting = opts[:nesting] nesting = opts[:nesting]
case break_level case break_level
@ -174,29 +118,17 @@ class Pry
opts[:output].puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}." opts[:output].puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}."
end end
end end
end
command "ls_methods" do command "ls_methods", "List public methods defined on class of receiver." do
describe "List public methods defined on class of receiver."
action do |opts|
opts[:output].puts "#{Pry.view(opts[:target].eval('public_methods(false)'))}" opts[:output].puts "#{Pry.view(opts[:target].eval('public_methods(false)'))}"
end end
end
command "ls_imethods" do command "ls_imethods", "List public instance methods defined on class of receiver." do
describe "List public instance methods defined on class of receiver."
action do |opts|
opts[:output].puts "#{Pry.view(opts[:target].eval('public_instance_methods(false)'))}" opts[:output].puts "#{Pry.view(opts[:target].eval('public_instance_methods(false)'))}"
end end
end
command ["exit", "quit", "back"] do command ["exit", "quit", "back"], "End the current Pry session." do
describe "End the current Pry session."
action do |opts|
throw(:breakout, opts[:nesting].level) throw(:breakout, opts[:nesting].level)
end end
end end
end end
end

View file

@ -85,7 +85,9 @@ class Pry
def self.reset_defaults def self.reset_defaults
@input = Readline @input = Readline
@output = $stdout @output = $stdout
@commands = Commands
# FIXME
@commands = Pry::Commands
@prompt = DEFAULT_PROMPT @prompt = DEFAULT_PROMPT
@print = DEFAULT_PRINT @print = DEFAULT_PRINT
@hooks = DEFAULT_HOOKS @hooks = DEFAULT_HOOKS

View file

@ -185,10 +185,11 @@ class Pry
pattern, action = commands.commands.find { |k, v| Array(k).any? { |a| a === val } } pattern, action = commands.commands.find { |k, v| Array(k).any? { |a| a === val } }
if pattern if pattern
last_match = Regexp.last_match captures = Regexp.last_match.captures
captures.compact!
options = { options = {
:captures => last_match ? last_match.captures : nil, :captures => captures,
:eval_string => eval_string, :eval_string => eval_string,
:target => target, :target => target,
:val => val, :val => val,
@ -197,7 +198,12 @@ class Pry
:command_info => commands.command_info :command_info => commands.command_info
} }
action.call(options) # because procs are defined in different places (e.g 'help' in CommandBase)
# we cannot simply use `commands.opts=...`
action_self = action.binding.eval('self')
action_self.opts = options
action.call(*captures)
val.clear val.clear
end end
end end

View file

@ -261,12 +261,11 @@ describe Pry do
end end
describe "commands" do describe "commands" do
it 'should set the commands default, and the default should be overridable' do it 'should set the commands default, and the default should be overridable' do
class Command0 < Pry::CommandBase class Command0 < Pry::CommandBase
command "hello" do command "hello" do
describe "" opts[:output].puts "hello world"
action { |opts| opts[:output].puts "hello world"; opts[:val].clear } opts[:val].clear
end end
end end
@ -277,9 +276,9 @@ describe Pry do
str_output.string.should =~ /hello world/ str_output.string.should =~ /hello world/
class Command1 < Pry::CommandBase class Command1 < Pry::CommandBase
command "goodbye" do command "goodbye", "" do
describe "" opts[:output].puts "goodbye world"
action { |opts| opts[:output].puts "goodbye world"; opts[:val].clear } opts[:val].clear
end end
end end
@ -294,9 +293,7 @@ describe Pry do
it 'should inherit "help" command from Pry::CommandBase' do it 'should inherit "help" command from Pry::CommandBase' do
class Command2 < Pry::CommandBase class Command2 < Pry::CommandBase
command "h" do |v| command "h", "h command" do
v.describe "h command"
v.action { }
end end
end end
@ -310,7 +307,6 @@ describe Pry do
it 'should inherit comands from Pry::Commands' do it 'should inherit comands from Pry::Commands' do
class Command3 < Pry::Commands class Command3 < Pry::Commands
command "v" do command "v" do
action {}
end end
end end

View file

@ -19,31 +19,13 @@ end
class CommandTester < Pry::CommandBase class CommandTester < Pry::CommandBase
command "command1" do command "command1", "command 1 test" do
describe "command 1 test" opts[:output].puts "command1"
action { |opts| opts[:output].puts "command1"; opts[:val].clear } opts[:val].clear
end end
command "command2" do command "command2", "command 2 test" do |arg|
describe "command 2 test"
pattern /command2\s*(.*)/
action { |opts|
arg = opts[:captures].first
opts[:output].puts arg opts[:output].puts arg
opts[:val].clear opts[:val].clear
}
end end
# def commands
# @commands ||= {
# "command1" => proc { |opts| opts[:output].puts "command1"; opts[:val].clear },
# /command2\s*(.*)/ => proc do |opts|
# arg = opts[:captures].first
# opts[:output].puts arg
# opts[:val].clear
# end
# }
# end
# e
end end