added import_from, delete, run to command API. Also added examples, added more tests, and changed the way that commands work using split instead of regex captures. Also added output and trget methods to Pry::CommandBase

This commit is contained in:
John Mair 2011-01-21 03:41:41 +13:00
parent ec66e9bade
commit 548b4f82d8
13 changed files with 458 additions and 85 deletions

View File

@ -343,14 +343,19 @@ and executed before a Ruby eval takes place. Pry comes with a default
command set (`Pry::Commands`), but these commands can be augmented or overriden by command set (`Pry::Commands`), but these commands can be augmented or overriden by
user-specified ones. user-specified ones.
The Pry command API is quite sophisticated supporting features such as:
command set inheritance, importing of specific commands from another
command set, deletion of commands, calling of commands within other
commands, and so on.
A valid Pry command object must inherit from A valid Pry command object must inherit from
`Pry::CommandBase` and use the special command API: `Pry::CommandBase` and use the special command API:
#### Example: Defining a command object and setting it globally #### Example: Defining a command object and setting it globally
class MyCommands < Pry::CommandBase class MyCommands < Pry::CommandBase
command "hello", "Output hello to the user." do |name| command greet", "Greet the user." do |name|
opts[:output].puts "hello #{name}!" output.puts "Hello #{name.capitalize}, how are you?"
end end
end end
@ -358,8 +363,8 @@ A valid Pry command object must inherit from
Then inside a pry session: Then inside a pry session:
pry(main)> hello john pry(main)> greet john
hello john! hello John, how are you?
=> nil => nil
#### Example: Using a command object in a specific session #### Example: Using a command object in a specific session
@ -367,7 +372,7 @@ Then inside a pry session:
As in the case of `input` and `output`: As in the case of `input` and `output`:
##### At session start: ##### At session start:
nnnnn
Pry.start(self, :commands => MyCommands) Pry.start(self, :commands => MyCommands)
##### At runtime: ##### At runtime:
@ -377,9 +382,9 @@ nnnnn
#### The command API #### The command API
The command API is defined by the `Pry::CommandBase` class (hence why The command API is defined by the `Pry::CommandBase` class (hence why
all commands must inherit from it). The API works as follows: all commands must inherit from it or a subclass). The API works as follows:
The `command` method defines a new command, its parameter is the * The `command` method defines a new command, its parameter is the
name of the command and an optional second parameter is a description of name of the command and an optional second parameter is a description of
the command. the command.
@ -398,23 +403,64 @@ for the command name - all these strings will be valid names for the
command. command.
command ["ls", "dir"], "show a list of local vars" do command ["ls", "dir"], "show a list of local vars" do
opts[:output].puts opts[:target].eval("local_variables") output.puts target.eval("local_variables")
end end
* The `delete` method deletes a command or a group of a commands; it
can be useful when inheriting from another command set when you decide
to keep only a portion of inherited commands.
#### opts hash class MyCommands < Pry::Commands
delete "show_method", "show_imethod"
end
Note that in the example above we are using `opts[:output]` for output; this is the output * The `import_from` method enables you to specifically select which
object in use by the current pry session. Other hash values accessible commands will be copied across from another command set, useful when
within a `command` block include: you only want a small number of commands and so inheriting and then
deleting would be inefficient. The first parameter to `import_from`
is the class to import from and the other paramters are the names of
the commands to import:
class MyCommands < Pry::CommandBase
import_from Pry::Commands, "ls", "status", "!"
end
* The `run` command invokes one command from within another.
The first parameter is the name of the command to invoke
and the remainder of the parameters will be passed on to the command
being invoked:
class MyCommands < Pry::Commands
command "ls_with_hello" do
output.puts "hello!"
run "ls"
end
end
#### Utility methods for commands
All commands can access the special `output` and `target` methods. The
`output` method returns the `output` object for the active pry session.
Ensuring that your commands invoke `puts` on this rather than using
the top-level `puts` will ensure that all your session output goes to
the same place.
The `target` method returns the `Binding` object the Pry session is currently
active on - useful when your commands need to manipulate or examine
the state of the object. E.g, the "ls" command is implemented as follows
command "ls" do
output.puts target.eval("local_variables + instance_variables").inspect
end
#### The opts hash
These are miscellaneous variables that may be useful to your own commands:
* `opts[:output]` - The session's output object.
* `opts[:val]` - The line of input that invoked the command. * `opts[:val]` - The line of input that invoked the command.
* `opts[:eval_string]` - The cumulative lines of input for multi-line input. * `opts[:eval_string]` - The cumulative lines of input for multi-line input.
* `opts[:target]` - The object the Pry session is currently on.
* `opts[:captures]` - The array of regex captures generated by the command (if any).
* `opts[:nesting]` - Lowlevel session nesting information. * `opts[:nesting]` - Lowlevel session nesting information.
* `opts[:command_info]` - Lowlevel information about all Pry commands. * `opts[:commands]` - Lowlevel data of all Pry commands.
(see commands.rb for examples of how some of these options are used) (see commands.rb for examples of how some of these options are used)
@ -424,7 +470,11 @@ The `Pry::CommandBase` class automatically defines a `help` command
for you. Typing `help` in a Pry session will show a list of commands for you. Typing `help` in a Pry session will show a list of commands
to the user followed by their descriptions. Passing a parameter to to the user followed by their descriptions. Passing a parameter to
`help` with the command name will just return the description of that `help` with the command name will just return the description of that
specific command. specific command. If a description is left out it will automatically
be given the description "No description.".
If the description is explicitly set to `""` then this command will
not be displayed in `help`.
### Hooks ### Hooks

