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

Merge branch 'master' of github.com:banister/pry

This commit is contained in:
Rob Gleeson 2011-06-05 23:48:34 +01:00
commit 528a55bda0
27 changed files with 601 additions and 434 deletions

23
bin/pry
View file

@ -20,8 +20,24 @@ See: `https://github.com/banister` for more information.
}
on :e, :exec, "A line of code to execute in context before the session starts", true
on :f, "Suppress loading of ~/.pryrc"
on "no-color", "Disable syntax highlighting for session"
on "no-pager", "Disable pager for long output" do
Pry.pager = false
end
on "no-color", "Disable syntax highlighting for session" do
Pry.color = false
end
on :f, "Suppress loading of ~/.pryrc" do
# load ~/.pryrc, if not suppressed with -f option
Pry.config.should_load_rc = false
end
on "no-plugins", "Suppress loading of plugins." do
# suppress plugins if given --no-plugins optino
Pry.config.plugins.enabled = false
end
on "simple-prompt", "Enable simple prompt mode" do
Pry.prompt = Pry::SIMPLE_PROMPT
@ -50,9 +66,6 @@ end
# invoked via cli
Pry.cli = true
# load ~/.pryrc, if not suppressed with -f option
Pry.config.should_load_rc = !opts.f?
# create the actual context
context = Pry.binding_for(eval(opts[:context]))

View file

@ -1,7 +1,4 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
# define a local.
a = "a local variable"
@ -14,4 +11,5 @@ end
# Start pry session at top-level.
# The local variable `a` and the `hello` method will
# be accessible.
puts __LINE__
binding.pry

View file

@ -1,7 +1,4 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
# Inherit standard command set, but tweak them by importing some and
# overriding others.
@ -18,7 +15,7 @@ class MyCommands < Pry::CommandBase
# analogy to Ruby's native alias_method idiom for decorating a method
alias_command "old_status", "status", ""
# Invoke one command from within another using `run`
command "status", "Modified status." do |x|
output.puts "About to show status, are you ready?"

View file

@ -1,7 +1,4 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
class MathCommands < Pry::CommandBase
command "greet", "Greet a person, e.g: greet john" do |name|

View file

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

View file

@ -1,7 +1,7 @@
# 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
#
@ -10,11 +10,7 @@
#
# Have fun! :)
direc = File.dirname(__FILE__)
require 'rubygems'
require "texplay"
require "#{direc}/../lib/pry"
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
WIDTH = 640
HEIGHT = 480
@ -42,12 +38,12 @@ class WinClass < Gosu::Window
@img.rect 0, 0, @img.width - 1, @img.height - 1
@binding = Pry.binding_for(@img)
@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)
@img.draw_rot(WIDTH / 2, HEIGHT / 2, 1, 0, 0.5, 0.5)
end
def update

View file

@ -1,7 +1,4 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
# Create a StringIO that contains the input data
str_input = StringIO.new("puts 'hello world!'\nputs \"I am in \#{self}\"\nexit")

View file

@ -1,7 +1,4 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
# Create a StringIO that contains the input data for all the Pry objects
cmds = <<-CMDS

View file

@ -1,7 +1,4 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
# Create a StringIO to contain the output data
str_output = StringIO.new

View file

@ -1,9 +1,6 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
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

@ -1,12 +1,9 @@
direc = File.dirname(__FILE__)
require 'rubygems'
require "#{direc}/../lib/pry"
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
# 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)

6
examples/helper.rb Normal file
View file

@ -0,0 +1,6 @@
require 'rubygems'
unless Object.const_defined? 'Pry'
$:.unshift File.expand_path '../../lib', __FILE__
require 'pry'
end

View file

