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:
commit
72ed265fb1
23 changed files with 521 additions and 529 deletions
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
185
lib/pry/method.rb
Normal 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
|
|
@ -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
20
lib/pry/rbx_method.rb
Normal 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
34
lib/pry/rbx_path.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
72
test/test_method.rb
Normal 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
|
||||
|
Loading…
Reference in a new issue