View File

@ -0,0 +1,27 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
# inherit standard command set, but tweak them by deleting some and
# overriding others
class MyCommands < Pry::CommandBase
# Override ls command
command "ls", "An unhelpful ls" do
output.puts "No, i refuse to display any useful information."
end
# Invoke one command from within another using `run`
command "status2" do |x|
output.puts "About to show status, are you ready?"
run "status", x
output.puts "Finished showing status."
end
import_from Pry::Commands, "quit", "show_method", "ls"
end
# Start a Pry session using the commands defined in MyCommands
# Type 'help' in Pry to get a list of the commands and their descriptions
Pry.start(TOPLEVEL_BINDING, :commands => MyCommands)

View File

@ -0,0 +1,36 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
class MathCommands < Pry::CommandBase
command "greet", "Greet a person, e.g: greet john" do |name|
output.puts "Good afternoon #{name.capitalize}! Do you like Math?"
end
command "add", "Add a list of numbers together, e.g: add 1 2 3 4" do |*args|
output.puts "Total: #{args.map(&:to_f).inject(&:+)}"
end
command "multiply", "Multiply a list of numbers together, e.g: multiply 1 2 3 4" do |*args|
output.puts "Total: #{args.map(&:to_f).inject(&:*)}"
end
# Explicitly giving a description of "" to prevent command being
# displayed in 'help'
command "exit", "" do
throw :breakout, 0
end
end
# Since we provide math commands, let's have mathematical
# before_session and after_session hooks, and a mathematical prompt
math_prompt = proc { "math> " }
math_hooks = {
:before_session => proc { |output, *| output.puts "Welcome! Let's do some math! Type 'help' for a list of commands." },
:after_session => proc { |output, *| output.puts "Goodbye!" }
}
# Start a Pry session using the commands defined in MyCommands
# Type 'help' in Pry to get a list of the commands and their descriptions
Pry.start(TOPLEVEL_BINDING, :commands => MathCommands, :prompt => math_prompt, :hooks => math_hooks)

12
examples/example_hooks.rb Normal file
View File

@ -0,0 +1,12 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
my_hooks = {
:before_session => proc { |out, obj| out.puts "Opening #{obj}." },
:after_session => proc { |out, obj| out.puts "Closing #{obj}." }
}
# Start a Pry session using the hooks hash defined in my_hooks
Pry.start(TOPLEVEL_BINDING, :hooks => my_hooks)

View File

