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

Merge branch 'feature/method_refactor'

Conflicts:
	CHANGELOG
	lib/pry/default_commands/introspection.rb
	pry.gemspec
This commit is contained in:
Ryan Fitzgerald 2011-10-01 17:06:11 -07:00
commit 72ed265fb1
23 changed files with 521 additions and 529 deletions

View file

@ -144,6 +144,10 @@ class Pry
end
end
# CommandErrors are caught by the REPL loop and displayed to the user. They
# indicate an exceptional condition that's fatal to the current command.
class CommandError < StandardError
end
end
require "method_source"
@ -172,6 +176,9 @@ if RUBY_PLATFORM =~ /mswin/ || RUBY_PLATFORM =~ /mingw/
end
require "pry/version"
require "pry/rbx_method"
require "pry/rbx_path"
require "pry/method"
require "pry/history_array"
require "pry/helpers"
require "pry/history"

View file

@ -9,6 +9,7 @@ class Pry
# give it a nice inspect
def VOID_VALUE.inspect() "void" end
attr_accessor :command_name
attr_accessor :output
attr_accessor :target
attr_accessor :target_self

View file

@ -11,6 +11,8 @@ class Pry
class Command < Struct.new(:name, :description, :options, :block)
def call(context, *args)
context.command_name = options[:listing]
if stub_block = options[:stub_info]
context.instance_eval(&stub_block)
else

View file

@ -21,24 +21,21 @@ class Pry
end
command "import-set", "Import a command set" do |command_set_name|
next output.puts "Provide a command set name" if command_set.nil?
raise CommandError, "Provide a command set name" if command_set.nil?
set = target.eval(arg_string)
_pry_.commands.import set
end
command "reload-method", "Reload the source file that contains the specified method" do |meth_name|
if (meth = get_method_object(meth_name, target, {})).nil?
output.puts "Invalid method name: #{meth_name}."
next
end
meth = get_method_or_raise(meth_name, target, {}, :omit_help)
if is_a_c_method?(meth)
output.puts "Error: Can't reload a C method."
elsif is_a_dynamically_defined_method?(meth)
output.puts "Error: Can't reload an eval method."
if meth.source_type == :c
raise CommandError, "Can't reload a C method."
elsif meth.dynamically_defined?
raise CommandError, "Can't reload an eval method."
else
file_name = meth.source_location.first
file_name = meth.source_file
load file_name
output.puts "Reloaded #{file_name}."
end

View file

@ -50,7 +50,7 @@ class Pry
selection = selection.to_i
if selection < 0 || selection > _pry_.binding_stack.size - 1
output.puts "Invalid binding index #{selection} - use `nesting` command to view valid indices."
raise CommandError, "Invalid binding index #{selection} - use `nesting` command to view valid indices."
else
Pry.start(_pry_.binding_stack[selection])
end
@ -137,20 +137,21 @@ class Pry
i_num = 5
end
meth_name = meth_name_from_binding(target)
meth_name = "N/A" if !meth_name
if (meth = Pry::Method.from_binding(target))
meth_name = meth.name
else
meth_name = "N/A"
end
if file =~ /(\(.*\))|<.*>/ || file == "" || file == "-e"
output.puts "Cannot find local context. Did you use `binding.pry` ?"
next
raise CommandError, "Cannot find local context. Did you use `binding.pry`?"
end
set_file_and_dir_locals(file)
output.puts "\n#{text.bold('From:')} #{file} @ line #{line_num} in #{klass}##{meth_name}:\n\n"
unless File.readable?(file)
output.puts "Cannot open #{file.inspect} for reading."
next
raise CommandError, "Cannot open #{file.inspect} for reading."
end
# This method inspired by http://rubygems.org/gems/ir_b

View file

@ -32,20 +32,19 @@ class Pry
args = [nil] if args.empty?
args.each do |method_name|
meth_name = method_name
if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
output.puts "Invalid method name: #{meth_name}. Type `show-doc --help` for help"
begin
meth = get_method_or_raise(method_name, target, opts.to_hash(true))
rescue CommandError => e
puts "\nError: #{e.message}"
next
end
doc, code_type = doc_and_code_type_for(meth)
next if !doc
next output.puts("No documentation found.") if meth.doc.nil? || meth.doc.empty?
next output.puts("No documentation found.") if doc.empty?
doc = process_comment_markup(doc, code_type)
output.puts make_header(meth, code_type, doc)
output.puts "#{text.bold("visibility: ")} #{method_visibility(meth).to_s}"
output.puts "#{text.bold("signature: ")} #{signature_for(meth)}"
doc = process_comment_markup(meth.doc, meth.source_type)
output.puts make_header(meth, doc)
output.puts "#{text.bold("visibility: ")} #{meth.visibility}"
output.puts "#{text.bold("signature: ")} #{meth.signature}"
output.puts
render_output(opts.flood?, false, doc)
doc
@ -76,26 +75,19 @@ class Pry
next if opts.help?
meth_name = args.shift
if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
output.puts "Invalid method name: #{meth_name}. Type `stat --help` for help"
next
end
meth = get_method_or_raise(args.shift, target, opts.to_hash(true))
if !is_a_c_method?(meth) && !is_a_dynamically_defined_method?(meth)
set_file_and_dir_locals(path_line_for(meth).first)
end
output.puts "Method Information:"
output.puts "--"
output.puts "Name: " + meth_name
output.puts "Owner: " + (meth.owner.to_s ? meth.owner.to_s : "Unknown")
output.puts "Visibility: " + method_visibility(meth).to_s
output.puts "Type: " + (meth.is_a?(Method) ? "Bound" : "Unbound")
output.puts "Arity: " + meth.arity.to_s
output.puts "Method Signature: " + signature_for(meth)
output.puts "Source location: " + (meth.source_location ? meth.source_location.join(":") : "Not found.")
output.puts unindent <<-EOS
Method Information:
--
Name: #{meth.name}
Owner: #{meth.owner ? meth.owner : "Unknown"}
Visibility: #{meth.visibility}
Type: #{meth.is_a?(::Method) ? "Bound" : "Unbound"}
Arity: #{meth.arity}
Method Signature: #{meth.signature}
Source Location: #{meth.source_location ? meth.source_location.join(":") : "Not found."}
EOS
end
command "gist-method", "Gist a method to github. Type `gist-method --help` for more info.", :requires_gem => "gist" do |*args|
@ -122,19 +114,16 @@ class Pry
next if opts.help?
# This needs to be extracted into its own method as it's shared
# by show-method and show-doc and stat commands
meth_name = args.shift
if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
output.puts "Invalid method name: #{meth_name}. Type `gist-method --help` for help"
next
end
meth = get_method_or_raise(args.shift, target, opts.to_hash(true))
type_map = { :ruby => "rb", :c => "c", :plain => "plain" }
if !opts.doc?
content, code_type = code_and_code_type_for(meth)
content = meth.source
code_type = meth.source_type
else
content, code_type = doc_and_code_type_for(meth)
content = meth.doc
code_type = meth.source_type
text.no_color do
content = process_comment_markup(content, code_type)
end
@ -147,44 +136,6 @@ class Pry
output.puts "Gist created at #{link}"
end
helpers do
# paraphrased from awesome_print gem
def signature_for(method)
if method.respond_to?(:parameters)
args = method.parameters.inject([]) do |arr, (type, name)|
name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
arr << case type
when :req then name.to_s
when :opt, :rest then "*#{name}"
when :block then "&#{name}"
else '?'
end
end
else
args = (1..method.arity.abs).map { |i| "arg#{i}" }
args[-1] = "*#{args[-1]}" if method.arity < 0
end
"#{method.name}(#{args.join(', ')})"
end
def method_visibility(meth)
if meth.owner.public_instance_methods.include? meth.name
:public
elsif meth.owner.protected_instance_methods.include? meth.name
:protected
elsif meth.owner.private_instance_methods.include? meth.name
:private
else
:none
end
end
end
end
end
end

