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

Merge branch 'master' into refactor/direct_tests

Conflicts:
	lib/pry/commands/cd.rb
	test/test_default_commands/test_documentation.rb
This commit is contained in:
Ryan Fitzgerald 2012-08-16 23:26:52 -07:00
commit 6271b16aee
20 changed files with 593 additions and 246 deletions

View file

@ -120,6 +120,10 @@ class Pry
end
end
# Store the current working directory. This allows show-source etc. to work if
# your process has changed directory since boot. [Issue #675]
INITIAL_PWD = Dir.pwd
# As a REPL, we often want to catch any unexpected exceptions that may have
# been raised; however we don't want to go overboard and prevent the user
# from exiting Pry when they want to.

View file

@ -57,12 +57,18 @@ class Pry
end
def parse_options(args=ARGV.dup)
raise NoOptionsError, "No command line options defined! Use Pry::CLI.add_options to add command line options." if !options
unless options
raise NoOptionsError, "No command line options defined! Use Pry::CLI.add_options to add command line options."
end
self.input_args = args
opts = Slop.parse!(args, :help => true, :multiple_switches => false, &options)
option_processors.each { |processor| processor.call(opts) } if option_processors # option processors are optional
# Option processors are optional.
if option_processors
option_processors.each { |processor| processor.call(opts) }
end
self
end
@ -139,8 +145,12 @@ Copyright (c) 2011 John Mair (banisterfiend)
Pry.config.requires << file
end
on :I, "Add a path to the $LOAD_PATH", :argument => true do |path|
$LOAD_PATH << path
on :I, "Add a path to the $LOAD_PATH", :argument => true, :as => Array, :delimiter => ":" do |load_path|
load_path.map! do |path|
/\A\.\// =~ path ? path : File.expand_path(path)
end
$LOAD_PATH.unshift(*load_path)
end
on :v, :version, "Display the Pry version" do

View file