@ -0,0 +1,70 @@
# Note: this requires you to have Gosu and TexPlay installed.
# `gem install gosu`
# `gem install texplay`
#
# Extra instructions for installing Gosu on Linux can be found here:
# http://code.google.com/p/gosu/wiki/GettingStartedOnLinux
#
# Instructions for using TexPlay can be found here:
# http://banisterfiend.wordpress.com/2008/08/23/texplay-an-image-manipulation-tool-for-ruby-and-gosu/
#
# Have fun! :)
direc = File.dirname(__FILE__)
require 'rubygems'
require "texplay"
require "#{direc}/../lib/pry"
WIDTH = 640
HEIGHT = 480
IMAGE_PROMPT = [ proc { "(image edit)> " }, proc { "(image edit)* " } ]
class ImageCommands < Pry::CommandBase
command "drawing_methods", "Show a list of TexPlay methods" do
output.puts "#{Pry.view(TexPlay.public_instance_methods)}"
end
command "exit", "Exit the program." do
output.puts "Thanks for dropping by!"
exit
end
import_from Pry::Commands, "ls", "ls_methods", "!"
end
class WinClass < Gosu::Window
def initialize
super(WIDTH, HEIGHT, false)
@img = TexPlay.create_image(self, 200, 200)
@img.rect 0, 0, @img.width - 1, @img.height - 1
@binding = @img.__binding__
@pry_instance = Pry.new(:commands => ImageCommands, :prompt => IMAGE_PROMPT)
end
def draw
@img.draw_rot(WIDTH / 2, HEIGHT / 2, 1, 0, 0.5, 0.5)
end
def update
exit if button_down?(Gosu::KbEscape)
# We do not want a REPL session as the loop prevents the image
# being updated; instead we do a REP session, and let the image
# update each time the user presses enter. We maintain the same
# binding object to keep locals between calls to `Pry#rep()`
@pry_instance.rep(@binding)
end
end
puts "Welcome to ImageEdit; type `help` for a list of commands and `drawing_methods` for a list of drawing methods available."
puts "--"
puts "Example: Try typing 'circle width/2, height/2, 95, :color => :blue, :fill => true'"
puts "If you want to save your image, type: save(\"img.png\")"
WinClass.new.show

10
examples/example_input.rb Normal file
View File

@ -0,0 +1,10 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
# Create a StringIO that contains the input data
str_input = StringIO.new("puts 'hello world!'\nputs \"I am in \#{self}\"\nexit")
# Start a Pry session on the Fixnum 5 using the input data in str_input
Pry.start(5, :input => str_input)

View File

@ -0,0 +1,14 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
# Create a StringIO to contain the output data
str_output = StringIO.new
# Start a Pry session on the Fixnum 5 using str_output to store the
# output (not writing to $stdout)
Pry.start(5, :output => str_output)
# Display all the output accumulated during the session
puts str_output.string

View File

@ -0,0 +1,9 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
my_print = proc { |out, value| out.puts "Output is: #{value.inspect}" }
# Start a Pry session using the print object defined in my_print
Pry.start(TOPLEVEL_BINDING, :print => my_print)

View File

@ -0,0 +1,12 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
# Remember, first prompt in array is the main prompt, second is the wait
# prompt (used for multiline input when more input is required)
my_prompt = [ proc { |obj, *| "inside #{obj}> " },
proc { |obj, *| "inside #{obj}* "} ]
# Start a Pry session using the prompt defined in my_prompt
Pry.start(TOPLEVEL_BINDING, :prompt => my_prompt)

View File