View file

@ -10,9 +10,9 @@ class Pry
installer = Gem::DependencyInstaller.new :install_dir => destination
installer.install gem
rescue Errno::EACCES
output.puts "Insufficient permissions to install `#{text.green gem}`"
raise CommandError, "Insufficient permissions to install `#{text.green gem}`."
rescue Gem::GemNotFoundException
output.puts "Gem `#{text.green gem}` not found."
raise CommandError, "Gem `#{text.green gem}` not found."
else
Gem.refresh
output.puts "Gem `#{text.green gem}` installed."
@ -22,7 +22,11 @@ class Pry
command "gem-cd", "Change working directory to specified gem's directory.", :argument_required => true do |gem|
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.")
if spec
Dir.chdir(spec.full_gem_path)
else
raise CommandError, "Gem `#{gem}` not found."
end
end
command "gem-list", "List/search installed gems. (Optional parameter: a regexp to limit the search)" do |pattern|

View file

@ -33,7 +33,10 @@ class Pry
end
next if opts.h?
next output.puts "No input to amend." if eval_string.empty?
if eval_string.empty?
raise CommandError, "No input to amend."
end
replacement_line = "" if !replacement_line
input_array = eval_string.each_line.to_a
@ -77,20 +80,20 @@ class Pry
if opts.m?
meth_name = opts[:m]
if (meth = get_method_object(meth_name, target, {})).nil?
output.puts "Invalid method name: #{meth_name}."
next
end
code, _ = code_and_code_type_for(meth)
next if !code
meth = get_method_or_raise(meth_name, target, {}, :omit_help)
next unless meth.source
range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
range = (0..-2) if opts.o?
eval_string << Array(code.each_line.to_a[range]).join
eval_string << Array(meth.source.each_line.to_a[range]).join
elsif opts.f?
file_name = File.expand_path(opts[:f])
next output.puts "No such file: #{opts[:f]}" if !File.exists?(file_name)
if !File.exists?(file_name)
raise CommandError, "No such file: #{opts[:f]}"
end
text_array = File.readlines(file_name)
range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
range = (0..-2) if opts.o?
@ -98,7 +101,10 @@ class Pry
_pry_.input_stack << _pry_.input
_pry_.input = StringIO.new(Array(text_array[range]).join)
else
next output.puts "Error: no input to play command" if !args.first
if !args.first
raise CommandError, "No input to play command."
end
code = target.eval(args.first)
range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
@ -242,7 +248,11 @@ class Pry
case opts["save"]
when Range
hist_array = Array(history[opts["save"]])
next output.puts "Must provide a file name." if !args.first
if !args.first
raise CommandError, "Must provide a file name."
end
file_name = File.expand_path(args.first)
when String
hist_array = history

View file