@ -63,13 +63,19 @@ class Pry
# multi-line input.
# @param [Binding] target The receiver of the commands.
def process_commands(val, eval_string, target)
command, captures, pos = command_matched(val)
# no command was matched, so return to caller
return if !command
val.replace interpolate_string(val, target) if command.options[:interpolate]
return if !valid_command?(val)
command, captures, pos = command_matched(val)
arg_string = val[pos..-1].strip
# perform ruby interpolation for commands
if command.options[:interpolate]
val.replace interpolate_string(val, target)
arg_string.replace interpolate_string(arg_string, target)
captures = captures.map { |v| interpolate_string(v, target) if v }
end
args = arg_string ? Shellwords.shellwords(arg_string) : []
options = {

View file

@ -81,6 +81,13 @@ class Pry
# saved to hist.file at session end.
# @return [OpenStruct]
attr_accessor :history
# Config option for plugins:
# sub-options include:
# `plugins.enabled` (Boolean) to toggle the loading of plugins on and off wholesale. (defaults to true)
# `plugins.strict_loading` (Boolean) which toggles whether referring to a non-existent plugin should raise an exception (defaults to `false`)
# @return [OpenStruct]
attr_accessor :plugins
end
end

View file

@ -109,8 +109,8 @@ class Pry
opt.on :M, "instance-methods", "Operate on instance methods."
opt.on :m, :methods, "Operate on methods."
opt.on "no-reload", "Do not automatically reload the method's file after editting."
opt.on :n, "no-jump", "Do not fast forward editor to first line of method."
opt.on :n, "no-reload", "Do not automatically reload the method's file after editting."
opt.on "no-jump", "Do not fast forward editor to first line of method."
opt.on :c, :context, "Select object context to run under.", true do |context|
target = Pry.binding_for(target.eval(context))
end
@ -136,25 +136,24 @@ class Pry
# editor is invoked here
else
file, line = meth.source_location
file, line = path_line_for(meth)
set_file_and_dir_locals(file)
if Pry.editor.respond_to?(:call)
editor_invocation = Pry.editor.call(file, line)
else
# only use start line if -n option is not used
start_line_syntax = opts.n? ? "" : start_line_for_editor(line)
start_line_syntax = opts["no-jump"] ? "" : start_line_for_editor(line)
editor_invocation = "#{Pry.editor} #{start_line_syntax} #{file}"
end
run ".#{editor_invocation}"
silence_warnings do
load file if !opts["no-reload"]
load file if !opts.n?
end
end
end
helpers do
def start_line_for_editor(line_number)

View file

@ -5,8 +5,9 @@ class Pry
command(/\.(.*)/, "All text following a '.' is forwarded to the shell.", :listing => ".<shell command>") do |cmd|
if cmd =~ /^cd\s+(.+)/i
dest = $1
begin
Dir.chdir File.expand_path($1)
Dir.chdir File.expand_path(dest)
rescue Errno::ENOENT
output.puts "No such directory: #{dest}"
end
@ -72,8 +73,6 @@ class Pry
render_output(opts.flood?, opts.l? ? normalized_start_line + 1 : false, contents)
contents
end
end
end

View file

@ -5,15 +5,6 @@ class Pry
module_function
def try_to_load_pry_doc
# YARD crashes on rbx, so do not require it
if !Object.const_defined?(:RUBY_ENGINE) || RUBY_ENGINE !~ /rbx/
require "pry-doc"
end
rescue LoadError
end
def meth_name_from_binding(b)
meth_name = b.eval('__method__')
if [:__script__, nil, :__binding__, :__binding_impl__].include?(meth_name)
@ -24,15 +15,15 @@ class Pry
end
# if start_line is not false then add line numbers starting with start_line
def render_output(should_flood, start_line, doc)
def render_output(should_flood, start_line, text)
if start_line
doc = Pry::Helpers::Text.with_line_numbers doc, start_line
text = Pry::Helpers::Text.with_line_numbers text, start_line
end
if should_flood
output.puts doc
output.puts text
else
stagger_output(doc)
stagger_output(text)
end
end
@ -48,6 +39,68 @@ class Pry
end
end
########### RBX HELPERS #############
def rbx_core?(meth)
defined?(RUBY_ENGINE) &&
RUBY_ENGINE =~ /rbx/ &&
meth.source_location &&
meth.source_location.first.start_with?("kernel")
end
def rvm_ruby?(path)
!!(path =~ /\.rvm/)
end
def rbx_core_code_for(meth)
rbx_core_code_or_doc_for(meth, :code)
end
def rbx_core_doc_for(meth)
rbx_core_code_or_doc_for(meth, :doc)
end
def rbx_core_code_or_doc_for(meth, code_or_doc)
path_line = rbx_core_path_line_for(meth)
case code_or_doc
when :code
MethodSource.source_helper(path_line)
when :doc
MethodSource.comment_helper(path_line)
end
end
def rbx_core_path_line_for(meth)
if rvm_ruby?(Rubinius::BIN_PATH)
rvm_rbx_core_path_line_for(meth)
else
std_rbx_core_path_line_for(meth)
end
end
def std_rbx_core_path_line_for(meth)
file_name = File.join(Rubinius::BIN_PATH, "..", meth.source_location.first)
raise "Cannot find rbx core source" if !File.exists?(file_name)
start_line = meth.source_location.last
[file_name, start_line]
end
def rvm_rbx_core_path_line_for(meth)
ruby_name = File.dirname(Rubinius::BIN_PATH).split("/").last
source_path = File.join(File.dirname(File.dirname(File.dirname(Rubinius::BIN_PATH))), "src", ruby_name)
file_name = File.join(source_path, meth.source_location.first)
raise "Cannot find rbx core source" if !File.exists?(file_name)
start_line = meth.source_location.last
[file_name, start_line]
end
######### END RBX HELPERS ###############
def code_and_code_type_for(meth)
case code_type = code_type_for(meth)
when nil
@ -57,14 +110,17 @@ class Pry
code = strip_comments_from_c_code(code)
when :ruby
if meth.source_location.first == Pry.eval_path
start_line = meth.source_location.last
p = Pry.new(:input => StringIO.new(Pry.line_buffer[start_line..-1].join)).r(target)
code = strip_leading_whitespace(p)
else
code = strip_leading_whitespace(meth.source)
if rbx_core?(meth)
code = strip_leading_whitespace(rbx_core_code_for(meth))
else
code = strip_leading_whitespace(meth.source)
end
end
set_file_and_dir_locals(meth.source_location.first)
set_file_and_dir_locals(path_line_for(meth).first)
end
[code, code_type]
@ -77,9 +133,12 @@ class Pry
when :c
doc = Pry::MethodInfo.info_for(meth).docstring
when :ruby
doc = meth.comment
doc = strip_leading_hash_and_whitespace_from_ruby_comments(doc)
set_file_and_dir_locals(meth.source_location.first)
if rbx_core?(meth)
doc = strip_leading_hash_and_whitespace_from_ruby_comments(rbx_core_doc_for(meth))
else
doc = strip_leading_hash_and_whitespace_from_ruby_comments(meth.comment)
end
set_file_and_dir_locals(path_line_for(meth).first)
end
[doc, code_type]
@ -119,11 +178,19 @@ class Pry
end
end
def path_line_for(meth)
if rbx_core?(meth)
rbx_core_path_line_for(meth)
else
meth.source_location
end
end
def make_header(meth, code_type, content)
num_lines = "Number of lines: #{Pry::Helpers::Text.bold(content.each_line.count.to_s)}"
case code_type
when :ruby
file, line = meth.source_location
file, line = path_line_for(meth)
"\n#{Pry::Helpers::Text.bold('From:')} #{file} @ line #{line}:\n#{num_lines}\n\n"
else
file = Pry::MethodInfo.info_for(meth).file

View file

@ -1,10 +1,10 @@
class Pry
class PluginManager
PRY_PLUGIN_PREFIX = /^pry-/
PluginNotFound = Class.new(LoadError)
MessageSink = Object.new.tap { |o| def o.method_missing(*args) end }
class Plugin
attr_accessor :name, :gem_name, :enabled, :active
@ -55,7 +55,7 @@ class Pry
# @return [Hash] A hash with all plugin names (minus the 'pry-') as
# keys and Plugin objects as values.
def plugins
h = {}
h = Pry.config.plugins.strict_loading ? {} : Hash.new { MessageSink }
@plugins.each do |plugin|
h[plugin.name] = plugin
end

View file

@ -96,7 +96,7 @@ class Pry
# we only want them loaded once per entire Pry lifetime, not
# multiple times per each new session (i.e in debugging)
load_rc if Pry.config.should_load_rc
load_plugins if Pry.config.should_load_plugins
load_plugins if Pry.config.plugins.enabled
load_history if Pry.config.history.load
@initial_session = false
@ -190,7 +190,10 @@ class Pry
config.pager = true
config.editor = default_editor_for_platform
config.should_load_rc = true
config.should_load_plugins = true
config.plugins ||= OpenStruct.new
config.plugins.enabled = true
config.plugins.strict_loading = true
config.history ||= OpenStruct.new
config.history.save = true

View file

@ -1,3 +1,3 @@
class Pry
VERSION = "0.9.0pre1"
VERSION = "0.9.0pre2"
end

View file

@ -19,7 +19,7 @@ class << Pry
Pry.color = false
Pry.pager = false
Pry.config.should_load_rc = false
Pry.config.should_load_plugins = false
Pry.config.plugins.enabled = false
Pry.config.history.load = false
Pry.config.history.save = false
end

View file

@ -1,347 +1,6 @@
require 'helper'
describe "Pry::Commands" do
after do
$obj = nil
end
describe "hist" do
push_first_hist_line = lambda do |hist, line|
hist.push line
end
before do
Readline::HISTORY.shift until Readline::HISTORY.empty?
@hist = Readline::HISTORY
end
it 'should display the correct history' do
push_first_hist_line.call(@hist, "'bug in 1.8 means this line is ignored'")
@hist.push "hello"
@hist.push "world"
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /hello\n.*world/
end
it 'should replay history correctly (single item)' do
push_first_hist_line.call(@hist, ":hello")
@hist.push ":blah"
@hist.push ":bucket"
@hist.push ":ostrich"
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --replay -1", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /ostrich/
end
it 'should replay a range of history correctly (range of items)' do
push_first_hist_line.call(@hist, "'bug in 1.8 means this line is ignored'")
@hist.push ":hello"
@hist.push ":carl"
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --replay 0..2", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /:hello\n.*:carl/
end
it 'should grep for correct lines in history' do
push_first_hist_line.call(@hist, "apple")
@hist.push "abby"
@hist.push "box"
@hist.push "button"
@hist.push "pepper"
@hist.push "orange"
@hist.push "grape"
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --grep o", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /\d:.*?box\n\d:.*?button\n\d:.*?orange/
end
it 'should return last N lines in history with --tail switch' do
push_first_hist_line.call(@hist, "0")
("a".."z").each do |v|
@hist.push v
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --tail 3", "exit-all"), str_output) do
pry
end
str_output.string.each_line.count.should == 3
str_output.string.should =~ /x\n\d+:.*y\n\d+:.*z/
end
# strangeness in this test is due to bug in Readline::HISTORY not
# always registering first line of input
it 'should return first N lines in history with --head switch' do
push_first_hist_line.call(@hist, "0")
("a".."z").each do |v|
@hist.push v
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --head 4", "exit-all"), str_output) do
pry
end
str_output.string.each_line.count.should == 4
str_output.string.should =~ /a\n\d+:.*b\n\d+:.*c/
end
# strangeness in this test is due to bug in Readline::HISTORY not
# always registering first line of input
it 'should show lines between lines A and B with the --show switch' do
push_first_hist_line.call(@hist, "0")
("a".."z").each do |v|
@hist.push v
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --show 1..4", "exit-all"), str_output) do
pry
end
str_output.string.each_line.count.should == 4
str_output.string.should =~ /b\n\d+:.*c\n\d+:.*d/
end
end
describe "show-method" do
it 'should output a method\'s source' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-method sample_method", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /def sample/
end
it 'should output a method\'s source with line numbers' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-method -l sample_method", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /\d+: def sample/
end
it 'should output a method\'s source if inside method without needing to use method name' do
$str_output = StringIO.new
o = Object.new
def o.sample
redirect_pry_io(InputTester.new("show-method", "exit-all"), $str_output) do
binding.pry
end
end
o.sample
$str_output.string.should =~ /def o.sample/
$str_output = nil
end
it 'should output a method\'s source if inside method without needing to use method name, and using the -l switch' do
$str_output = StringIO.new
o = Object.new
def o.sample
redirect_pry_io(InputTester.new("show-method -l", "exit-all"), $str_output) do
binding.pry
end
end
o.sample
$str_output.string.should =~ /\d+: def o.sample/
$str_output = nil
end
# dynamically defined method source retrieval is only supported in
# 1.9 - where Method#source_location is native
if RUBY_VERSION =~ /1.9/
it 'should output a method\'s source for a method defined inside pry' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("def dyna_method", ":testing", "end", "show-method dyna_method"), str_output) do
TOPLEVEL_BINDING.pry
end
str_output.string.should =~ /def dyna_method/
Object.remove_method :dyna_method
end
it 'should output a method\'s source for a method defined inside pry, even if exceptions raised before hand' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("bad code", "123", "bad code 2", "1 + 2", "def dyna_method", ":testing", "end", "show-method dyna_method"), str_output) do
TOPLEVEL_BINDING.pry
end
str_output.string.should =~ /def dyna_method/
Object.remove_method :dyna_method
end
it 'should output an instance method\'s source for a method defined inside pry' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("class A", "def yo", "end", "end", "show-method A#yo"), str_output) do
TOPLEVEL_BINDING.pry
end
str_output.string.should =~ /def yo/
Object.remove_const :A
end
it 'should output an instance method\'s source for a method defined inside pry using define_method' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("class A", "define_method(:yup) {}", "end", "end", "show-method A#yup"), str_output) do
TOPLEVEL_BINDING.pry
end
str_output.string.should =~ /define_method\(:yup\)/
Object.remove_const :A
end
end
end
describe "show-doc" do
it 'should output a method\'s documentation' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-doc sample_method", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /sample doc/
end
it 'should output a method\'s documentation if inside method without needing to use method name' do
$str_output = StringIO.new
o = Object.new
def o.sample
redirect_pry_io(InputTester.new("show-doc", "exit-all"), $str_output) do
binding.pry
end
end
o.sample
$str_output.string.should =~ /sample doc/
$str_output = nil
end
end
describe "cd" do
it 'should cd into simple input' do
b = Pry.binding_for(Object.new)
b.eval("x = :mon_ouie")
redirect_pry_io(InputTester.new("cd x", "$obj = self", "exit-all"), StringIO.new) do
b.pry
end
$obj.should == :mon_ouie
end
it 'should break out of session with cd ..' do
b = Pry.binding_for(:outer)
b.eval("x = :inner")
redirect_pry_io(InputTester.new("cd x", "$inner = self;", "cd ..", "$outer = self", "exit-all"), StringIO.new) do
b.pry
end
$inner.should == :inner
$outer.should == :outer
end
it 'should break out to outer-most session with cd /' do
b = Pry.binding_for(:outer)
b.eval("x = :inner")
redirect_pry_io(InputTester.new("cd x", "$inner = self;", "cd 5", "$five = self", "cd /", "$outer = self", "exit-all"), StringIO.new) do
b.pry
end
$inner.should == :inner
$five.should == 5
$outer.should == :outer
end
it 'should start a session on TOPLEVEL_BINDING with cd ::' do
b = Pry.binding_for(:outer)
redirect_pry_io(InputTester.new("cd ::", "$obj = self", "exit-all"), StringIO.new) do
5.pry
end
$obj.should == TOPLEVEL_BINDING.eval('self')
end
it 'should cd into complex input (with spaces)' do
o = Object.new
def o.hello(x, y, z)
:mon_ouie
end
redirect_pry_io(InputTester.new("cd hello 1, 2, 3", "$obj = self", "exit-all"), StringIO.new) do
o.pry
end
$obj.should == :mon_ouie
end
end
# show-command only works in implementations that support Proc#source_location
if Proc.method_defined?(:source_location)
describe "show-command" do
it 'should show source for an ordinary command' do
set = Pry::CommandSet.new do
import_from Pry::Commands, "show-command"
command "foo" do
:body_of_foo
end
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-command foo"), str_output) do
Pry.new(:commands => set).rep
end
str_output.string.should =~ /:body_of_foo/
end
it 'should show source for a command with spaces in its name' do
set = Pry::CommandSet.new do
import_from Pry::Commands, "show-command"
command "foo bar" do
:body_of_foo_bar
end
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-command \"foo bar\""), str_output) do
Pry.new(:commands => set).rep
end
str_output.string.should =~ /:body_of_foo_bar/
end
it 'should show source for a command by listing name' do
set = Pry::CommandSet.new do
import_from Pry::Commands, "show-command"
command /foo(.*)/, "", :listing => "bar" do
:body_of_foo_regex
end
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-command bar"), str_output) do
Pry.new(:commands => set).rep
end
str_output.string.should =~ /:body_of_foo_regex/
end
end
end
describe "help" do
it 'should display help for a specific command' do
str_output = StringIO.new