@ -6,7 +6,7 @@ class Pry
class << self class << self
attr_accessor :commands attr_accessor :commands
attr_accessor :command_info attr_accessor :command_info
attr_accessor :opts attr_accessor :opts, :output, :target
# private because we want to force function style invocation. We require # private because we want to force function style invocation. We require
# that the location where the block is defined has the `opts` # that the location where the block is defined has the `opts`
@ -14,7 +14,7 @@ class Pry
private private
# 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] names The name of the command (or array of
# command name aliases). # command name aliases).
# @param [String] description A description of the command. # @param [String] description A description of the command.
# @yield The action to perform. The parameters in the block # @yield The action to perform. The parameters in the block
@ -34,42 +34,73 @@ class Pry
# # Good afternoon John! # # Good afternoon John!
# # pry(main)> help greet # # pry(main)> help greet
# # Greet somebody # # Greet somebody
def command(name, description="No description.", &block) def command(names, description="No description.", &block)
@commands ||= {} @commands ||= {}
@command_info ||= {}
arg_match = '(?:\s+(\S+))?' * 20 Array(names).each do |name|
if name.is_a?(Array) commands[name] = { :description => description, :action => block }
name.each do |n|
matcher = /^#{n}(?!\S)#{arg_match}?/
commands[matcher] = block
command_info[n] = description
end
else
matcher = /^#{name}(?!\S)#{arg_match}?/
commands[matcher] = block
command_info[name] = description
end 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)
action = opts[:commands][name][:action]
instance_exec(*args, &action)
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 end
end end
command "help", "This menu." do |cmd| command "help", "This menu." do |cmd|
out = opts[:output] command_info = opts[:commands]
command_info = opts[:command_info]
param = cmd param = cmd
if !param if !param
out.puts "Command list:" output.puts "Command list:"
out.puts "--" output.puts "--"
command_info.each do |k, v| command_info.each do |k, data|
out.puts "#{k}".ljust(18) + v output.puts "#{k}".ljust(18) + data[:description] if !data[:description].empty?
end end
else else
key = command_info.keys.find { |v| Array(v).any? { |k| k === param } } if command_info[param]
if key output.puts command_info[param][:description]
out.puts command_info[key]
else else
out.puts "No info for command: #{param}" output.puts "No info for command: #{param}"
end end
end end
end end
@ -77,7 +108,7 @@ class Pry
# Ensures that commands can be inherited # Ensures that commands can be inherited
def self.inherited(klass) def self.inherited(klass)
klass.commands = commands.dup klass.commands = commands.dup
klass.command_info = command_info.dup
end end
end end
end end

View File

@ -7,12 +7,12 @@ class Pry
class Commands < CommandBase class Commands < CommandBase
command "!", "Refresh the REPL" do command "!", "Refresh the REPL" do
opts[:output].puts "Refreshed REPL" output.puts "Refreshed REPL"
opts[:eval_string].clear opts[:eval_string].clear
end end
command "!pry", "Start a Pry session on current self; this even works mid-expression." do command "!pry", "Start a Pry session on current self; this even works mid-expression." do
Pry.start(opts[:target]) Pry.start(target)
end end
command ["exit_program", "quit_program"], "End the current program." do command ["exit_program", "quit_program"], "End the current program." do
@ -20,7 +20,7 @@ class Pry
end end
command "nesting", "Show nesting information." do command "nesting", "Show nesting information." do
out = opts[:output] out = output
nesting = opts[:nesting] nesting = opts[:nesting]
out.puts "Nesting status:" out.puts "Nesting status:"
@ -35,9 +35,8 @@ class Pry
end end
command "status", "Show status information." do command "status", "Show status information." do
out = opts[:output] out = output
nesting = opts[:nesting] nesting = opts[:nesting]
target = opts[:target]
out.puts "Status:" out.puts "Status:"
out.puts "--" out.puts "--"
@ -53,37 +52,37 @@ class Pry
end end
command "ls", "Show the list of vars in the current scope." do command "ls", "Show the list of vars in the current scope." do
opts[:output].puts "#{Pry.view(opts[:target].eval('local_variables + instance_variables'))}" output.puts "#{Pry.view(target.eval('local_variables + instance_variables'))}"
end end
command "cat", "Show output of <var>.inspect." do |obj| command "cat", "Show output of <var>.inspect." do |obj|
out = opts[:output] out = output
out.puts opts[:target].eval("#{obj}.inspect") out.puts target.eval("#{obj}.inspect")
end end
command "cd", "Start a Pry session on <var> (use `cd ..` to go back)" do |obj| command "cd", "Start a Pry session on <var> (use `cd ..` to go back)" do |obj|
throw(:breakout, opts[:nesting].level) if obj == ".." throw(:breakout, opts[:nesting].level) if obj == ".."
opts[:target].eval("#{obj}.pry") target.eval("#{obj}.pry")
end end
command "show_doc", "Show the comments above <methname>" do |meth_name| command "show_doc", "Show the comments above <methname>" do |meth_name|
doc = opts[:target].eval("method(:#{meth_name})").comment doc = target.eval("method(:#{meth_name})").comment
opts[:output].puts doc output.puts doc
end end
command "show_idoc", "Show the comments above instance method <methname>" do |meth_name| command "show_idoc", "Show the comments above instance method <methname>" do |meth_name|
doc = opts[:target].eval("instance_method(:#{meth_name})").comment doc = target.eval("instance_method(:#{meth_name})").comment
opts[:output].puts doc output.puts doc
end end
command "show_method", "Show sourcecode for method <methname>." do |meth_name| command "show_method", "Show sourcecode for method <methname>." do |meth_name|
doc = opts[:target].eval("method(:#{meth_name})").source doc = target.eval("method(:#{meth_name})").source
opts[:output].puts doc output.puts doc
end end
command "show_imethod", "Show sourcecode for instance method <methname>." do |meth_name| command "show_imethod", "Show sourcecode for instance method <methname>." do |meth_name|
doc = opts[:target].eval("instance_method(:#{meth_name})").source doc = target.eval("instance_method(:#{meth_name})").source
opts[:output].puts doc output.puts doc
end end
command "jump_to", "Jump to a Pry session further up the stack, exiting all sessions below." do |break_level| command "jump_to", "Jump to a Pry session further up the stack, exiting all sessions below." do |break_level|
@ -92,21 +91,21 @@ class Pry
case break_level case break_level
when nesting.level when nesting.level
opts[:output].puts "Already at nesting level #{nesting.level}" output.puts "Already at nesting level #{nesting.level}"
when (0...nesting.level) when (0...nesting.level)
throw(:breakout, break_level + 1) throw(:breakout, break_level + 1)
else else
max_nest_level = nesting.level - 1 max_nest_level = nesting.level - 1
opts[:output].puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}." output.puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}."
end end
end end
command "ls_methods", "List all methods defined on class of receiver." do command "ls_methods", "List all methods defined on class of receiver." do
opts[:output].puts "#{Pry.view(opts[:target].eval('public_methods(false) + private_methods(false) + protected_methods(false)'))}" output.puts "#{Pry.view(target.eval('public_methods(false) + private_methods(false) + protected_methods(false)'))}"
end end
command "ls_imethods", "List all instance methods defined on class of receiver." do command "ls_imethods", "List all instance methods defined on class of receiver." do
opts[:output].puts "#{Pry.view(opts[:target].eval('public_instance_methods(false) + private_instance_methods(false) + protected_instance_methods(false)'))}" output.puts "#{Pry.view(target.eval('public_instance_methods(false) + private_instance_methods(false) + protected_instance_methods(false)'))}"
end end
command ["exit", "quit", "back"], "End the current Pry session." do command ["exit", "quit", "back"], "End the current Pry session." do

