mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
Version 0.5.4. Added Pry.run_command
* Added Pry.run_command for running Pry commands outside of a session. * Added more graceful error messages when trying to show-method on dynamically defined methods. * Added tests for new Pry.run_command method * Updated README with info on Pry.run_command
This commit is contained in:
parent
adfd39f962
commit
5cda6865d4
5 changed files with 117 additions and 20 deletions
|
@ -221,6 +221,9 @@ it returns the result of the evaluation or an Exception object in
|
|||
case of error. It also takes the same parameters as `Pry#repl()`
|
||||
* Similarly `Pry#r()` only performs the Read section of the REPL, only
|
||||
returning the Ruby expression (as a string). It takes the same parameters as all the others.
|
||||
* `Pry.run_command COMMAND` enables you to invoke Pry commands outside
|
||||
of a session, e.g `Pry.run_command "ls -m", :context => MyObject`. See
|
||||
docs for more info.
|
||||
|
||||
### Session commands
|
||||
|
||||
|
|
|
@ -16,6 +16,12 @@ class Pry
|
|||
meth_name
|
||||
end
|
||||
end
|
||||
|
||||
check_for_dynamically_defined_method = lambda do |file|
|
||||
if file =~ /(\(.*\))|<.*>/
|
||||
raise "Cannot retrieve source for dynamically defined method."
|
||||
end
|
||||
end
|
||||
|
||||
command "!", "Clear the input buffer. Useful if the parsing process goes wrong and you get stuck in the read loop." do
|
||||
output.puts "Input buffer cleared!"
|
||||
|
@ -72,7 +78,7 @@ class Pry
|
|||
|
||||
command "ls", "Show the list of vars in the current scope. Type `ls --help` for more info." do |*args|
|
||||
options = {}
|
||||
|
||||
|
||||
# Set target local to the default -- note that we can set a different target for
|
||||
# ls if we like: e.g ls my_var
|
||||
target = target()
|
||||
|
@ -172,10 +178,10 @@ Shows local and instance variables by default.
|
|||
info["instance variables"] = [Array(target.eval("instance_variables")).sort, i += 1] if options[:i] || options[:a]
|
||||
|
||||
info["class variables"] = [if target_self.is_a?(Module)
|
||||
Array(target.eval("class_variables")).sort
|
||||
else
|
||||
Array(target.eval("self.class.class_variables")).sort
|
||||
end, i += 1] if options[:k] || options[:a]
|
||||
Array(target.eval("class_variables")).sort
|
||||
else
|
||||
Array(target.eval("self.class.class_variables")).sort
|
||||
end, i += 1] if options[:k] || options[:a]
|
||||
|
||||
info["global variables"] = [Array(target.eval("global_variables")).sort, i += 1] if options[:g] || options[:a]
|
||||
|
||||
|
@ -196,9 +202,9 @@ Shows local and instance variables by default.
|
|||
if Module.method(:constants).arity == 0
|
||||
csuper = nil
|
||||
end
|
||||
|
||||
|
||||
info["constants"] = [Array(target_self.is_a?(Module) ? target.eval("constants(#{csuper})") :
|
||||
target.eval("self.class.constants(#{csuper})")).uniq.sort, i += 1] if options[:c] || options[:a]
|
||||
target.eval("self.class.constants(#{csuper})")).uniq.sort, i += 1] if options[:c] || options[:a]
|
||||
|
||||
# verbose output?
|
||||
if options[:v]
|
||||
|
@ -212,9 +218,11 @@ Shows local and instance variables by default.
|
|||
end
|
||||
end
|
||||
|
||||
# plain
|
||||
# plain
|
||||
else
|
||||
output.puts Pry.view(info.values.sort_by { |v| v.last }.map { |v| v.first }.inject(&:+))
|
||||
list = info.values.sort_by { |v| v.last }.map { |v| v.first }.inject(&:+)
|
||||
output.puts Pry.view(list)
|
||||
list
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -264,8 +272,8 @@ e.g: eval-file -c "hello.rb"
|
|||
TOPLEVEL_BINDING.eval(File.read(file_name))
|
||||
output.puts "--\nEval'd '#{file_name}' at top-level."
|
||||
end
|
||||
new_constants = Object.constants - old_constants
|
||||
output.puts "Brought in the following top-level constants: #{new_constants.inspect}" if !new_constants.empty?
|
||||
new_constants = Object.constants - old_constants
|
||||
output.puts "Brought in the following top-level constants: #{new_constants.inspect}" if !new_constants.empty?
|
||||
end
|
||||
|
||||
command "cat", "Show output of VAR.inspect. Aliases: inspect" do |obj|
|
||||
|
@ -329,8 +337,10 @@ e.g show-doc hello_method
|
|||
next
|
||||
end
|
||||
|
||||
doc = meth.comment
|
||||
file, line = meth.source_location
|
||||
check_for_dynamically_defined_method.call(file)
|
||||
doc = meth.comment
|
||||
|
||||
output.puts "--\nFrom #{file} @ line ~#{line}:\n--"
|
||||
output.puts doc
|
||||
end
|
||||
|
@ -378,26 +388,31 @@ e.g: show-method hello_method
|
|||
next
|
||||
end
|
||||
|
||||
code = meth.source
|
||||
file, line = meth.source_location
|
||||
check_for_dynamically_defined_method.call(file)
|
||||
code = meth.source
|
||||
|
||||
output.puts "--\nFrom #{file} @ line #{line}:\n--"
|
||||
output.puts code
|
||||
code
|
||||
end
|
||||
|
||||
command "show-command", "Show sourcecode for a Pry command, e.g: show-command ls" do |command_name|
|
||||
cmds = Pry.active_instance.commands.commands
|
||||
|
||||
command "show-command", "Show sourcecode for a Pry command, e.g: show-command cd" do |command_name|
|
||||
if !command_name
|
||||
output.puts "You must provide a command name."
|
||||
next
|
||||
end
|
||||
|
||||
if cmds[command_name]
|
||||
meth = cmds[command_name][:action]
|
||||
code = meth.source
|
||||
if commands[command_name]
|
||||
meth = commands[command_name][:action]
|
||||
|
||||
file, line = meth.source_location
|
||||
check_for_dynamically_defined_method.call(file)
|
||||
code = meth.source
|
||||
|
||||
output.puts "--\nFrom #{file} @ line #{line}:\n--"
|
||||
output.puts code
|
||||
code
|
||||
else
|
||||
output.puts "No such command: #{command_name}."
|
||||
end
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require 'readline'
|
||||
require 'shellwords'
|
||||
|
||||
# @author John Mair (banisterfiend)
|
||||
class Pry
|
||||
|
@ -94,6 +95,47 @@ class Pry
|
|||
end
|
||||
end
|
||||
|
||||
# Run a Pry command from outside a session. The commands available are
|
||||
# those referenced by `Pry.commands` (the default command set).
|
||||
# Command output is suppresed by default, this is because the return
|
||||
# value (if there is one) is likely to be more useful.
|
||||
# @param [String] arg_string The Pry command (including arguments,
|
||||
# if any).
|
||||
# @param [Hash] options Optional named parameters.
|
||||
# @option options [Object, Binding] :context The object context to run the
|
||||
# command under. Defaults to `TOPLEVEL_BINDING` (main).
|
||||
# @option options [Boolean] :show_output Whether to show command
|
||||
# output. Defaults to false.
|
||||
# @example Run at top-level with no output.
|
||||
# Pry.run_command "ls"
|
||||
# @example Run under Pry class, returning only public methods.
|
||||
# Pry.run_command "ls -m", :context => Pry
|
||||
# @example Display command output.
|
||||
# Pry.run_command "ls -av", :show_output => true
|
||||
def self.run_command(arg_string, options={})
|
||||
name, arg_string = arg_string.split(/\s+/, 2)
|
||||
arg_string = "" if !arg_string
|
||||
|
||||
options = {
|
||||
:context => TOPLEVEL_BINDING,
|
||||
:show_output => false
|
||||
}.merge!(options)
|
||||
|
||||
null_output = Object.new.tap { |v| v.instance_eval { def puts(*) end } }
|
||||
|
||||
commands = Pry.commands.dup
|
||||
commands.output = options[:show_output] ? Pry.output : null_output
|
||||
commands.target = Pry.binding_for(options[:context])
|
||||
|
||||
cmd = commands.commands[name]
|
||||
if cmd
|
||||
action = cmd[:action]
|
||||
commands.instance_exec(*Shellwords.shellwords(arg_string), &action)
|
||||
else
|
||||
raise "No such command: #{name}"
|
||||
end
|
||||
end
|
||||
|
||||
# Set all the configurable options back to their default values
|
||||
def self.reset_defaults
|
||||
@input = Readline
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
class Pry
|
||||
VERSION = "0.5.3"
|
||||
VERSION = "0.5.4"
|
||||
end
|
||||
|
|
37
test/test.rb
37
test/test.rb
|
@ -297,6 +297,43 @@ describe Pry do
|
|||
str_output2.string.should =~ /7/
|
||||
end
|
||||
|
||||
describe "Pry.run_command" do
|
||||
before do
|
||||
class RCTest
|
||||
def a() end
|
||||
B = 20
|
||||
@x = 10
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
Object.remove_const(:RCTest)
|
||||
end
|
||||
|
||||
it "should execute command in the appropriate object context" do
|
||||
result = Pry.run_command "ls", :context => RCTest
|
||||
result.map(&:to_sym).should == [:@x]
|
||||
end
|
||||
|
||||
it "should execute command with parameters in the appropriate object context" do
|
||||
result = Pry.run_command "ls -M", :context => RCTest
|
||||
result.map(&:to_sym).should == [:a]
|
||||
end
|
||||
|
||||
it "should execute command and show output with :show_output => true flag" do
|
||||
str = StringIO.new
|
||||
Pry.output = str
|
||||
result = Pry.run_command "ls -av", :context => RCTest, :show_output => true
|
||||
str.string.should =~ /global variables/
|
||||
Pry.output = $stdout
|
||||
end
|
||||
|
||||
it "should execute command with multiple parameters" do
|
||||
result = Pry.run_command "ls -c -M RCTest"
|
||||
result.map(&:to_sym).should == [:a, :B]
|
||||
end
|
||||
end
|
||||
|
||||
describe "commands" do
|
||||
it 'should set the commands default, and the default should be overridable' do
|
||||
class Command0 < Pry::CommandBase
|
||||
|
|
Loading…
Add table
Reference in a new issue