View file

@ -0,0 +1,64 @@
require 'helper'
describe "Pry::DefaultCommands::Context" do
describe "cd" do
after do
$obj = nil
end
it 'should cd into simple input' do
b = Pry.binding_for(Object.new)
b.eval("x = :mon_ouie")
redirect_pry_io(InputTester.new("cd x", "$obj = self", "exit-all"), StringIO.new) do
b.pry
end
$obj.should == :mon_ouie
end
it 'should break out of session with cd ..' do
b = Pry.binding_for(:outer)
b.eval("x = :inner")
redirect_pry_io(InputTester.new("cd x", "$inner = self;", "cd ..", "$outer = self", "exit-all"), StringIO.new) do
b.pry
end
$inner.should == :inner
$outer.should == :outer
end
it 'should break out to outer-most session with cd /' do
b = Pry.binding_for(:outer)
b.eval("x = :inner")
redirect_pry_io(InputTester.new("cd x", "$inner = self;", "cd 5", "$five = self", "cd /", "$outer = self", "exit-all"), StringIO.new) do
b.pry
end
$inner.should == :inner
$five.should == 5
$outer.should == :outer
end
it 'should start a session on TOPLEVEL_BINDING with cd ::' do
b = Pry.binding_for(:outer)
redirect_pry_io(InputTester.new("cd ::", "$obj = self", "exit-all"), StringIO.new) do
5.pry
end
$obj.should == TOPLEVEL_BINDING.eval('self')
end
it 'should cd into complex input (with spaces)' do
o = Object.new
def o.hello(x, y, z)
:mon_ouie
end
redirect_pry_io(InputTester.new("cd hello 1, 2, 3", "$obj = self", "exit-all"), StringIO.new) do
o.pry
end
$obj.should == :mon_ouie
end
end
end

