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 into feature/history-array
Conflicts: lib/pry/pry_instance.rb
This commit is contained in:
commit
fca1005b64
38 changed files with 755 additions and 431 deletions
|
@ -1,4 +1,4 @@
|
|||
![Alt text](http://dl.dropbox.com/u/26521875/pry_logo_shade.png)
|
||||
![Alt text](http://dl.dropbox.com/u/15761219/pry_horizontal_red.png)
|
||||
|
||||
(C) John Mair (banisterfiend) 2011
|
||||
|
||||
|
|
11
Rakefile
11
Rakefile
|
@ -17,7 +17,6 @@ def apply_spec_defaults(s)
|
|||
s.email = 'jrmair@gmail.com'
|
||||
s.description = s.summary
|
||||
s.homepage = "http://banisterfiend.wordpress.com"
|
||||
s.has_rdoc = 'yard'
|
||||
s.executables = ["pry"]
|
||||
s.files = `git ls-files`.split("\n")
|
||||
s.test_files = `git ls-files -- test/*`.split("\n")
|
||||
|
@ -34,8 +33,7 @@ end
|
|||
|
||||
desc "run pry"
|
||||
task :pry do
|
||||
require 'pry'
|
||||
binding.pry
|
||||
load 'bin/pry'
|
||||
end
|
||||
|
||||
desc "show pry version"
|
||||
|
@ -53,6 +51,13 @@ namespace :ruby do
|
|||
pkg.need_zip = false
|
||||
pkg.need_tar = false
|
||||
end
|
||||
|
||||
desc "Generate gemspec file"
|
||||
task :gemspec do
|
||||
File.open("#{spec.name}-#{spec.version}.gemspec", "w") do |f|
|
||||
f << spec.to_ruby
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
[:mingw32, :mswin32].each do |v|
|
||||
|
|
23
bin/pry
23
bin/pry
|
@ -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]))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?"
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
6
examples/helper.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
require 'rubygems'
|
||||
unless Object.const_defined? 'Pry'
|
||||
$:.unshift File.expand_path '../../lib', __FILE__
|
||||
require 'pry'
|
||||
end
|
||||
|
|
@ -16,14 +16,6 @@ class Pry
|
|||
# @param [String] val The string passed in from the Pry prompt.
|
||||
# @return [Boolean] Whether the string is a valid command.
|
||||
def valid_command?(val)
|
||||
pry_command?(val)
|
||||
end
|
||||
|
||||
|
||||
# Is the string a valid pry command?
|
||||
# @param [String] val The string passed in from the Pry prompt.
|
||||
# @return [Boolean] Whether the string is a valid Pry command.
|
||||
def pry_command?(val)
|
||||
!!(command_matched(val)[0])
|
||||
end
|
||||
|
||||
|
@ -48,7 +40,6 @@ class Pry
|
|||
target.eval(dumped_str)
|
||||
end
|
||||
|
||||
|
||||
# Determine whether a Pry command was matched and return command data
|
||||
# and argument string.
|
||||
# This method should not need to be invoked directly.
|
||||
|
@ -72,18 +63,19 @@ class Pry
|
|||
# multi-line input.
|
||||
# @param [Binding] target The receiver of the commands.
|
||||
def process_commands(val, eval_string, target)
|
||||
def val.clear() replace("") end
|
||||
def eval_string.clear() replace("") end
|
||||
|
||||
# no command was matched, so return to caller
|
||||
return if !pry_command?(val)
|
||||
|
||||
return if !valid_command?(val)
|
||||
command, captures, pos = command_matched(val)
|
||||
|
||||
val.replace interpolate_string(val, target) if command.options[:interpolate]
|
||||
|
||||
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 = {
|
||||
|
@ -121,7 +113,7 @@ class Pry
|
|||
ret = commands.run_command(context, command, *args)
|
||||
|
||||
# Tick, tock, im getting rid of this shit soon.
|
||||
options[:val].clear
|
||||
options[:val].replace("")
|
||||
|
||||
ret
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ class Pry
|
|||
end
|
||||
end
|
||||
|
||||
# This class used to create sets of commands. Commands can be impoted from
|
||||
# This class is used to create sets of commands. Commands can be imported from
|
||||
# different sets, aliased, removed, etc.
|
||||
class CommandSet
|
||||
class Command < Struct.new(:name, :description, :options, :block)
|
||||
|
@ -31,6 +31,7 @@ class Pry
|
|||
end
|
||||
end
|
||||
|
||||
include Enumerable
|
||||
include Pry::Helpers::BaseHelpers
|
||||
|
||||
attr_reader :commands
|
||||
|
@ -112,7 +113,7 @@ class Pry
|
|||
gems_not_installed = gems_needed.select { |g| !gem_installed?(g) }
|
||||
|
||||
options[:stub_info] = proc do
|
||||
output.puts "\nThe command '#{name}' is unavailable because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
|
||||
output.puts "\nThe command '#{name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
|
||||
output.puts "-"
|
||||
output.puts "Type `install #{name}` to install the required gems and activate this command."
|
||||
end
|
||||
|
@ -121,6 +122,10 @@ class Pry
|
|||
commands[name] = Command.new(name, description, options, block)
|
||||
end
|
||||
|
||||
def each &block
|
||||
@commands.each(&block)
|
||||
end
|
||||
|
||||
# Removes some commands from the set
|
||||
# @param [Array<String>] names name of the commands to remove
|
||||
def delete(*names)
|
||||
|
@ -205,6 +210,11 @@ class Pry
|
|||
end
|
||||
|
||||
|
||||
# @return [Array] The list of commands provided by the command set.
|
||||
def list_commands
|
||||
commands.keys
|
||||
end
|
||||
|
||||
private
|
||||
def define_default_commands
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -30,13 +30,13 @@ class Object
|
|||
begin
|
||||
instance_eval %{
|
||||
def __binding_impl__
|
||||
Kernel.binding
|
||||
binding
|
||||
end
|
||||
}
|
||||
rescue TypeError
|
||||
self.class.class_eval %{
|
||||
def __binding_impl__
|
||||
Kernel.binding
|
||||
binding
|
||||
end
|
||||
}
|
||||
end
|
||||
|
|
|
@ -23,7 +23,7 @@ class Pry
|
|||
command "import", "Import a command set" do |command_set_name|
|
||||
next output.puts "Provide a command set name" if command_set.nil?
|
||||
|
||||
set = target.eval(opts[:arg_string])
|
||||
set = target.eval(arg_string)
|
||||
Pry.active_instance.commands.import set
|
||||
end
|
||||
|
||||
|
|
|
@ -19,14 +19,18 @@ class Pry
|
|||
end
|
||||
|
||||
command "gem-cd", "Change working directory to specified gem's directory.", :argument_required => true do |gem|
|
||||
spec = Gem.source_index.find_name(gem).sort { |a,b| Gem::Version.new(b.version) <=> Gem::Version.new(a.version) }.first
|
||||
specs = Gem::Specification.respond_to?(:each) ? Gem::Specification.find_all_by_name(gem) : Gem.source_index.find_name(gem)
|
||||
spec = specs.sort { |a,b| Gem::Version.new(b.version) <=> Gem::Version.new(a.version) }.first
|
||||
spec ? Dir.chdir(spec.full_gem_path) : output.puts("Gem `#{gem}` not found.")
|
||||
end
|
||||
|
||||
|
||||
command "gem-list", "List/search installed gems. (Optional parameter: a regexp to limit the search)" do |pattern|
|
||||
pattern = Regexp.new pattern.to_s, Regexp::IGNORECASE
|
||||
gems = Gem.source_index.find_name(pattern).group_by(&:name)
|
||||
gems = if Gem::Specification.respond_to?(:each)
|
||||
Gem::Specification.select{|spec| spec.name =~ pattern }.group_by(&:name)
|
||||
else
|
||||
Gem.source_index.gems.values.group_by(&:name).select { |gemname, specs| gemname =~ pattern }
|
||||
end
|
||||
|
||||
gems.each do |gem, specs|
|
||||
specs.sort! do |a,b|
|
||||
|
|
|
@ -5,7 +5,7 @@ class Pry
|
|||
|
||||
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!"
|
||||
eval_string.clear
|
||||
eval_string.replace("")
|
||||
end
|
||||
|
||||
command "show-input", "Show the current eval_string" do
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -13,39 +13,36 @@ class Pry
|
|||
meth.reload
|
||||
end
|
||||
|
||||
command "play-string", "Play a string as input" do
|
||||
Pry.active_instance.input = StringIO.new(opts[:arg_string])
|
||||
end
|
||||
|
||||
command "play-method", "Play a method source as input" do |*args|
|
||||
target = target()
|
||||
opts = Slop.parse!(args) do |opt|
|
||||
command "play", "Play a string as input" do |*args|
|
||||
Slop.parse!(args) do |opt|
|
||||
opt.banner "Usage: play-method [--replay START..END] [--clear] [--grep PATTERN] [--help]\n"
|
||||
|
||||
opt.on :l, :lines, 'The line (or range of lines) to replay.', true, :as => Range
|
||||
opt.on :m, :method, 'Play a method.', true do |meth_name|
|
||||
if (meth = get_method_object(meth_name, target, {})).nil?
|
||||
output.puts "Invalid method name: #{meth_name}."
|
||||
next
|
||||
end
|
||||
code, code_type = code_and_code_type_for(meth)
|
||||
next if !code
|
||||
|
||||
range = opt.l? ? opt[:l] : (0..-1)
|
||||
|
||||
Pry.active_instance.input = StringIO.new(code[range])
|
||||
end
|
||||
|
||||
opt.on :f, "file", 'The line (or range of lines) to replay.', true do |file_name|
|
||||
text = File.read File.expand_path(file_name)
|
||||
range = opt.l? ? opt[:l] : (0..-1)
|
||||
|
||||
Pry.active_instance.input = StringIO.new(text[range])
|
||||
end
|
||||
|
||||
opt.on :h, :help, "This message." do
|
||||
output.puts opt
|
||||
end
|
||||
end
|
||||
|
||||
next if opts.help?
|
||||
|
||||
meth_name = args.shift
|
||||
if (meth = get_method_object(meth_name, target, {})).nil?
|
||||
output.puts "Invalid method name: #{meth_name}. Type `play-method --help` for help"
|
||||
next
|
||||
end
|
||||
|
||||
code, code_type = code_and_code_type_for(meth)
|
||||
next if !code
|
||||
|
||||
slice = opts[:l] ? opts[:l] : (0..-1)
|
||||
|
||||
sliced_code = code.each_line.to_a[slice].join("\n")
|
||||
|
||||
Pry.active_instance.input = StringIO.new(sliced_code)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,10 +6,10 @@ class Pry
|
|||
command "define-command", "To honor Mon-Ouie" do |arg|
|
||||
next output.puts("Provide an arg!") if arg.nil?
|
||||
|
||||
prime_string = "command #{opts[:arg_string]}\n"
|
||||
prime_string = "command #{arg_string}\n"
|
||||
command_string = Pry.active_instance.r(target, prime_string)
|
||||
|
||||
opts[:eval_string].replace <<-HERE
|
||||
eval_string.replace <<-HERE
|
||||
_pry_.commands.instance_eval do
|
||||
#{command_string}
|
||||
end
|
||||
|
|
|
@ -23,7 +23,7 @@ class Pry
|
|||
|
||||
def gem_installed?(gem_name)
|
||||
require 'rubygems'
|
||||
!!Gem.source_index.find_name(gem_name).first
|
||||
Gem::Specification.respond_to?(:find_all_by_name) ? !Gem::Specification.find_all_by_name(gem_name).empty? : Gem.source_index.find_name(gem_name).first
|
||||
end
|
||||
|
||||
def command_dependencies_met?(options)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -44,7 +44,7 @@ class Pry
|
|||
# Find all installed Pry plugins and store them in an internal array.
|
||||
def locate_plugins
|
||||
Gem.refresh
|
||||
Gem.source_index.find_name('').each do |gem|
|
||||
(Gem::Specification.respond_to?(:each) ? Gem::Specification : Gem.source_index.find_name('')).each do |gem|
|
||||
next if gem.name !~ PRY_PLUGIN_PREFIX
|
||||
plugin_name = gem.name.split('-', 2).last
|
||||
@plugins << Plugin.new(plugin_name, gem.name, true) if !gem_located?(gem.name)
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -19,12 +19,25 @@ class Pry
|
|||
# @param [Hash] options The optional configuration parameters.
|
||||
# @option options [#readline] :input The object to use for input.
|
||||
# @option options [#puts] :output The object to use for output.
|
||||
# @option options [Pry::CommandBase] :commands The object to use for commands. (see commands.rb)
|
||||
# @option options [Hash] :hooks The defined hook Procs (see hooks.rb)
|
||||
# @option options [Array<Proc>] :default_prompt The array of Procs to use for the prompts. (see prompts.rb)
|
||||
# @option options [Pry::CommandBase] :commands The object to use for commands.
|
||||
# @option options [Hash] :hooks The defined hook Procs
|
||||
# @option options [Array<Proc>] :prompt The array of Procs to use for the prompts.
|
||||
# @option options [Proc] :print The Proc to use for the 'print'
|
||||
# component of the REPL. (see print.rb)
|
||||
def initialize(options={})
|
||||
refresh(options)
|
||||
|
||||
@command_processor = CommandProcessor.new(self)
|
||||
|
||||
@input_array = HistoryArray.new(100)
|
||||
@output_array = HistoryArray.new(100)
|
||||
end
|
||||
|
||||
# Refresh the Pry instance settings from the Pry class.
|
||||
# Allows options to be specified to override settings from Pry class.
|
||||
# @param [Hash] options The options to override Pry class settings
|
||||
# for this instance.
|
||||
def refresh(options={})
|
||||
defaults = {}
|
||||
attributes = [
|
||||
:input, :output, :commands, :print,
|
||||
|
@ -36,14 +49,11 @@ class Pry
|
|||
defaults[attribute] = Pry.send attribute
|
||||
end
|
||||
|
||||
defaults.merge!(options).each_key do |key|
|
||||
send "#{key}=", defaults[key]
|
||||
defaults.merge!(options).each do |key, value|
|
||||
send "#{key}=", value
|
||||
end
|
||||
|
||||
@command_processor = CommandProcessor.new(self)
|
||||
|
||||
@input_array = HistoryArray.new(100)
|
||||
@output_array = HistoryArray.new(100)
|
||||
true
|
||||
end
|
||||
|
||||
# The current prompt.
|
||||
|
@ -106,11 +116,12 @@ class Pry
|
|||
Pry.active_instance = self
|
||||
|
||||
# Make sure special locals exist
|
||||
target.eval("_pry_ = ::Pry.active_instance")
|
||||
target.eval("_ = ::Pry.last_result")
|
||||
target.eval("_in_ = ::Pry.active_instance.instance_eval { @input_array }")
|
||||
target.eval("_out_ = ::Pry.active_instance.instance_eval { @output_array }")
|
||||
|
||||
set_active_instance(target)
|
||||
set_last_result(Pry.last_result, target)
|
||||
|
||||
self.session_target = target
|
||||
end
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
class Pry
|
||||
VERSION = "0.9.0pre1"
|
||||
VERSION = "0.9.0pre2"
|
||||
end
|
||||
|
|
|
@ -18,6 +18,7 @@ class << Pry
|
|||
Pry.color = false
|
||||
Pry.pager = false
|
||||
Pry.config.should_load_rc = false
|
||||
Pry.config.plugins.enabled = false
|
||||
Pry.config.history.load = false
|
||||
Pry.config.history.save = false
|
||||
end
|
||||
|
|
|
@ -1,295 +1,59 @@
|
|||
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"
|
||||
describe "help" do
|
||||
it 'should display help for a specific command' do
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("hist", "exit-all"), str_output) do
|
||||
redirect_pry_io(InputTester.new("help ls", "exit-all"), str_output) do
|
||||
pry
|
||||
end
|
||||
str_output.string.should =~ /hello\n.*world/
|
||||
str_output.string.each_line.count.should == 1
|
||||
str_output.string.should =~ /ls --help/
|
||||
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
|
||||
it 'should display help for a regex command with a "listing"' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /bar(.*)/, "Test listing", :listing => "foo" do
|
||||
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
|
||||
|
||||
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
|
||||
redirect_pry_io(InputTester.new("help foo"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /sample doc/
|
||||
str_output.string.each_line.count.should == 1
|
||||
str_output.string.should =~ /Test listing/
|
||||
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
|
||||
it 'should display help for a command with a spaces in its name' do
|
||||
set = Pry::CommandSet.new do
|
||||
command "command with spaces", "description of a command with spaces" do
|
||||
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
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("help \"command with spaces\""), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
$obj.should == :mon_ouie
|
||||
str_output.string.each_line.count.should == 1
|
||||
str_output.string.should =~ /description of a command with spaces/
|
||||
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
|
||||
it 'should display help for all commands with a description' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /bar(.*)/, "Test listing", :listing => "foo" do; end
|
||||
command "b", "description for b", :listing => "foo" do; end
|
||||
command "c" do;end
|
||||
command "d", "" do;end
|
||||
end
|
||||
|
||||
redirect_pry_io(InputTester.new("cd hello 1, 2, 3", "$obj = self", "exit-all"), StringIO.new) do
|
||||
o.pry
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("help"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
$obj.should == :mon_ouie
|
||||
str_output.string.should =~ /Test listing/
|
||||
str_output.string.should =~ /description for b/
|
||||
str_output.string.should =~ /No description/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
64
test/test_default_commands/test_context.rb
Normal file
64
test/test_default_commands/test_context.rb
Normal 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
|
31
test/test_default_commands/test_documentation.rb
Normal file
31
test/test_default_commands/test_documentation.rb
Normal 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
|
157
test/test_default_commands/test_input.rb
Normal file
157
test/test_default_commands/test_input.rb
Normal 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
|
146
test/test_default_commands/test_introspection.rb
Normal file
146
test/test_default_commands/test_introspection.rb
Normal 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
|
|
@ -297,11 +297,6 @@ describe Pry do
|
|||
Pry.binding_for(_main_.call).should == TOPLEVEL_BINDING
|
||||
Pry.binding_for(_main_.call).should == Pry.binding_for(_main_.call)
|
||||
end
|
||||
|
||||
it 'should return a binding with the right self for procs' do
|
||||
proc = Proc.new {}
|
||||
Pry.binding_for(proc).eval("self").should.equal? proc
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -484,6 +479,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|
|
||||
|
@ -617,6 +652,49 @@ describe Pry do
|
|||
str_output.string.should =~ /v command/
|
||||
end
|
||||
|
||||
it 'should run a regex command from within a command' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command /v(.*)?/ do |arg|
|
||||
output.puts "v #{arg}"
|
||||
end
|
||||
|
||||
command "run_v" do
|
||||
run "vbaby"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("run_v"), str_output) do
|
||||
Pry.new(:commands => klass).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /v baby/
|
||||
end
|
||||
|
||||
it 'should run a command from within a command with arguments' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command /v(\w+)/ do |arg1, arg2|
|
||||
output.puts "v #{arg1} #{arg2}"
|
||||
end
|
||||
|
||||
command "run_v_explicit_parameter" do
|
||||
run "vbaby", "param"
|
||||
end
|
||||
|
||||
command "run_v_embedded_parameter" do
|
||||
run "vbaby param"
|
||||
end
|
||||
end
|
||||
|
||||
["run_v_explicit_parameter", "run_v_embedded_parameter"].each do |cmd|
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new(cmd), str_output) do
|
||||
Pry.new(:commands => klass).rep
|
||||
end
|
||||
str_output.string.should =~ /v baby param/
|
||||
end
|
||||
end
|
||||
|
||||
it 'should enable an inherited method to access opts and output and target, due to instance_exec' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "v" do
|
||||
|
|
Loading…
Reference in a new issue