View File

@ -125,7 +125,7 @@ class Pry
target = binding_for(target) target = binding_for(target)
if input == Readline if input == Readline
Readline.completion_proc = Pry::InputCompleter.build_completion_proc(target, Pry.commands.command_info.keys.flatten) Readline.completion_proc = Pry::InputCompleter.build_completion_proc(target, commands.commands.keys)
end end
# eval the expression and save to last_result # eval the expression and save to last_result
@ -182,28 +182,29 @@ class Pry
def val.clear() replace("") end def val.clear() replace("") end
def eval_string.clear() replace("") end def eval_string.clear() replace("") end
pattern, action = commands.commands.find { |k, v| k === val } pattern, data = commands.commands.find do |name, data|
/^#{name}(?!\S)(?:\s+(.+))?/ =~ val
end
if pattern if pattern
captures = Regexp.last_match.captures args_string = $1
captures.compact! args = args_string ? args_string.split : []
action = data[:action]
options = { options = {
:captures => captures, :captures => args_string,
:eval_string => eval_string, :eval_string => eval_string,
:target => target, :target => target,
:val => val, :val => val,
:nesting => nesting, :nesting => nesting,
:output => output, :output => output,
:command_info => commands.command_info :commands => commands.commands
} }
# because procs are defined in different places (e.g 'help' in CommandBase) # set some useful methods to be used by the action blocks
# we cannot simply use `commands.opts=...`; instead we have to commands.opts = options
# retrieve the object where the block was defined; since that is commands.target = target
# where the `opts` method the block will have access to is defined. commands.output = output
action_self = action.binding.eval('self')
action_self.opts = options
# send the correct number of parameters to the block (to avoid # send the correct number of parameters to the block (to avoid
# warnings in 1.8.7) # warnings in 1.8.7)
@ -212,14 +213,19 @@ class Pry
# if arity is negative then we have a *args in 1.8.7. # if arity is negative then we have a *args in 1.8.7.
# In 1.9 we have default values or *args # In 1.9 we have default values or *args
action.call(*captures) # Use instance_exec() to make the opts, target, output, etc methods available
commands.instance_exec(*args, &action)
when 1, 0 when 1, 0
# ensure that we get the right number of parameters; # ensure that we get the right number of parameters;
# using values_at we pad out missing parameters with nils so # using values_at we pad out missing parameters with nils so
# that 1.8.7 doesn't complain about incorrect arity (1.9.2 # that 1.8.7 doesn't complain about incorrect arity (1.9.2
# doesn't care) # doesn't care)
action.call(*captures.values_at(*0..(action.arity - 1))) args_with_corrected_arity = args.values_at *0..(action.arity - 1)
# Use instance_exec() to make the opts, target, output, etc methods
# available
commands.instance_exec(*args_with_corrected_arity, &action)
end end
val.clear val.clear