View file

@ -0,0 +1,31 @@
require 'helper'
describe "Pry::DefaultCommands::Documentation" do
describe "show-doc" do
it 'should output a method\'s documentation' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-doc sample_method", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /sample doc/
end
it 'should output a method\'s documentation if inside method without needing to use method name' do
$str_output = StringIO.new
o = Object.new
# sample comment
def o.sample
redirect_pry_io(InputTester.new("show-doc", "exit-all"), $str_output) do
binding.pry
end
end
o.sample
$str_output.string.should =~ /sample comment/
$str_output = nil
end
end
end

View file

@ -0,0 +1,157 @@
require 'helper'
describe "Pry::DefaultCommands::Input" do
describe "amend-line-N" do
it 'should correctly amend the last line of input when no line number specified ' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("def hello", "puts :bing", "amend-line puts :blah", "show-input", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /\A\d+: def hello\n\d+: puts :blah/
end
it 'should correctly amend the specified line of input when line number given ' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("def hello", "puts :bing", "puts :bang", "amend-line-0 def goodbye", "show-input", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /\A\d+: def goodbye\n\d+: puts :bing\n\d+: puts :bang/
end
end
describe "show-input" do
it 'should correctly show the current lines in the input buffer' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("def hello", "puts :bing", "show-input", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /\A\d+: def hello\n\d+: puts :bing/
end
end
describe "!" do
it 'should correctly clear the input buffer ' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("def hello", "puts :bing", "!", "show-input", "exit-all"), str_output) do
pry
end
stripped_output = str_output.string.strip!
stripped_output.each_line.count.should == 1
stripped_output.should =~ /Input buffer cleared!/
end
end
describe "hist" do
push_first_hist_line = lambda do |hist, line|
hist.push line
end
before do
Readline::HISTORY.shift until Readline::HISTORY.empty?
@hist = Readline::HISTORY
end
it 'should display the correct history' do
push_first_hist_line.call(@hist, "'bug in 1.8 means this line is ignored'")
@hist.push "hello"
@hist.push "world"
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /hello\n.*world/
end
it 'should replay history correctly (single item)' do
push_first_hist_line.call(@hist, ":hello")
@hist.push ":blah"
@hist.push ":bucket"
@hist.push ":ostrich"
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --replay -1", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /ostrich/
end
it 'should replay a range of history correctly (range of items)' do
push_first_hist_line.call(@hist, "'bug in 1.8 means this line is ignored'")
@hist.push ":hello"
@hist.push ":carl"
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --replay 0..2", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /:hello\n.*:carl/
end
it 'should grep for correct lines in history' do
push_first_hist_line.call(@hist, "apple")
@hist.push "abby"
@hist.push "box"
@hist.push "button"
@hist.push "pepper"
@hist.push "orange"
@hist.push "grape"
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --grep o", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /\d:.*?box\n\d:.*?button\n\d:.*?orange/
end
it 'should return last N lines in history with --tail switch' do
push_first_hist_line.call(@hist, "0")
("a".."z").each do |v|
@hist.push v
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --tail 3", "exit-all"), str_output) do
pry
end
str_output.string.each_line.count.should == 3
str_output.string.should =~ /x\n\d+:.*y\n\d+:.*z/
end
# strangeness in this test is due to bug in Readline::HISTORY not
# always registering first line of input
it 'should return first N lines in history with --head switch' do
push_first_hist_line.call(@hist, "0")
("a".."z").each do |v|
@hist.push v
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --head 4", "exit-all"), str_output) do
pry
end
str_output.string.each_line.count.should == 4
str_output.string.should =~ /a\n\d+:.*b\n\d+:.*c/
end
# strangeness in this test is due to bug in Readline::HISTORY not
# always registering first line of input
it 'should show lines between lines A and B with the --show switch' do
push_first_hist_line.call(@hist, "0")
("a".."z").each do |v|
@hist.push v
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("hist --show 1..4", "exit-all"), str_output) do
pry
end
str_output.string.each_line.count.should == 4
str_output.string.should =~ /b\n\d+:.*c\n\d+:.*d/
end
end
end

View file

@ -0,0 +1,146 @@
require 'helper'
describe "Pry::DefaultCommands::Introspection" do
describe "show-method" do
it 'should output a method\'s source' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-method sample_method", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /def sample/
end
it 'should output a method\'s source with line numbers' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-method -l sample_method", "exit-all"), str_output) do
pry
end
str_output.string.should =~ /\d+: def sample/
end
it 'should output a method\'s source if inside method without needing to use method name' do
$str_output = StringIO.new
o = Object.new
def o.sample
redirect_pry_io(InputTester.new("show-method", "exit-all"), $str_output) do
binding.pry
end
end
o.sample
$str_output.string.should =~ /def o.sample/
$str_output = nil
end
it 'should output a method\'s source if inside method without needing to use method name, and using the -l switch' do
$str_output = StringIO.new
o = Object.new
def o.sample
redirect_pry_io(InputTester.new("show-method -l", "exit-all"), $str_output) do
binding.pry
end
end
o.sample
$str_output.string.should =~ /\d+: def o.sample/
$str_output = nil
end
# dynamically defined method source retrieval is only supported in
# 1.9 - where Method#source_location is native
if RUBY_VERSION =~ /1.9/
it 'should output a method\'s source for a method defined inside pry' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("def dyna_method", ":testing", "end", "show-method dyna_method"), str_output) do
TOPLEVEL_BINDING.pry
end
str_output.string.should =~ /def dyna_method/
Object.remove_method :dyna_method
end
it 'should output a method\'s source for a method defined inside pry, even if exceptions raised before hand' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("bad code", "123", "bad code 2", "1 + 2", "def dyna_method", ":testing", "end", "show-method dyna_method"), str_output) do
TOPLEVEL_BINDING.pry
end
str_output.string.should =~ /def dyna_method/
Object.remove_method :dyna_method
end
it 'should output an instance method\'s source for a method defined inside pry' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("class A", "def yo", "end", "end", "show-method A#yo"), str_output) do
TOPLEVEL_BINDING.pry
end
str_output.string.should =~ /def yo/
Object.remove_const :A
end
it 'should output an instance method\'s source for a method defined inside pry using define_method' do
str_output = StringIO.new
redirect_pry_io(InputTester.new("class A", "define_method(:yup) {}", "end", "end", "show-method A#yup"), str_output) do
TOPLEVEL_BINDING.pry
end
str_output.string.should =~ /define_method\(:yup\)/
Object.remove_const :A
end
end
end
# show-command only works in implementations that support Proc#source_location
if Proc.method_defined?(:source_location)
describe "show-command" do
it 'should show source for an ordinary command' do
set = Pry::CommandSet.new do
import_from Pry::Commands, "show-command"
command "foo" do
:body_of_foo
end
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-command foo"), str_output) do
Pry.new(:commands => set).rep
end
str_output.string.should =~ /:body_of_foo/
end
it 'should show source for a command with spaces in its name' do
set = Pry::CommandSet.new do
import_from Pry::Commands, "show-command"
command "foo bar" do
:body_of_foo_bar
end
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-command \"foo bar\""), str_output) do
Pry.new(:commands => set).rep
end
str_output.string.should =~ /:body_of_foo_bar/
end
it 'should show source for a command by listing name' do
set = Pry::CommandSet.new do
import_from Pry::Commands, "show-command"
command /foo(.*)/, "", :listing => "bar" do
:body_of_foo_regex
end
end
str_output = StringIO.new
redirect_pry_io(InputTester.new("show-command bar"), str_output) do
Pry.new(:commands => set).rep
end
str_output.string.should =~ /:body_of_foo_regex/
end
end
end
end