@ -28,33 +28,33 @@ class Pry
output.puts opt
end
end
next if opts.help?
opts[:instance] = opts['instance-methods'] if opts.m?
args = [nil] if args.empty?
args.each do |method_name|
meth_name = method_name
if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
output.puts "Invalid method name: #{meth_name}. Type `show-method --help` for help"
begin
meth = get_method_or_raise(method_name, target, opts.to_hash(true))
rescue CommandError => e
puts "\nError: #{e.message}"
next
end
next unless meth.source
code, code_type = code_and_code_type_for(meth)
next if !code
output.puts make_header(meth, code_type, code)
output.puts make_header(meth)
if Pry.color
code = CodeRay.scan(code, code_type).term
code = CodeRay.scan(meth.source, meth.source_type).term
else
code = meth.source
end
start_line = false
if opts.l?
start_line = meth.source_location ? meth.source_location.last : 1
if opts.b?
start_line = 1
elsif opts.l?
start_line = meth.source_line || 1
end
start_line = opts.b? ? 1 : start_line
render_output(opts.flood?, start_line, code)
code
end
@ -84,31 +84,32 @@ class Pry
command_name = args.shift
if !command_name
output.puts "You must provide a command name."
next
raise CommandError, "You must provide a command name."
end
if find_command(command_name)
block = find_command(command_name).block
block = Pry::Method.new(find_command(command_name).block)
code, _ = code_and_code_type_for(block)
next if !code
next unless block.source
set_file_and_dir_locals(block.source_file)
output.puts make_header(block, :ruby, code)
output.puts make_header(block)
if Pry.color
code = CodeRay.scan(code, :ruby).term
code = CodeRay.scan(block.source, :ruby).term
else
code = block.source
end
start_line = false
if opts.l?
start_line = block.source_location ? block.source_location.last : 1
start_line = block.source_line || 1
end
render_output(opts.flood?, opts.l? ? block.source_location.last : false, code)
render_output(opts.flood?, opts.l? ? block.source_line : false, code)
code
else
output.puts "No such command: #{command_name}."
raise CommandError, "No such command: #{command_name}."
end
end
@ -134,7 +135,7 @@ class Pry
next if opts.h?
if [opts.ex?, opts.t?, opts.in?, !args.empty?].count(true) > 1
next output.puts "Only one of --ex, --temp, --in and FILE may be specified"
raise CommandError, "Only one of --ex, --temp, --in and FILE may be specified."
end
# edit of local code, eval'd within pry.
@ -173,21 +174,29 @@ class Pry
# edit of remote code, eval'd at top-level
else
if opts.ex?
next output.puts "No Exception found." if _pry_.last_exception.nil?
if _pry_.last_exception.nil?
raise CommandError, "No exception found."
end
ex = _pry_.last_exception
bt_index = opts[:ex].to_i
ex_file, ex_line = ex.bt_source_location_for(bt_index)
if ex_file && is_core_rbx_path?(ex_file)
file_name = rbx_convert_path_to_full(ex_file)
if ex_file && RbxPath.is_core_path?(ex_file)
file_name = RbxPath.convert_path_to_full(ex_file)
else
file_name = ex_file
end
line = ex_line
next output.puts "Exception has no associated file." if file_name.nil?
next output.puts "Cannot edit exceptions raised in REPL." if Pry.eval_path == file_name
if file_name.nil?
raise CommandError, "Exception has no associated file."
end
if Pry.eval_path == file_name
raise CommandError, "Cannot edit exceptions raised in REPL."
end
else
# break up into file:line
file_name = File.expand_path(args.first)
@ -231,32 +240,21 @@ class Pry
output.puts opt
end
end
next if opts.help?
if !Pry.config.editor
output.puts "Error: No editor set!"
output.puts "Ensure that #{text.bold("Pry.config.editor")} is set to your editor of choice."
next
raise CommandError, "No editor set!\nEnsure that #{text.bold("Pry.config.editor")} is set to your editor of choice."
end
meth_name = args.shift
meth_name, target, type = get_method_attributes(meth_name, target, opts.to_hash(true))
meth = get_method_object_from_target(meth_name, target, type)
meth = get_method_or_raise(args.shift, target, opts.to_hash(true))
if meth.nil?
output.puts "Invalid method name: #{meth_name}."
next
end
if opts.p? || meth.dynamically_defined?
lines = meth.source.lines.to_a
if opts.p? || is_a_dynamically_defined_method?(meth)
code, _ = code_and_code_type_for(meth)
lines = code.lines.to_a
if lines[0] =~ /^def [^( \n]+/
lines[0] = "def #{meth_name}#{$'}"
lines[0] = "def #{meth.name}#{$'}"
else
next output.puts "Error: Pry can only patch methods created with the `def` keyword."
raise CommandError, "Pry can only patch methods created with the `def` keyword."
end
temp_file do |f|
@ -268,11 +266,10 @@ class Pry
next
end
if is_a_c_method?(meth)
output.puts "Error: Can't edit a C method."
if meth.source_type == :c
raise CommandError, "Can't edit a C method."
else
file, line = path_line_for(meth)
set_file_and_dir_locals(file)
file, line = meth.source_file, meth.source_line
invoke_editor(file, opts["no-jump"] ? 0 : line)
silence_warnings do

View file

@ -45,11 +45,14 @@ class Pry
target = target()
OptionParser.new do |opts|
opts.banner = %{Usage: ls [OPTIONS] [VAR]\n\
opts.banner = unindent <<-EOS
Usage: ls [OPTIONS] [VAR]
List information about VAR (the current context by default).
Shows local and instance variables by default.
--
}
EOS
opts.on("-g", "--globals", "Display global variables.") do
options[:g] = true
end

View file

@ -9,7 +9,7 @@ class Pry
begin
Dir.chdir File.expand_path(dest)
rescue Errno::ENOENT
output.puts "No such directory: #{dest}"
raise CommandError, "No such directory: #{dest}"
end
else
Pry.config.system.call(output, cmd, _pry_)
@ -61,8 +61,8 @@ class Pry
start_line = (ex_line - 1) - window_size
start_line = start_line < 0 ? 0 : start_line
end_line = (ex_line - 1) + window_size
if ex_file && is_core_rbx_path?(ex_file)
file_name = rbx_convert_path_to_full(ex_file)
if ex_file && RbxPath.is_core_path?(ex_file)
file_name = RbxPath.convert_path_to_full(ex_file)
else
file_name = ex_file
end
@ -79,22 +79,22 @@ class Pry
next if opts.help?
if opts.ex?
next output.puts "No Exception or Exception has no associated file." if file_name.nil?
if file_name.nil?
raise CommandError, "No Exception or Exception has no associated file."
end
else
file_name = args.shift
end
if !file_name
output.puts "Must provide a file name."
next
raise CommandError, "Must provide a file name."
end
begin
contents, _, _ = read_between_the_lines(file_name, start_line, end_line)
contents = syntax_highlight_by_file_type_or_specified(contents, file_name, opts[:type])
rescue Errno::ENOENT
output.puts "Could not find file: #{file_name}"
next
raise CommandError, "Could not find file: #{file_name}"
end
if opts.l?

View file

@ -4,11 +4,7 @@ class Pry
Experimental = Pry::CommandSet.new do
command "reload-method", "Reload the source specifically for a method", :requires_gem => "method_reload" do |meth_name|
if (meth = get_method_object(meth_name, target, {})).nil?
output.puts "Invalid method name: #{meth_name}."
next
end
meth = get_method_or_raise(meth_name, target, {}, :omit_help)
meth.reload
end
end

View file

@ -4,7 +4,9 @@ class Pry
UserCommandAPI = Pry::CommandSet.new do
command "define-command", "Define a command in the session, use same syntax as `command` method for command API" do |arg|
next output.puts("Provide an arg!") if arg.nil?
if arg.nil?
raise CommandError, "Provide an arg!"
end
prime_string = "command #{arg_string}\n"
command_string = _pry_.r(target, prime_string)
@ -18,8 +20,13 @@ class Pry
end
command "reload-command", "Reload a command. reload-command CMD_NAME CMD_SET" do |command_name, set_name|
next output.puts "Must provide command name" if command_name.nil?
next output.puts "Must provide command set name" if set_name.nil?
if command_name.nil?
raise CommandError, "Must provide command name"
end
if set_name.nil?
raise CommandError, "Must provide command set name"
end
cmd = Pry.config.commands.commands[command_name]
file_name = cmd.block.source_location.first
@ -33,8 +40,13 @@ class Pry
end
command "edit-command", "Edit a command. edit-command CMD_NAME CMD_SET" do |command_name, set_name|
next output.puts "Must provide command name" if command_name.nil?
next output.puts "Must provide a command set name" if set_name.nil?
if command_name.nil?
raise CommandError, "Must provide command name"
end
if set_name.nil?
raise CommandError, "Must provide command set name"
end
cmd = Pry.config.commands.commands[command_name]
file_name = cmd.block.source_location.first

View file

@ -35,7 +35,7 @@ class Pry
end
def set_file_and_dir_locals(file_name)
return if !target
return if !target or !file_name
_pry_.last_file = File.expand_path(file_name)
_pry_.inject_local("_file_", _pry_.last_file, target)

View file

@ -5,15 +5,6 @@ class Pry
module_function
def meth_name_from_binding(b)
meth_name = b.eval('__method__')
if [:__script__, nil, :__binding__, :__binding_impl__].include?(meth_name)
nil
else
meth_name
end
end
# if start_line is not false then add line numbers starting with start_line
def render_output(should_flood, start_line, text, color=:blue)
if start_line
@ -27,18 +18,6 @@ class Pry
end
end
def is_a_dynamically_defined_method?(meth)
file, _ = meth.source_location
!!(file =~ /(\(.*\))|<.*>/)
end
def check_for_dynamically_defined_method(meth)
file, _ = meth.source_location
if file =~ /(\(.*\))|<.*>/ && file != Pry.eval_path
raise "Cannot retrieve source for dynamically defined method."
end
end
# Open a temp file and yield it to the block, closing it after
# @return [String] The path of the temp file
def temp_file
@ -48,225 +27,28 @@ class Pry
file.close
end
########### RBX HELPERS #############
def is_core_rbx_path?(path)
rbx? &&
path.start_with?("kernel")
end
def rbx_core?(meth)
meth.source_location &&
is_core_rbx_path?(meth.source_location.first)
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_convert_path_to_full(path)
if rvm_ruby?(Rubinius::BIN_PATH)
rbx_rvm_convert_path_to_full(path)
def get_method_or_raise(name, target, opts={}, omit_help=false)
if (meth = Pry::Method.from_str(name, target, opts))
set_file_and_dir_locals(meth.source_file)
meth
else
rbx_std_convert_path_to_full(path)
# FIXME: better/more accurate error handling
message = "Invalid method name: #{name}."
message << " Type `#{command_name} --help` for help." unless omit_help
raise CommandError, message
end
end
def rbx_rvm_convert_path_to_full(path)
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, path)
raise "Cannot find rbx core source" if !File.exists?(file_name)
file_name
end
def rbx_std_convert_path_to_full(path)
file_name = File.join(Rubinius::BIN_PATH, "..", path)
raise "Cannot find rbx core source" if !File.exists?(file_name)
file_name
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 = rbx_std_convert_path_to_full(meth.source_location.first)
start_line = meth.source_location.last
[file_name, start_line]
end
def rvm_rbx_core_path_line_for(meth)
file_name = rbx_rvm_convert_path_to_full(meth.source_location.first)
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
return nil
when :c
code = Pry::MethodInfo.info_for(meth).source
code = strip_comments_from_c_code(code)
when :ruby
if meth.source_location.first == Pry.eval_path
start_line = meth.source_location.last
# FIXME this line below needs to be refactored, WAY too
# much of a hack. We pass nothing to prompt because if
# prompt uses #inspect (or #pretty_inspect) on the context
# it can hang the session if the object being inspected on
# is enormous see: https://github.com/pry/pry/issues/245
p = Pry.new(:input => StringIO.new(Pry.line_buffer[start_line..-1].join), :prompt => proc {""}, :hooks => {}).r(target)
code = strip_leading_whitespace(p)
else
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(path_line_for(meth).first)
end
[code, code_type]
end
def doc_and_code_type_for(meth)
case code_type = code_type_for(meth)
when nil
return nil
when :c
doc = Pry::MethodInfo.info_for(meth).docstring
when :ruby
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]
end
def get_method_object(meth_name, target=nil, options={})
get_method_object_from_target(*get_method_attributes(meth_name, target, options)) rescue nil
end
def get_method_attributes(meth_name, target=nil, options={})
if meth_name
if meth_name =~ /(\S+)\#(\S+)\Z/
context, meth_name = $1, $2
target = Pry.binding_for(target.eval(context))
type = :instance
elsif meth_name =~ /(\S+)\.(\S+)\Z/
context, meth_name = $1, $2
target = Pry.binding_for(target.eval(context))
type = :singleton
elsif options["instance_methods"]
type = :instance
elsif options[:methods]
type = :singleton
else
type = nil
end
else
meth_name = meth_name_from_binding(target)
type = nil
end
[meth_name, target, type]
end
def get_method_object_from_target(meth_name, target, type=nil)
case type
when :instance
target.eval("instance_method(:#{meth_name})") rescue nil
when :singleton
target.eval("method(:#{meth_name})") rescue nil
else
get_method_object_from_target(meth_name, target, :instance) ||
get_method_object_from_target(meth_name, target, :singleton)
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)
def make_header(meth, content=meth.source)
code_type = meth.source_type
num_lines = "Number of lines: #{Pry::Helpers::Text.bold(content.each_line.count.to_s)}"
case code_type
when :ruby
file, line = path_line_for(meth)
"\n#{Pry::Helpers::Text.bold('From:')} #{file} @ line #{line}:\n#{num_lines}\n\n"
else
when :c
file = Pry::MethodInfo.info_for(meth).file
"\n#{Pry::Helpers::Text.bold('From:')} #{file} in Ruby Core (C Method):\n#{num_lines}\n\n"
end
end
def is_a_c_method?(meth)
meth.source_location.nil?
end
def should_use_pry_doc?(meth)
Pry.config.has_pry_doc && is_a_c_method?(meth)
end
def code_type_for(meth)
# only C methods
if should_use_pry_doc?(meth)
info = Pry::MethodInfo.info_for(meth)
if info && info.source
code_type = :c
else
output.puts "Cannot find C method: #{meth.name}"
code_type = nil
end
else
if is_a_c_method?(meth)
output.puts "Cannot locate this method: #{meth.name}. Try `gem install pry-doc` to get access to Ruby Core documentation."
code_type = nil
else
check_for_dynamically_defined_method(meth)
code_type = :ruby
end
end
code_type
end
def file_map
{
[".c", ".h"] => :c,
@ -357,24 +139,6 @@ class Pry
process_yardoc process_rdoc(comment, code_type)
end
# strip leading whitespace but preserve indentation
def strip_leading_whitespace(text)
return text if text.empty?
leading_spaces = text.lines.first[/^(\s+)/, 1]
text.gsub(/^#{leading_spaces}/, '')
end
def strip_leading_hash_and_whitespace_from_ruby_comments(comment)
comment = comment.dup
comment.gsub!(/\A\#+?$/, '')
comment.gsub!(/^\s*#/, '')
strip_leading_whitespace(comment)
end
def strip_comments_from_c_code(code)
code.sub(/\A\s*\/\*.*?\*\/\s*/m, '')
end
def invoke_editor(file, line)
if Pry.config.editor.respond_to?(:call)
editor_invocation = Pry.config.editor.call(file, line)

185
lib/pry/method.rb Normal file
View file

@ -0,0 +1,185 @@
class Pry
class Method
include RbxMethod if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/
class << self
def from_str(str, target=TOPLEVEL_BINDING, options={})
if str.nil?
from_binding(target)
elsif str.to_s =~ /(\S+)\#(\S+)\Z/
context, meth_name = $1, $2
from_module(target.eval(context), meth_name)
elsif str.to_s =~ /(\S+)\.(\S+)\Z/
context, meth_name = $1, $2
from_obj(target.eval(context), meth_name)
elsif options[:instance]
new(target.eval("instance_method(:#{str})")) rescue nil
elsif options[:methods]
new(target.eval("method(:#{str})")) rescue nil
else
from_str(str, target, :instance => true) or
from_str(str, target, :methods => true) or
raise CommandError, "Method #{str} could not be found."
end
end
def from_binding(b)
meth_name = b.eval('__method__')
if [:__script__, nil, :__binding__, :__binding_impl__].include?(meth_name)
nil
else
new(b.eval("method(:#{meth_name})"))
end
end
def from_module(nodule, name)
new(nodule.instance_method(name)) rescue nil
end
alias from_class from_module
def from_obj(obj, name)
new(obj.method(name)) rescue nil
end
end
def initialize(method)
@method = method
end
def source
@source ||= case source_type
when :c
info = pry_doc_info
if info and info.source
code = strip_comments_from_c_code(info.source)
end
when :rbx
strip_leading_whitespace(core_code)
when :ruby
if pry_method?
code = Pry.new(:input => StringIO.new(Pry.line_buffer[source_line..-1].join), :prompt => proc {""}, :hooks => {}).r
else
code = @method.source
end
strip_leading_whitespace(code)
end
end
def doc
@doc ||= case source_type
when :c
info = pry_doc_info
info.docstring if info
when :rbx
strip_leading_hash_and_whitespace_from_ruby_comments(core_doc)
when :ruby
if pry_method?
raise CommandError, "Can't view doc for a REPL-defined method."
else
strip_leading_hash_and_whitespace_from_ruby_comments(@method.comment)
end
end
end
def source_type
if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/
if core? then :rbx else :ruby end
else
if source_location.nil? then :c else :ruby end
end
end
def source_file
source_location.nil? ? nil : source_location.first
end
def source_line
source_location.nil? ? nil : source_location.last
end
def visibility
if owner.public_instance_methods.include?(name)
:public
elsif owner.protected_instance_methods.include?(name)
:protected
elsif owner.private_instance_methods.include?(name)
:private
else
:none
end
end
# paraphrased from awesome_print gem
def signature
if respond_to?(:parameters)
args = parameters.inject([]) do |arr, (type, name)|
name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
arr << case type
when :req then name.to_s
when :opt, :rest then "*#{name}"
when :block then "&#{name}"
else '?'
end
end
else
args = (1..arity.abs).map { |i| "arg#{i}" }
args[-1] = "*#{args[-1]}" if arity < 0
end
"#{name}(#{args.join(', ')})"
end
def dynamically_defined?
source_file ? !!(source_file =~ /(\(.*\))|<.*>/) : nil
end
def pry_method?
source_file == Pry.eval_path
end
def ==(obj)
if obj.is_a? Pry::Method
super
else
@method == obj
end
end
def is_a?(klass)
klass == Pry::Method or @method.is_a?(klass)
end
alias kind_of? is_a?
def respond_to?(method_name)
super or @method.respond_to?(method_name)
end
def method_missing(method_name, *args, &block)
@method.send(method_name, *args, &block)
end
private
def pry_doc_info
if Pry.config.has_pry_doc
Pry::MethodInfo.info_for(@method) or raise CommandError, "Cannot find C method: #{name}."
else
raise CommandError, "Cannot locate this method: #{name}. Try `gem install pry-doc` to get access to Ruby Core documentation."
end
end
def strip_comments_from_c_code(code)
code.sub(/\A\s*\/\*.*?\*\/\s*/m, '')
end
def strip_leading_hash_and_whitespace_from_ruby_comments(comment)
comment = comment.dup
comment.gsub!(/\A\#+?$/, '')
comment.gsub!(/^\s*#/, '')
strip_leading_whitespace(comment)
end
def strip_leading_whitespace(text)
Pry::Helpers::CommandHelpers.unindent(text)
end
end
end

View file

@ -219,6 +219,9 @@ class Pry
result = set_last_result(target.eval(code, Pry.eval_path, Pry.current_line), target)
result
rescue CommandError => e
output.puts "Error: #{e.message}"
@suppress_output = true
rescue RescuableException => e
set_last_exception(e, target)
ensure

20
lib/pry/rbx_method.rb Normal file
View file

@ -0,0 +1,20 @@
class Pry
module RbxMethod
private
def core?
source_file and RbxPath.is_core_path?(source_file)
end
def core_code
MethodSource.source_helper(core_path_line)
end
def core_doc
MethodSource.comment_helper(core_path_line)
end
def core_path_line
[RbxPath.convert_path_to_full(source_file), source_line]
end
end
end

34
lib/pry/rbx_path.rb Normal file
View file

@ -0,0 +1,34 @@
class Pry
module RbxPath
module_function
def is_core_path?(path)
path.start_with?("kernel")
end
def convert_path_to_full(path)
if rvm_ruby?(Rubinius::BIN_PATH)
rvm_convert_path_to_full(path)
else
std_convert_path_to_full(path)
end
end
def rvm_ruby?(path)
!!(path =~ /\.rvm/)
end
def rvm_convert_path_to_full(path)
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, path)
raise "Cannot find rbx core source" if !File.exists?(file_name)
file_name
end
def std_convert_path_to_full(path)
file_name = File.join(Rubinius::BIN_PATH, "..", path)
raise "Cannot find rbx core source" if !File.exists?(file_name)
file_name
end
end
end

View file

@ -6,16 +6,16 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = [%q{John Mair (banisterfiend)}]
s.date = %q{2011-09-27}
s.date = %q{2011-10-01}
s.description = %q{An IRB alternative and runtime developer console}
s.email = %q{jrmair@gmail.com}
s.executables = [%q{pry}]
s.files = [%q{.document}, %q{.gemtest}, %q{.gitignore}, %q{.travis.yml}, %q{.yardopts}, %q{CHANGELOG}, %q{CONTRIBUTORS}, %q{Gemfile}, %q{LICENSE}, %q{README.markdown}, %q{Rakefile}, %q{TODO}, %q{bin/pry}, %q{examples/example_basic.rb}, %q{examples/example_command_override.rb}, %q{examples/example_commands.rb}, %q{examples/example_hooks.rb}, %q{examples/example_image_edit.rb}, %q{examples/example_input.rb}, %q{examples/example_input2.rb}, %q{examples/example_output.rb}, %q{examples/example_print.rb}, %q{examples/example_prompt.rb}, %q{examples/helper.rb}, %q{lib/pry.rb}, %q{lib/pry/command_context.rb}, %q{lib/pry/command_processor.rb}, %q{lib/pry/command_set.rb}, %q{lib/pry/commands.rb}, %q{lib/pry/completion.rb}, %q{lib/pry/config.rb}, %q{lib/pry/core_extensions.rb}, %q{lib/pry/custom_completions.rb}, %q{lib/pry/default_commands/basic.rb}, %q{lib/pry/default_commands/context.rb}, %q{lib/pry/default_commands/documentation.rb}, %q{lib/pry/default_commands/easter_eggs.rb}, %q{lib/pry/default_commands/gems.rb}, %q{lib/pry/default_commands/input.rb}, %q{lib/pry/default_commands/introspection.rb}, %q{lib/pry/default_commands/ls.rb}, %q{lib/pry/default_commands/shell.rb}, %q{lib/pry/extended_commands/experimental.rb}, %q{lib/pry/extended_commands/user_command_api.rb}, %q{lib/pry/helpers.rb}, %q{lib/pry/helpers/base_helpers.rb}, %q{lib/pry/helpers/command_helpers.rb}, %q{lib/pry/helpers/text.rb}, %q{lib/pry/history.rb}, %q{lib/pry/history_array.rb}, %q{lib/pry/plugins.rb}, %q{lib/pry/pry_class.rb}, %q{lib/pry/pry_instance.rb}, %q{lib/pry/version.rb}, %q{pry.gemspec}, %q{test/helper.rb}, %q{test/test_command_helpers.rb}, %q{test/test_command_processor.rb}, %q{test/test_command_set.rb}, %q{test/test_completion.rb}, %q{test/test_default_commands.rb}, %q{test/test_default_commands/test_context.rb}, %q{test/test_default_commands/test_documentation.rb}, %q{test/test_default_commands/test_gems.rb}, %q{test/test_default_commands/test_input.rb}, %q{test/test_default_commands/test_introspection.rb}, %q{test/test_default_commands/test_shell.rb}, %q{test/test_exception_whitelist.rb}, %q{test/test_history_array.rb}, %q{test/test_input_stack.rb}, %q{test/test_pry.rb}, %q{test/test_pry_history.rb}, %q{test/test_pry_output.rb}, %q{test/test_special_locals.rb}, %q{test/testrc}, %q{wiki/Customizing-pry.md}, %q{wiki/Home.md}]
s.files = [%q{.document}, %q{.gemtest}, %q{.gitignore}, %q{.travis.yml}, %q{.yardopts}, %q{CHANGELOG}, %q{CONTRIBUTORS}, %q{Gemfile}, %q{LICENSE}, %q{README.markdown}, %q{Rakefile}, %q{TODO}, %q{bin/pry}, %q{examples/example_basic.rb}, %q{examples/example_command_override.rb}, %q{examples/example_commands.rb}, %q{examples/example_hooks.rb}, %q{examples/example_image_edit.rb}, %q{examples/example_input.rb}, %q{examples/example_input2.rb}, %q{examples/example_output.rb}, %q{examples/example_print.rb}, %q{examples/example_prompt.rb}, %q{examples/helper.rb}, %q{lib/pry.rb}, %q{lib/pry/command_context.rb}, %q{lib/pry/command_processor.rb}, %q{lib/pry/command_set.rb}, %q{lib/pry/commands.rb}, %q{lib/pry/completion.rb}, %q{lib/pry/config.rb}, %q{lib/pry/core_extensions.rb}, %q{lib/pry/custom_completions.rb}, %q{lib/pry/default_commands/basic.rb}, %q{lib/pry/default_commands/context.rb}, %q{lib/pry/default_commands/documentation.rb}, %q{lib/pry/default_commands/easter_eggs.rb}, %q{lib/pry/default_commands/gems.rb}, %q{lib/pry/default_commands/input.rb}, %q{lib/pry/default_commands/introspection.rb}, %q{lib/pry/default_commands/ls.rb}, %q{lib/pry/default_commands/shell.rb}, %q{lib/pry/extended_commands/experimental.rb}, %q{lib/pry/extended_commands/user_command_api.rb}, %q{lib/pry/helpers.rb}, %q{lib/pry/helpers/base_helpers.rb}, %q{lib/pry/helpers/command_helpers.rb}, %q{lib/pry/helpers/text.rb}, %q{lib/pry/history.rb}, %q{lib/pry/history_array.rb}, %q{lib/pry/method.rb}, %q{lib/pry/plugins.rb}, %q{lib/pry/pry_class.rb}, %q{lib/pry/pry_instance.rb}, %q{lib/pry/rbx_method.rb}, %q{lib/pry/rbx_path.rb}, %q{lib/pry/version.rb}, %q{pry.gemspec}, %q{test/helper.rb}, %q{test/test_command_helpers.rb}, %q{test/test_command_processor.rb}, %q{test/test_command_set.rb}, %q{test/test_completion.rb}, %q{test/test_default_commands.rb}, %q{test/test_default_commands/test_context.rb}, %q{test/test_default_commands/test_documentation.rb}, %q{test/test_default_commands/test_gems.rb}, %q{test/test_default_commands/test_input.rb}, %q{test/test_default_commands/test_introspection.rb}, %q{test/test_default_commands/test_shell.rb}, %q{test/test_exception_whitelist.rb}, %q{test/test_history_array.rb}, %q{test/test_input_stack.rb}, %q{test/test_method.rb}, %q{test/test_pry.rb}, %q{test/test_pry_history.rb}, %q{test/test_pry_output.rb}, %q{test/test_special_locals.rb}, %q{test/testrc}, %q{wiki/Customizing-pry.md}, %q{wiki/Home.md}]
s.homepage = %q{http://pry.github.com}
s.require_paths = [%q{lib}]
s.rubygems_version = %q{1.8.6}
s.summary = %q{An IRB alternative and runtime developer console}
s.test_files = [%q{test/helper.rb}, %q{test/test_command_helpers.rb}, %q{test/test_command_processor.rb}, %q{test/test_command_set.rb}, %q{test/test_completion.rb}, %q{test/test_default_commands.rb}, %q{test/test_default_commands/test_context.rb}, %q{test/test_default_commands/test_documentation.rb}, %q{test/test_default_commands/test_gems.rb}, %q{test/test_default_commands/test_input.rb}, %q{test/test_default_commands/test_introspection.rb}, %q{test/test_default_commands/test_shell.rb}, %q{test/test_exception_whitelist.rb}, %q{test/test_history_array.rb}, %q{test/test_input_stack.rb}, %q{test/test_pry.rb}, %q{test/test_pry_history.rb}, %q{test/test_pry_output.rb}, %q{test/test_special_locals.rb}, %q{test/testrc}]
s.test_files = [%q{test/helper.rb}, %q{test/test_command_helpers.rb}, %q{test/test_command_processor.rb}, %q{test/test_command_set.rb}, %q{test/test_completion.rb}, %q{test/test_default_commands.rb}, %q{test/test_default_commands/test_context.rb}, %q{test/test_default_commands/test_documentation.rb}, %q{test/test_default_commands/test_gems.rb}, %q{test/test_default_commands/test_input.rb}, %q{test/test_default_commands/test_introspection.rb}, %q{test/test_default_commands/test_shell.rb}, %q{test/test_exception_whitelist.rb}, %q{test/test_history_array.rb}, %q{test/test_input_stack.rb}, %q{test/test_method.rb}, %q{test/test_pry.rb}, %q{test/test_pry_history.rb}, %q{test/test_pry_output.rb}, %q{test/test_special_locals.rb}, %q{test/testrc}]
if s.respond_to? :specification_version then
s.specification_version = 3

View file

@ -5,73 +5,5 @@ describe Pry::Helpers::CommandHelpers do
@helper = Pry::Helpers::CommandHelpers
end
describe "get_method_object" do
it 'should look up instance methods if no methods available and no options provided' do
klass = Class.new { def hello; end }
meth = @helper.get_method_object(:hello, Pry.binding_for(klass), {})
meth.should == klass.instance_method(:hello)
# FIXME: currently no tests
end
it 'should look up methods if no instance methods available and no options provided' do
klass = Class.new { def self.hello; end }
meth = @helper.get_method_object(:hello, Pry.binding_for(klass), {})
meth.should == klass.method(:hello)
end
it 'should look up instance methods first even if methods available and no options provided' do
klass = Class.new { def hello; end; def self.hello; end }
meth = @helper.get_method_object(:hello, Pry.binding_for(klass), {})
meth.should == klass.instance_method(:hello)
end
it 'should look up instance methods if "instance-methods" option provided' do
klass = Class.new { def hello; end; def self.hello; end }
meth = @helper.get_method_object(:hello, Pry.binding_for(klass), {"instance-methods" => true})
meth.should == klass.instance_method(:hello)
end
it 'should look up methods if :methods option provided' do
klass = Class.new { def hello; end; def self.hello; end }
meth = @helper.get_method_object(:hello, Pry.binding_for(klass), {:methods => true})
meth.should == klass.method(:hello)
end
it 'should look up instance methods using the Class#method syntax' do
klass = Class.new { def hello; end; def self.hello; end }
meth = @helper.get_method_object("klass#hello", Pry.binding_for(binding), {})
meth.should == klass.instance_method(:hello)
end
it 'should look up methods using the object.method syntax' do
klass = Class.new { def hello; end; def self.hello; end }
meth = @helper.get_method_object("klass.hello", Pry.binding_for(binding), {})
meth.should == klass.method(:hello)
end
it 'should NOT look up instance methods using the Class#method syntax if no instance methods defined' do
klass = Class.new { def self.hello; end }
meth = @helper.get_method_object("klass#hello", Pry.binding_for(binding), {})
meth.should == nil
end
it 'should NOT look up methods using the object.method syntax if no methods defined' do
klass = Class.new { def hello; end }
meth = @helper.get_method_object("klass.hello", Pry.binding_for(binding), {})
meth.should == nil
end
it 'should look up methods using klass.new.method syntax' do
klass = Class.new { def hello; :hello; end }
meth = @helper.get_method_object("klass.new.hello", Pry.binding_for(binding), {})
meth.name.to_sym.should == :hello
end
it 'should look up instance methods using klass.meth#method syntax' do
klass = Class.new { def self.meth; Class.new; end }
meth = @helper.get_method_object("klass.meth#initialize", Pry.binding_for(binding), {})
meth.name.to_sym.should == :initialize
end
end
end

View file

@ -3,6 +3,7 @@ require 'helper'
describe Pry::CommandSet do
before do
@set = Pry::CommandSet.new
@ctx = Pry::CommandContext.new
end
it 'should call the block used for the command when it is called' do
@ -11,7 +12,7 @@ describe Pry::CommandSet do
run = true
end
@set.run_command nil, 'foo'
@set.run_command @ctx, 'foo'
run.should == true
end
@ -20,21 +21,23 @@ describe Pry::CommandSet do
args.should == [1, 2, 3]
end
@set.run_command nil, 'foo', 1, 2, 3
@set.run_command @ctx, 'foo', 1, 2, 3
end
it 'should use the first argument as self' do
ctx = @ctx
@set.command 'foo' do
self.should == true
self.should == ctx
end
@set.run_command true, 'foo'
@set.run_command @ctx, 'foo'
end
it 'should raise an error when calling an undefined command' do
@set.command('foo') {}
lambda {
@set.run_command nil, 'bar'
@set.run_command @ctx, 'bar'
}.should.raise(Pry::NoCommandError)
end
@ -43,7 +46,7 @@ describe Pry::CommandSet do
@set.delete 'foo'
lambda {
@set.run_command nil, 'foo'
@set.run_command @ctx, 'foo'
}.should.raise(Pry::NoCommandError)
end
@ -57,11 +60,11 @@ describe Pry::CommandSet do
@set.import_from(other_set, 'foo')
@set.run_command nil, 'foo'
@set.run_command @ctx, 'foo'
run.should == true
lambda {
@set.run_command nil, 'bar'
@set.run_command @ctx, 'bar'
}.should.raise(Pry::NoCommandError)
end
@ -75,8 +78,8 @@ describe Pry::CommandSet do
@set.import other_set
@set.run_command nil, 'foo'
@set.run_command nil, 'bar'
@set.run_command @ctx, 'foo'
@set.run_command @ctx, 'bar'
run.should == [true, true]
end
@ -84,7 +87,7 @@ describe Pry::CommandSet do
run = false
@set.command('foo') { run = true }
Pry::CommandSet.new(@set).run_command nil, 'foo'
Pry::CommandSet.new(@set).run_command @ctx, 'foo'
run.should == true
end
@ -101,7 +104,7 @@ describe Pry::CommandSet do
@set.commands['bar'].name.should == 'bar'
@set.commands['bar'].description.should == ''
@set.run_command nil, 'bar'
@set.run_command @ctx, 'bar'
run.should == true
end
@ -114,17 +117,17 @@ describe Pry::CommandSet do
it 'should return Pry::CommandContext::VOID_VALUE for commands by default' do
@set.command('foo') { 3 }
@set.run_command(nil, 'foo').should == Pry::CommandContext::VOID_VALUE
@set.run_command(@ctx, 'foo').should == Pry::CommandContext::VOID_VALUE
end
it 'should be able to keep return values' do
@set.command('foo', '', :keep_retval => true) { 3 }
@set.run_command(nil, 'foo').should == 3
@set.run_command(@ctx, 'foo').should == 3
end
it 'should be able to keep return values, even if return value is nil' do
@set.command('foo', '', :keep_retval => true) { nil }
@set.run_command(nil, 'foo').should == nil
@set.run_command(@ctx, 'foo').should == nil
end
it 'should be able to have its own helpers' do
@ -136,7 +139,7 @@ describe Pry::CommandSet do
def my_helper; end
end
@set.run_command(Pry::CommandContext.new, 'foo')
@set.run_command(@ctx, 'foo')
Pry::CommandContext.new.should.not.respond_to :my_helper
end
@ -154,7 +157,7 @@ describe Pry::CommandSet do
def my_other_helper; end
end
@set.run_command(Pry::CommandContext.new, 'foo')
@set.run_command(@ctx, 'foo')
end
it 'should import helpers from imported sets' do
@ -166,7 +169,7 @@ describe Pry::CommandSet do
@set.import imported_set
@set.command('foo') { should.respond_to :imported_helper_method }
@set.run_command(Pry::CommandContext.new, 'foo')
@set.run_command(@ctx, 'foo')
end
it 'should import helpers even if only some commands are imported' do
@ -180,7 +183,7 @@ describe Pry::CommandSet do
@set.import_from imported_set, 'bar'
@set.command('foo') { should.respond_to :imported_helper_method }
@set.run_command(Pry::CommandContext.new, 'foo')
@set.run_command(@ctx, 'foo')
end
it 'should provide a :listing for a command that defaults to its name' do
@ -194,12 +197,11 @@ describe Pry::CommandSet do
end
it "should provide a 'help' command" do
context = Pry::CommandContext.new
context.command_set = @set
context.output = StringIO.new
@ctx.command_set = @set
@ctx.output = StringIO.new
lambda {
@set.run_command(context, 'help')
@set.run_command(@ctx, 'help')
}.should.not.raise
end
@ -209,13 +211,12 @@ describe Pry::CommandSet do
@set.command 'moo', "Mooerizes" do; end
@set.command 'boo', "Booerizes" do; end
context = Pry::CommandContext.new
context.command_set = @set
context.output = StringIO.new
@ctx.command_set = @set
@ctx.output = StringIO.new
@set.run_command(context, 'help')
@set.run_command(@ctx, 'help')
doc = context.output.string
doc = @ctx.output.string
order = [doc.index("boo"),
doc.index("foo"),

72
test/test_method.rb Normal file
View file

@ -0,0 +1,72 @@
require 'helper'
describe Pry::Method do
describe ".from_str" do
it 'should look up instance methods if no methods available and no options provided' do
klass = Class.new { def hello; end }
meth = Pry::Method.from_str(:hello, Pry.binding_for(klass))
meth.should == klass.instance_method(:hello)
end
it 'should look up methods if no instance methods available and no options provided' do
klass = Class.new { def self.hello; end }
meth = Pry::Method.from_str(:hello, Pry.binding_for(klass))
meth.should == klass.method(:hello)
end
it 'should look up instance methods first even if methods available and no options provided' do
klass = Class.new { def hello; end; def self.hello; end }
meth = Pry::Method.from_str(:hello, Pry.binding_for(klass))
meth.should == klass.instance_method(:hello)
end
it 'should look up instance methods if "instance-methods" option provided' do
klass = Class.new { def hello; end; def self.hello; end }
meth = Pry::Method.from_str(:hello, Pry.binding_for(klass), {"instance-methods" => true})
meth.should == klass.instance_method(:hello)
end
it 'should look up methods if :methods option provided' do
klass = Class.new { def hello; end; def self.hello; end }
meth = Pry::Method.from_str(:hello, Pry.binding_for(klass), {:methods => true})
meth.should == klass.method(:hello)
end
it 'should look up instance methods using the Class#method syntax' do
klass = Class.new { def hello; end; def self.hello; end }
meth = Pry::Method.from_str("klass#hello", Pry.binding_for(binding))
meth.should == klass.instance_method(:hello)
end
it 'should look up methods using the object.method syntax' do
klass = Class.new { def hello; end; def self.hello; end }
meth = Pry::Method.from_str("klass.hello", Pry.binding_for(binding))
meth.should == klass.method(:hello)
end
it 'should NOT look up instance methods using the Class#method syntax if no instance methods defined' do
klass = Class.new { def self.hello; end }
meth = Pry::Method.from_str("klass#hello", Pry.binding_for(binding))
meth.should == nil
end
it 'should NOT look up methods using the object.method syntax if no methods defined' do
klass = Class.new { def hello; end }
meth = Pry::Method.from_str("klass.hello", Pry.binding_for(binding))
meth.should == nil
end
it 'should look up methods using klass.new.method syntax' do
klass = Class.new { def hello; :hello; end }
meth = Pry::Method.from_str("klass.new.hello", Pry.binding_for(binding))
meth.name.to_sym.should == :hello
end
it 'should look up instance methods using klass.meth#method syntax' do
klass = Class.new { def self.meth; Class.new; end }
meth = Pry::Method.from_str("klass.meth#initialize", Pry.binding_for(binding))
meth.name.to_sym.should == :initialize
end
end
end