@ -35,20 +35,23 @@ class Pry
# @param [String] fn The name of a file, or "(pry)".
# @param [Symbol] code_type The type of code the file contains.
# @return [Code]
def from_file(fn, code_type = nil)
def from_file(fn, code_type=type_from_filename(fn))
if fn == Pry.eval_path
f = Pry.line_buffer.drop(1)
new(Pry.line_buffer.drop(1), 1, code_type)
else
if File.readable?(fn)
f = File.open(fn, 'r')
code_type ||= type_from_filename(fn)
else
abs_path = [File.expand_path(fn, Dir.pwd),
File.expand_path(fn, Pry::INITIAL_PWD)
].detect{ |abs_path| File.readable?(abs_path) }
unless abs_path
raise MethodSource::SourceNotFoundError, "Cannot open #{fn.inspect} for reading."
end
File.open(abs_path, 'r') do |f|
new(f, 1, code_type)
end
end
new(f, 1, code_type || :ruby)
ensure
f.close if f.respond_to?(:close)
end
# Instantiate a `Code` object containing code extracted from a
@ -85,8 +88,9 @@ class Pry
# unknown.
#
# @param [String] filename
# @param [Symbol] default (:ruby) the file type to assume if none could be detected
# @return [Symbol, nil]
def type_from_filename(filename)
def type_from_filename(filename, default=:ruby)
map = {
%w(.c .h) => :c,
%w(.cpp .hpp .cc .h cxx) => :cpp,
@ -108,7 +112,7 @@ class Pry
k.any? { |ext| ext == File.extname(filename) }
end
type
type || default
end
end

View file

@ -1,9 +1,12 @@
require 'pry/helpers/documentation_helpers'
class Pry
# The super-class of all commands, new commands should be created by calling
# {Pry::CommandSet#command} which creates a BlockCommand or {Pry::CommandSet#create_command}
# which creates a ClassCommand. Please don't use this class directly.
class Command
extend Helpers::DocumentationHelpers
# represents a void return value for a command
VOID_VALUE = Object.new
@ -49,6 +52,14 @@ class Pry
def block
@block || instance_method(:process) && instance_method(:process)
end
def source
strip_leading_whitespace(block.source)
end
def source_location
block.source_location
end
end
# Make those properties accessible to instances
@ -58,6 +69,8 @@ class Pry
def block; self.class.block; end
def command_options; self.class.options; end
def command_name; command_options[:listing]; end
def source; self.class.source; end
def source_location; self.class.source_location; end
class << self
def name

View file

@ -20,64 +20,9 @@ class Pry
BANNER
def process
# Extract command arguments. Delete blank arguments like " ", but
# don't delete empty strings like "".
path = arg_string.split(/\//).delete_if { |a| a =~ /\A\s+\z/ }
stack = _pry_.binding_stack.dup
old_stack = state.old_stack || []
# Special case when we only get a single "/", return to root.
if path.empty?
state.old_stack = stack.dup unless old_stack.empty?
stack = [stack.first]
end
path.each_with_index do |context, i|
begin
case context.chomp
when ""
state.old_stack = stack.dup
stack = [stack.first]
when "::"
state.old_stack = stack.dup
stack.push(TOPLEVEL_BINDING)
when "."
next
when ".."
unless stack.size == 1
# Don't rewrite old_stack if we're in complex expression
# (e.g.: `cd 1/2/3/../4).
state.old_stack = stack.dup if path.first == ".."
stack.pop
end
when "-"
unless old_stack.empty?
# Interchange current stack and old stack with each other.
stack, state.old_stack = state.old_stack, stack
end
else
state.old_stack = stack.dup if i == 0
stack.push(Pry.binding_for(stack.last.eval(context)))
end
rescue RescuableException => e
# Restore old stack to its initial values.
state.old_stack = old_stack
msg = [
"Bad object path: #{arg_string}.",
"Failed trying to resolve: #{context}.",
e.inspect
].join(' ')
CommandError.new(msg).tap do |err|
err.set_backtrace e.backtrace
raise err
end
end
end
_pry_.binding_stack = stack
stack, old_stack = context_from_object_path(arg_string, _pry_, state.old_stack||[])
state.old_stack = old_stack
_pry_.binding_stack = stack unless stack.nil?
end
end
end

View file

@ -8,40 +8,15 @@ class Pry
opts = Slop.parse!(args) do |opt|
opt.banner unindent <<-USAGE
Usage: show-command [OPTIONS] [CMD]
Show the source for command CMD.
e.g: show-command show-method
NOTE: show-command is DEPRACTED. Use show-source [command_name] instead.
USAGE
opt.on :l, "line-numbers", "Show line numbers."
opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
opt.on :h, :help, "This message." do
output.puts opt.help
end
end
return if opts.present?(:help)
command_name = args.shift
if !command_name
raise CommandError, "You must provide a command name."
end
if find_command(command_name)
block = Pry::Method.new(find_command(command_name).block)
return unless block.source
set_file_and_dir_locals(block.source_file)
output.puts make_header(block)
output.puts
code = Pry::Code.from_method(block).with_line_numbers(opts.present?(:'line-numbers')).to_s
render_output(code, opts)
else
raise CommandError, "No such command: #{command_name}."
end
render_output opts.banner
end
end
end

View file

@ -111,6 +111,24 @@ class Pry
doc
end
def process_command
name = args.join(" ").gsub(/\"/,"")
command = find_command(name)
doc = command.new.help
doc = strip_leading_whitespace(doc)
file_name, line = command.source_location
set_file_and_dir_locals(file_name)
result = ""
result << "\n#{Pry::Helpers::Text.bold('From:')} #{file_name} @ line #{line}:\n"
result << "#{Pry::Helpers::Text.bold('Number of lines:')} #{doc.lines.count}\n\n"
result << doc
result << "\n"
end
def module_start_line(mod, candidate=0)
if opts.present?(:'base-one')
1

View file

@ -111,6 +111,23 @@ class Pry
result
end
def process_command
name = args.join(" ").gsub(/\"/,"")
command = find_command(name)
file_name, line = command.source_location
set_file_and_dir_locals(file_name)
code = Pry::Code.new(command.source, line).with_line_numbers(use_line_numbers?).to_s
result = ""
result << "\n#{Pry::Helpers::Text.bold('From:')} #{file_name} @ line #{line}:\n"
result << "#{Pry::Helpers::Text.bold('Number of lines:')} #{code.lines.count}\n\n"
result << "\n"
result << code
end
def use_line_numbers?
opts.present?(:b) || opts.present?(:l)
end

View file

@ -41,36 +41,50 @@ class Pry
# Return a new completion proc for use by Readline.
# @param [Binding] target The current binding context.
# @param [Array<String>] commands The array of Pry commands.
def self.build_completion_proc(target, commands=[""])
def self.build_completion_proc(target, pry=nil, commands=[""])
proc do |input|
# if there are multiple contexts e.g. cd 1/2/3
# get new target for 1/2 and find candidates for 3
path, input = build_path(input)
unless path.call.empty?
target, _ = Pry::Helpers::BaseHelpers.context_from_object_path(path.call, pry)
target = target.last
end
begin
bind = target
case input
# Complete stdlib symbols
when /^(\/[^\/]*\/)\.([^.]*)$/
# Regexp
receiver = $1
message = Regexp.quote($2)
candidates = Regexp.instance_methods.collect{|m| m.to_s}
select_message(receiver, message, candidates)
candidates = Regexp.instance_methods.collect(&:to_s)
select_message(path, receiver, message, candidates)
when /^([^\]]*\])\.([^.]*)$/
# Array
receiver = $1
message = Regexp.quote($2)
candidates = Array.instance_methods.collect{|m| m.to_s}
select_message(receiver, message, candidates)
candidates = Array.instance_methods.collect(&:to_s)
select_message(path, receiver, message, candidates)
when /^([^\}]*\})\.([^.]*)$/
# Proc or Hash
receiver = $1
message = Regexp.quote($2)
candidates = Proc.instance_methods.collect{|m| m.to_s}
candidates |= Hash.instance_methods.collect{|m| m.to_s}
select_message(receiver, message, candidates)
candidates = Proc.instance_methods.collect(&:to_s)
candidates |= Hash.instance_methods.collect(&:to_s)
select_message(path, receiver, message, candidates)
when /^(:[^:.]*)$/
# Symbol
@ -86,16 +100,32 @@ class Pry
when /^::([A-Z][^:\.\(]*)$/
# Absolute Constant or class methods
receiver = $1
candidates = Object.constants.collect{|m| m.to_s}
candidates = Object.constants.collect(&:to_s)
candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
# Complete target symbols
when /^([A-Z][A-Za-z0-9]*)$/
# Constant
message = $1
begin
context = target.eval("self")
context = context.class unless context.respond_to? :constants
candidates = context.constants.collect(&:to_s)
rescue
candidates = []
end
candidates = candidates.grep(/^#{message}/).collect(&path)
when /^([A-Z].*)::([^:.]*)$/
# Constant or class methods
receiver = $1
message = Regexp.quote($2)
begin
candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
candidates = eval("#{receiver}.constants.collect(&:to_s)", bind)
candidates |= eval("#{receiver}.methods.collect(&:to_s)", bind)
rescue RescuableException
candidates = []
end
@ -106,8 +136,8 @@ class Pry
receiver = $1
message = Regexp.quote($2)
candidates = Symbol.instance_methods.collect{|m| m.to_s}
select_message(receiver, message, candidates)
candidates = Symbol.instance_methods.collect(&:to_s)
select_message(path, receiver, message, candidates)
when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/
# Numeric
@ -115,42 +145,43 @@ class Pry
message = Regexp.quote($5)
begin
candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
candidates = eval(receiver, bind).methods.collect(&:to_s)
rescue RescuableException
candidates = []
end
select_message(receiver, message, candidates)
select_message(path, receiver, message, candidates)
when /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/
when /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/#
# Numeric(0xFFFF)
receiver = $1
message = Regexp.quote($2)
begin
candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
candidates = eval(receiver, bind).methods.collect(&:to_s)
rescue RescuableException
candidates = []
end
select_message(receiver, message, candidates)
select_message(path, receiver, message, candidates)
when /^(\$[^.]*)$/
# Global variables
regmessage = Regexp.new(Regexp.quote($1))
candidates = global_variables.collect{|m| m.to_s}.grep(regmessage)
candidates = global_variables.collect(&:to_s).grep(regmessage)
when /^([^."].*)\.([^.]*)$/
# variable
# Variable
receiver = $1
message = Regexp.quote($2)
gv = eval("global_variables", bind).collect{|m| m.to_s}
lv = eval("local_variables", bind).collect{|m| m.to_s}
cv = eval("self.class.constants", bind).collect{|m| m.to_s}
gv = eval("global_variables", bind).collect(&:to_s)
lv = eval("local_variables", bind).collect(&:to_s)
cv = eval("self.class.constants", bind).collect(&:to_s)
if (gv | lv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
# foo.func and foo is local var. OR
# Foo::Bar.func
begin
candidates = eval("#{receiver}.methods", bind).collect{|m| m.to_s}
candidates = eval("#{receiver}.methods", bind).collect(&:to_s)
rescue RescuableException
candidates = []
end
@ -169,35 +200,35 @@ class Pry
# jruby doesn't always provide #instance_methods() on each
# object.
if m.respond_to?(:instance_methods)
candidates.concat m.instance_methods(false).collect{|x| x.to_s}
candidates.concat m.instance_methods(false).collect(&:to_s)
end
}
candidates.sort!
candidates.uniq!
end
select_message(receiver, message, candidates)
select_message(path, receiver, message, candidates)
when /^\.([^.]*)$/
# unknown(maybe String)
# Unknown(maybe String)
receiver = ""
message = Regexp.quote($1)
candidates = String.instance_methods(true).collect{|m| m.to_s}
select_message(receiver, message, candidates)
candidates = String.instance_methods(true).collect(&:to_s)
select_message(path, receiver, message, candidates)
else
candidates = eval(
"methods | private_methods | local_variables | " \
"self.class.constants | instance_variables",
bind
).collect{|m| m.to_s}
).collect(&:to_s)
if eval("respond_to?(:class_variables)", bind)
candidates += eval("class_variables", bind).collect { |m| m.to_s }
candidates += eval("class_variables", bind).collect(&:to_s)
end
(candidates|ReservedWords|commands).grep(/^#{Regexp.quote(input)}/)
candidates = (candidates|ReservedWords|commands).grep(/^#{Regexp.quote(input)}/)
candidates.collect(&path)
end
rescue RescuableException
[]
@ -205,17 +236,38 @@ class Pry
end
end
def self.select_message(receiver, message, candidates)
def self.select_message(path, receiver, message, candidates)
candidates.grep(/^#{message}/).collect do |e|
case e
when /^[a-zA-Z_]/
receiver + "." + e
when /^[0-9]/
when *Operators
#receiver + " " + e
end
case e
when /^[a-zA-Z_]/
path.call(receiver + "." + e)
when /^[0-9]/
when *Operators
#receiver + " " + e
end
end
end
# build_path seperates the input into two parts: path and input.
# input is the partial string that should be completed
# path is a proc that takes an input and builds a full path.
def self.build_path(input)
# check to see if the input is a regex
return proc {|input| input.to_s }, input if input[/\/\./]
trailing_slash = input.end_with?('/')
contexts = input.chomp('/').split(/\//)
input = contexts[-1]
path = proc do |input|
p = contexts[0..-2].push(input).join('/')
p += '/' if trailing_slash && !input.nil?
p
end
return path, input
end
end
end

View file

@ -70,7 +70,7 @@ class Pry
end
def use_ansi_codes?
windows_ansi? || ENV['TERM'] && ENV['TERM'] != "dumb"
windows_ansi? || ENV['TERM'] && ENV['TERM'] != "dumb"
end
def colorize_code(code)
@ -123,16 +123,16 @@ class Pry
# simple_pager. Also do not page if Pry.pager is falsey
def stagger_output(text, out = nil)
out ||= case
when respond_to?(:output)
# Mixin.
output
when Pry.respond_to?(:output)
# Parent.
Pry.output
else
# Sys.
$stdout
end
when respond_to?(:output)
# Mixin.
output
when Pry.respond_to?(:output)
# Parent.
Pry.output
else
# Sys.
$stdout
end
if text.lines.count < Pry::Pager.page_size || !Pry.pager
out.puts text
@ -143,6 +143,73 @@ class Pry
Pry::Pager.page(text, :simple)
rescue Errno::EPIPE
end
# @param [String] arg_string The object path expressed as a string.
# @param [Pry] _pry_ The relevant Pry instance.
# @param [Array<Binding>] old_stack The state of the old binding stack
# @return [Array<Array<Binding>, Array<Binding>>] An array
# containing two elements: The new `binding_stack` and the old `binding_stack`.
def context_from_object_path(arg_string, _pry_=nil, old_stack=[])
# Extract command arguments. Delete blank arguments like " ", but
# don't delete empty strings like "".
path = arg_string.split(/\//).delete_if { |a| a =~ /\A\s+\z/ }
stack = _pry_.binding_stack.dup
state_old_stack = old_stack
# Special case when we only get a single "/", return to root.
if path.empty?
state_old_stack = stack.dup unless old_stack.empty?
stack = [stack.first]
end
path.each_with_index do |context, i|
begin
case context.chomp
when ""
state_old_stack = stack.dup
stack = [stack.first]
when "::"
state_old_stack = stack.dup
stack.push(TOPLEVEL_BINDING)
when "."
next
when ".."
unless stack.size == 1
# Don't rewrite old_stack if we're in complex expression
# (e.g.: `cd 1/2/3/../4).
state_old_stack = stack.dup if path.first == ".."
stack.pop
end
when "-"
unless old_stack.empty?
# Interchange current stack and old stack with each other.
stack, state_old_stack = state_old_stack, stack
end
else
state_old_stack = stack.dup if i == 0
stack.push(Pry.binding_for(stack.last.eval(context)))
end
rescue RescuableException => e
# Restore old stack to its initial values.
state_old_stack = old_stack
msg = [
"Bad object path: #{arg_string}.",
"Failed trying to resolve: #{context}.",
e.inspect
].join(' ')
CommandError.new(msg).tap do |err|
err.set_backtrace e.backtrace
raise err
end
end
end
return stack, state_old_stack
end
end
end
end

View file

@ -31,13 +31,23 @@ class Pry
:method
elsif Pry::WrappedModule.from_str(input, target)
:module
elsif target.eval("defined? #{input} ") =~ /variable|constant/
:variable_or_constant
elsif find_command(input)
:command
else
:unknown
end
rescue SyntaxError
if find_command(input)
:command
else
:unknown
end
end
def process(name)
input = args.join(" ")
input = args.join(" ").gsub(/\"/,"")
type = input_type(input, target)
code_or_doc = case type
@ -49,8 +59,12 @@ class Pry
process_method
when :module
process_module
when :variable_or_constant
process_variable_or_constant
when :command
process_command
else
command_error("method or module for '#{input}' could not be found or derived", false)
command_error("method/module/command for '#{input}' could not be found or derived", false)
end
render_output(code_or_doc, opts)
@ -79,6 +93,14 @@ class Pry
Pry::Method.from_binding(target)
end
def process_variable_or_constant
name = args.first
object = target.eval(name)
@module_object = Pry::WrappedModule(object.class)
process_module
end
def module_start_line(mod, candidate_rank=0)
if opts.present?(:'base-one')
1

View file

@ -365,7 +365,7 @@ class Pry
@indent.reset if eval_string.empty?
current_prompt = select_prompt(eval_string, target)
completion_proc = Pry::InputCompleter.build_completion_proc(target,
completion_proc = Pry::InputCompleter.build_completion_proc(target, self,
instance_eval(&custom_completions))

View file

@ -6,11 +6,11 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["John Mair (banisterfiend)", "Conrad Irwin"]
s.date = "2012-08-10"
s.date = "2012-08-13"
s.description = "An IRB alternative and runtime developer console"
s.email = ["jrmair@gmail.com", "conrad.irwin@gmail.com"]
s.executables = ["pry"]
s.files = [".document", ".gemtest", ".gitignore", ".travis.yml", ".yardopts", "CHANGELOG", "CONTRIBUTORS", "Gemfile", "LICENSE", "README.markdown", "Rakefile", "TODO", "bin/pry", "examples/example_basic.rb", "examples/example_command_override.rb", "examples/example_commands.rb", "examples/example_hooks.rb", "examples/example_image_edit.rb", "examples/example_input.rb", "examples/example_input2.rb", "examples/example_output.rb", "examples/example_print.rb", "examples/example_prompt.rb", "examples/helper.rb", "lib/pry.rb", "lib/pry/cli.rb", "lib/pry/code.rb", "lib/pry/command.rb", "lib/pry/command_set.rb", "lib/pry/commands.rb", "lib/pry/completion.rb", "lib/pry/config.rb", "lib/pry/core_extensions.rb", "lib/pry/custom_completions.rb", "lib/pry/default_commands/cd.rb", "lib/pry/default_commands/commands.rb", "lib/pry/default_commands/context.rb", "lib/pry/default_commands/easter_eggs.rb", "lib/pry/default_commands/editing.rb", "lib/pry/default_commands/find_method.rb", "lib/pry/default_commands/gems.rb", "lib/pry/default_commands/gist.rb", "lib/pry/default_commands/help.rb", "lib/pry/default_commands/hist.rb", "lib/pry/default_commands/input_and_output.rb", "lib/pry/default_commands/introspection.rb", "lib/pry/default_commands/ls.rb", "lib/pry/default_commands/misc.rb", "lib/pry/default_commands/navigating_pry.rb", "lib/pry/default_commands/whereami.rb", "lib/pry/extended_commands/experimental.rb", "lib/pry/helpers.rb", "lib/pry/helpers/base_helpers.rb", "lib/pry/helpers/command_helpers.rb", "lib/pry/helpers/documentation_helpers.rb", "lib/pry/helpers/options_helpers.rb", "lib/pry/helpers/text.rb", "lib/pry/history.rb", "lib/pry/history_array.rb", "lib/pry/hooks.rb", "lib/pry/indent.rb", "lib/pry/method.rb", "lib/pry/module_candidate.rb", "lib/pry/pager.rb", "lib/pry/plugins.rb", "lib/pry/pry_class.rb", "lib/pry/pry_instance.rb", "lib/pry/rbx_method.rb", "lib/pry/rbx_path.rb", "lib/pry/repl_file_loader.rb", "lib/pry/version.rb", "lib/pry/wrapped_module.rb", "man/pry.1", "man/pry.1.html", "man/pry.1.ronn", "pry.gemspec", "test/candidate_helper1.rb", "test/candidate_helper2.rb", "test/example_nesting.rb", "test/helper.rb", "test/test_cli.rb", "test/test_code.rb", "test/test_command.rb", "test/test_command_helpers.rb", "test/test_command_integration.rb", "test/test_command_set.rb", "test/test_completion.rb", "test/test_control_d_handler.rb", "test/test_default_commands/example.erb", "test/test_default_commands/test_cd.rb", "test/test_default_commands/test_context.rb", "test/test_default_commands/test_documentation.rb", "test/test_default_commands/test_find_method.rb", "test/test_default_commands/test_gems.rb", "test/test_default_commands/test_help.rb", "test/test_default_commands/test_input.rb", "test/test_default_commands/test_introspection.rb", "test/test_default_commands/test_ls.rb", "test/test_default_commands/test_shell.rb", "test/test_default_commands/test_show_source.rb", "test/test_exception_whitelist.rb", "test/test_history_array.rb", "test/test_hooks.rb", "test/test_indent.rb", "test/test_input_stack.rb", "test/test_method.rb", "test/test_prompt.rb", "test/test_pry.rb", "test/test_pry_defaults.rb", "test/test_pry_history.rb", "test/test_pry_output.rb", "test/test_sticky_locals.rb", "test/test_syntax_checking.rb", "test/test_wrapped_module.rb", "test/testrc", "test/testrcbad", "wiki/Customizing-pry.md", "wiki/Home.md"]
s.files = [".document", ".gemtest", ".gitignore", ".travis.yml", ".yardopts", "CHANGELOG", "CONTRIBUTORS", "Gemfile", "LICENSE", "README.markdown", "Rakefile", "TODO", "bin/pry", "examples/example_basic.rb", "examples/example_command_override.rb", "examples/example_commands.rb", "examples/example_hooks.rb", "examples/example_image_edit.rb", "examples/example_input.rb", "examples/example_input2.rb", "examples/example_output.rb", "examples/example_print.rb", "examples/example_prompt.rb", "examples/helper.rb", "lib/pry.rb", "lib/pry/cli.rb", "lib/pry/code.rb", "lib/pry/command.rb", "lib/pry/command_set.rb", "lib/pry/commands.rb", "lib/pry/commands/amend_line.rb", "lib/pry/commands/bang.rb", "lib/pry/commands/bang_pry.rb", "lib/pry/commands/cat.rb", "lib/pry/commands/cd.rb", "lib/pry/commands/easter_eggs.rb", "lib/pry/commands/edit.rb", "lib/pry/commands/edit_method.rb", "lib/pry/commands/exit.rb", "lib/pry/commands/exit_all.rb", "lib/pry/commands/exit_program.rb", "lib/pry/commands/find_method.rb", "lib/pry/commands/gem_cd.rb", "lib/pry/commands/gem_install.rb", "lib/pry/commands/gem_list.rb", "lib/pry/commands/gist.rb", "lib/pry/commands/help.rb", "lib/pry/commands/hist.rb", "lib/pry/commands/import_set.rb", "lib/pry/commands/install_command.rb", "lib/pry/commands/jump_to.rb", "lib/pry/commands/ls.rb", "lib/pry/commands/nesting.rb", "lib/pry/commands/play.rb", "lib/pry/commands/pry_backtrace.rb", "lib/pry/commands/pry_version.rb", "lib/pry/commands/raise_up.rb", "lib/pry/commands/reload_method.rb", "lib/pry/commands/reset.rb", "lib/pry/commands/ri.rb", "lib/pry/commands/save_file.rb", "lib/pry/commands/shell_command.rb", "lib/pry/commands/shell_mode.rb", "lib/pry/commands/show_command.rb", "lib/pry/commands/show_doc.rb", "lib/pry/commands/show_input.rb", "lib/pry/commands/show_source.rb", "lib/pry/commands/simple_prompt.rb", "lib/pry/commands/stat.rb", "lib/pry/commands/switch_to.rb", "lib/pry/commands/toggle_color.rb", "lib/pry/commands/whereami.rb", "lib/pry/commands/wtf.rb", "lib/pry/completion.rb", "lib/pry/config.rb", "lib/pry/core_extensions.rb", "lib/pry/custom_completions.rb", "lib/pry/helpers.rb", "lib/pry/helpers/base_helpers.rb", "lib/pry/helpers/command_helpers.rb", "lib/pry/helpers/documentation_helpers.rb", "lib/pry/helpers/module_introspection_helpers.rb", "lib/pry/helpers/options_helpers.rb", "lib/pry/helpers/text.rb", "lib/pry/history.rb", "lib/pry/history_array.rb", "lib/pry/hooks.rb", "lib/pry/indent.rb", "lib/pry/method.rb", "lib/pry/module_candidate.rb", "lib/pry/pager.rb", "lib/pry/plugins.rb", "lib/pry/pry_class.rb", "lib/pry/pry_instance.rb", "lib/pry/rbx_method.rb", "lib/pry/rbx_path.rb", "lib/pry/repl_file_loader.rb", "lib/pry/version.rb", "lib/pry/wrapped_module.rb", "man/pry.1", "man/pry.1.html", "man/pry.1.ronn", "pry.gemspec", "test/candidate_helper1.rb", "test/candidate_helper2.rb", "test/example_nesting.rb", "test/helper.rb", "test/test_cli.rb", "test/test_code.rb", "test/test_command.rb", "test/test_command_helpers.rb", "test/test_command_integration.rb", "test/test_command_set.rb", "test/test_completion.rb", "test/test_control_d_handler.rb", "test/test_default_commands/example.erb", "test/test_default_commands/test_cd.rb", "test/test_default_commands/test_context.rb", "test/test_default_commands/test_documentation.rb", "test/test_default_commands/test_find_method.rb", "test/test_default_commands/test_gems.rb", "test/test_default_commands/test_help.rb", "test/test_default_commands/test_input.rb", "test/test_default_commands/test_introspection.rb", "test/test_default_commands/test_ls.rb", "test/test_default_commands/test_shell.rb", "test/test_default_commands/test_show_source.rb", "test/test_exception_whitelist.rb", "test/test_history_array.rb", "test/test_hooks.rb", "test/test_indent.rb", "test/test_input_stack.rb", "test/test_method.rb", "test/test_prompt.rb", "test/test_pry.rb", "test/test_pry_defaults.rb", "test/test_pry_history.rb", "test/test_pry_output.rb", "test/test_sticky_locals.rb", "test/test_syntax_checking.rb", "test/test_wrapped_module.rb", "test/testrc", "test/testrcbad", "wiki/Customizing-pry.md", "wiki/Home.md"]
s.homepage = "http://pry.github.com"
s.require_paths = ["lib"]
s.rubygems_version = "1.8.24"

View file

@ -34,6 +34,18 @@ describe Pry::Code do
Pry::Code.from_file('/knalkjsdnalsd/alkjdlkq')
end.should.raise(MethodSource::SourceNotFoundError)
end
should 'check for files relative to origin pwd' do
Dir.chdir('test') do |f|
Pry::Code.from_file('test/' + File.basename(__FILE__)).code_type.should == :ruby
end
end
should 'find files that are relative to the current working directory' do
Dir.chdir('test') do |f|
Pry::Code.from_file(File.basename(__FILE__)).code_type.should == :ruby
end
end
end
describe '.from_method' do

View file

@ -619,8 +619,10 @@ describe "Pry::Command" do
mock_pry("my---test").should =~ /my-testmy-test/
end
it "should show the source of the process method" do
mock_pry("show-command my-test").should =~ /output.puts command_name/
if !mri18_and_no_real_source_location?
it "should show the source of the process method" do
mock_pry("show-source my-test").should =~ /output.puts command_name/
end
end
end

View file

@ -1,5 +1,16 @@
require 'helper'
def new_completer(bind, pry=nil)
Pry::InputCompleter.build_completion_proc(Pry.binding_for(bind), pry)
end
def completer_test(bind, pry=nil, assert_flag=true)
completer = new_completer(bind, pry)
test = proc {|symbol| completer.call(symbol[0..-2]).include?(symbol).should == assert_flag}
return proc {|*symbols| symbols.each(&test) }
end
describe Pry::InputCompleter do
before do
@ -33,30 +44,176 @@ describe Pry::InputCompleter do
it 'should complete instance variables' do
object = Object.new
# set variables in appropriate scope
object.instance_variable_set(:'@name', 'Pry')
object.class.send(:class_variable_set, :'@@number', 10)
object.instance_variables.map { |v| v.to_sym } \
.include?(:'@name').should == true
# check to see if variables are in scope
object.instance_variables.
map { |v| v.to_sym }.
include?(:'@name').should == true
object.class.class_variables.map { |v| v.to_sym } \
.include?(:'@@number').should == true
completer = Pry::InputCompleter.build_completion_proc(
Pry.binding_for(object)
)
object.class.class_variables.
map { |v| v.to_sym }.
include?(:'@@number').should == true
# Complete instance variables.
completer.call('@na').include?('@name').should == true
completer.call('@name.down').include?('@name.downcase').should == true
b = Pry.binding_for(object)
completer_test(b).call('@name', '@name.downcase')
# Complete class variables.
completer = Pry::InputCompleter.build_completion_proc(
Pry.binding_for(object.class)
)
b = Pry.binding_for(object.class)
completer_test(b).call('@@number', '@@number.class')
completer.call('@@nu').include?('@@number').should == true
completer.call('@@number.cl').include?('@@number.class').should == true
end
it 'should complete for stdlib symbols' do
o = Object.new
# Regexp
completer_test(o).call('/foo/.extend')
# Array
completer_test(o).call('[1].push')
# Hash
completer_test(o).call('{"a" => "b"}.keys')
# Proc
completer_test(o).call('{2}.call')
# Symbol
completer_test(o).call(':symbol.to_s')
# Absolute Constant
completer_test(o).call('::IndexError')
end
it 'should complete for target symbols' do
o = Object.new
# Constant
module Mod
Con = 'Constant'
module Mod2
end
end
completer_test(Mod).call('Con')
# Constants or Class Methods
completer_test(o).call('Mod::Con')
# Symbol
foo = :symbol
completer_test(o).call(':symbol')
# Variables
class << o
attr_accessor :foo
end
o.foo = 'bar'
completer_test(binding).call('o.foo')
# trailing slash
new_completer(Mod).call('Mod2/').include?('Mod2/').should == true
end
it 'should complete for arbitrary scopes' do
module Bar
@barvar = :bar
end
module Baz
@bar = Bar
@bazvar = :baz
Con = :constant
end
pry = Pry.new()
stack = pry.binding_stack
stack.push(Pry.binding_for(Baz))
stack.push(Pry.binding_for(Bar))
b = Pry.binding_for(Bar)
completer_test(b, pry).call("../@bazvar")
completer_test(b, pry).call('/Con')
end
it 'should complete for stdlib symbols' do
o = Object.new
# Regexp
completer_test(o).call('/foo/.extend')
# Array
completer_test(o).call('[1].push')
# Hash
completer_test(o).call('{"a" => "b"}.keys')
# Proc
completer_test(o).call('{2}.call')
# Symbol
completer_test(o).call(':symbol.to_s')
# Absolute Constant
completer_test(o).call('::IndexError')
end
it 'should complete for target symbols' do
o = Object.new
# Constant
module Mod
Con = 'Constant'
module Mod2
end
end
completer_test(Mod).call('Con')
# Constants or Class Methods
completer_test(o).call('Mod::Con')
# Symbol
foo = :symbol
completer_test(o).call(':symbol')
# Variables
class << o
attr_accessor :foo
end
o.foo = 'bar'
completer_test(binding).call('o.foo')
# trailing slash
new_completer(Mod).call('Mod2/').include?('Mod2/').should == true
end
it 'should complete for arbitrary scopes' do
module Bar
@barvar = :bar
end
module Baz
@bar = Bar
@bazvar = :baz
Con = :constant
end
pry = Pry.new()
stack = pry.binding_stack
stack.push(Pry.binding_for(Baz))
stack.push(Pry.binding_for(Bar))
b = Pry.binding_for(Bar)
completer_test(b, pry).call("../@bazvar")
completer_test(b, pry).call('/Con')
end
end

View file

@ -20,9 +20,9 @@ describe 'Pry::DefaultCommands::Cd' do
eval '_pry_.command_state["cd"]'
end
def old_stack
eval '_pry_.command_state["cd"].old_stack.dup'
end
# def old_stack
# eval '_pry_.command_state["cd"].old_stack.dup'
# end
end
end
@ -42,20 +42,20 @@ describe 'Pry::DefaultCommands::Cd' do
end
end
describe 'when an error was raised' do
it 'should not toggle and should keep correct stacks' do
proc {
@t.eval 'cd @'
}.should.raise(Pry::CommandError)
# describe 'when an error was raised' do
# it 'should not toggle and should keep correct stacks' do
# proc {
# @t.eval 'cd @'
# }.should.raise(Pry::CommandError)
@t.old_stack.should == []
@t.assert_binding_stack [@o]
# @t.old_stack.should == []
# @t.assert_binding_stack [@o]
@t.eval 'cd -'
@t.old_stack.should == []
@t.assert_binding_stack [@o]
end
end
# @t.eval 'cd -'
# @t.old_stack.should == []
# @t.assert_binding_stack [@o]
# end
# end
describe 'when using simple cd syntax' do
it 'should toggle' do

View file

@ -307,5 +307,35 @@ if !mri18_and_no_real_source_location?
end
end
end
describe "on commands" do
# mostly copied & modified from test_help.rb
before do
@oldset = Pry.config.commands
@set = Pry.config.commands = Pry::CommandSet.new do
import Pry::Commands
end
end
after do
Pry.config.commands = @oldset
end
it 'should display help for a specific command' do
mock_pry('show-doc ls').should =~ /Usage: ls/
end
it 'should display help for a regex command with a "listing"' do
@set.command /bar(.*)/, "Test listing", :listing => "foo" do; end
mock_pry('show-doc foo').should =~ /Test listing/
end
it 'should display help for a command with a spaces in its name' do
@set.command "command with spaces", "description of a command with spaces" do; end
mock_pry('show-doc "command with spaces"').should =~ /description of a command with spaces/
end
end
end
end

View file

@ -470,58 +470,4 @@ describe "Pry::DefaultCommands::Introspection" do
end
end
# show-command only works in implementations that support Proc#source_location
if Proc.method_defined?(:source_location)
describe "show-command" do
before do
@str_output = StringIO.new
end
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
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
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
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

@ -255,6 +255,34 @@ if !mri18_and_no_real_source_location?
end
describe "on variable or constant" do
before do
class TestHost
def hello
"hi there"
end
end
end
after do
Object.remove_const(:TestHost)
end
it "should output source of its class if variable doesn't respond to source_location" do
test_host = TestHost.new
string = mock_pry(binding,"show-source test_host","exit-all")
string.should =~ /class TestHost\n.*def hello/
end
it "should output source of its class if constant doesn't respond to source_location" do
TEST_HOST = TestHost.new
string = mock_pry(binding,"show-source TEST_HOST","exit-all")
string.should =~ /class TestHost\n.*def hello/
Object.remove_const(:TEST_HOST)
end
end
describe "on modules" do
before do
class ShowSourceTestSuperClass
@ -525,6 +553,51 @@ if !mri18_and_no_real_source_location?
end
end
end
describe "on commands" do
before do
@oldset = Pry.config.commands
@set = Pry.config.commands = Pry::CommandSet.new do
import Pry::Commands
end
end
after do
Pry.config.commands = @oldset
end
it 'should show source for an ordinary command' do
@set.command "foo", :body_of_foo do; end
string = mock_pry("show-source foo")
string.should =~ /:body_of_foo/
end
it "should output source of commands using special characters" do
@set.command "!", "Clear the input buffer" do; end
string = mock_pry("show-source !")
string.should =~ /Clear the input buffer/
end
it 'should show source for a command with spaces in its name' do
@set.command "foo bar", :body_of_foo_bar do; end
string = mock_pry("show-source \"foo bar\"")
string.should =~ /:body_of_foo_bar/
end
it 'should show source for a command by listing name' do
@set.command /foo(.*)/, :body_of_foo_bar_regex, :listing => "bar" do; end
string = mock_pry("show-source bar")
string.should =~ /:body_of_foo_bar_regex/
end
end
end
end