View File

@ -298,25 +298,122 @@ describe Pry do
end end
Command2.commands.keys.size.should == 2 Command2.commands.keys.size.should == 2
Command2.command_info.keys.include?("help").should == true Command2.commands.keys.include?("help").should == true
Command2.command_info.keys.include?("h").should == true Command2.commands.keys.include?("h").should == true
Object.remove_const(:Command2) Object.remove_const(:Command2)
end end
it 'should inherit comands from Pry::Commands' do it 'should inherit commands from Pry::Commands' do
class Command3 < Pry::Commands class Command3 < Pry::Commands
command "v" do command "v" do
end end
end end
Command3.command_info.include?("nesting").should == true Command3.commands.include?("nesting").should == true
Command3.command_info.include?("jump_to").should == true Command3.commands.include?("jump_to").should == true
Command3.command_info.include?("cd").should == true Command3.commands.include?("cd").should == true
Command3.command_info.include?("v").should == true Command3.commands.include?("v").should == true
Object.remove_const(:Command3) Object.remove_const(:Command3)
end end
it 'should run a command from within a command' do
class Command3 < Pry::Commands
command "v" do
output.puts "v command"
end
command "run_v" do
run "v"
end
end
str_output = StringIO.new
Pry.new(:input => InputTester.new("run_v"), :output => str_output, :commands => Command3).rep
str_output.string.should =~ /v command/
Object.remove_const(:Command3)
end
it 'should enable an inherited method to access opts and output and target, due to instance_exec' do
class Command3 < Pry::Commands
command "v" do
output.puts "#{target.eval('self')}"
end
end
class Command4 < Command3
end
str_output = StringIO.new
Pry.new(:print => proc {}, :input => InputTester.new("v"),
:output => str_output, :commands => Command4).rep("john")
str_output.string.chomp.should == "john"
Object.remove_const(:Command3)
Object.remove_const(:Command4)
end
it 'should import commands from another command object' do
class Command3 < Pry::CommandBase
import_from Pry::Commands, "status", "jump_to"
end
str_output = StringIO.new
Pry.new(:print => proc {}, :input => InputTester.new("status"),
:output => str_output, :commands => Command3).rep("john")
str_output.string.should =~ /Status:/
Object.remove_const(:Command3)
end
it 'should delete some inherited commands when using delete method' do
class Command3 < Pry::Commands
command "v" do
end
delete "show_doc", "show_method"
delete "ls"
end
Command3.commands.include?("nesting").should == true
Command3.commands.include?("jump_to").should == true
Command3.commands.include?("cd").should == true
Command3.commands.include?("v").should == true
Command3.commands.include?("show_doc").should == false
Command3.commands.include?("show_method").should == false
Command3.commands.include?("ls").should == false
Object.remove_const(:Command3)
end
it 'should override some inherited commands' do
class Command3 < Pry::Commands
command "jump_to" do
output.puts "jump_to the music"
end
command "help" do
output.puts "help to the music"
end
end
# suppress evaluation output
Pry.print = proc {}
str_output = StringIO.new
Pry.new(:input => InputTester.new("jump_to"), :output => str_output, :commands => Command3).rep
str_output.string.chomp.should == "jump_to the music"
str_output = StringIO.new
Pry.new(:input => InputTester.new("help"), :output => str_output, :commands => Command3).rep
str_output.string.chomp.should == "help to the music"
Object.remove_const(:Command3)
Pry.reset_defaults
end
end end
it "should set the print default, and the default should be overridable" do it "should set the print default, and the default should be overridable" do