View file

@ -488,6 +488,46 @@ describe Pry do
str_output.string.should =~ /hello 1 baby/
end
it 'should create a regex command and interpolate the captures' do
set = Pry::CommandSet.new do
command /hello (.*)/, "" do |c1|
output.puts "hello #{c1}"
end
end
str_output = StringIO.new
$obj = "bing"
redirect_pry_io(InputTester.new('hello #{$obj}'), str_output) do
Pry.new(:commands => set).rep
end
str_output.string.should =~ /hello bing/
$obj = nil
end
it 'should create a regex command and arg_string should be interpolated' do
set = Pry::CommandSet.new do
command /hello(\w+)/, "" do |c1, a1, a2, a3|
output.puts "hello #{c1} #{a1} #{a2} #{a3}"
end
end
str_output = StringIO.new
$a1 = "bing"
$a2 = "bong"
$a3 = "bang"
redirect_pry_io(InputTester.new('hellojohn #{$a1} #{$a2} #{$a3}'), str_output) do
Pry.new(:commands => set).rep
end
str_output.string.should =~ /hello john bing bong bang/
$a1 = nil
$a2 = nil
$a3 = nil
end
it 'if a regex capture is missing it should be nil' do
set = Pry::CommandSet.new do
command /hello(.)?/, "" do |c1, a1|