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

implement edit-method -p

This commit is contained in:
Ryan Fitzgerald 2011-09-09 00:31:56 -07:00
parent 078594ba83
commit f19e6a9073
2 changed files with 51 additions and 22 deletions

View file

@ -203,6 +203,7 @@ class Pry
opt.on :m, :methods, "Operate on methods."
opt.on :n, "no-reload", "Do not automatically reload the method's file after editing."
opt.on "no-jump", "Do not fast forward editor to first line of method."
opt.on :p, :patch, "Instead of editing the method's file, try to edit in a tempfile and apply as a monkey patch."
opt.on :c, :context, "Select object context to run under.", true do |context|
target = Pry.binding_for(target.eval(context))
end
@ -213,20 +214,42 @@ class Pry
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
end
meth_name = args.shift
if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
meth_name, target, type = get_method_attributes(meth_name, target, opts.to_hash(true))
meth = get_method_object_from_target(meth_name, target, type)
if meth.nil?
output.puts "Invalid method name: #{meth_name}."
next
end
next output.puts "Error: No editor set!\nEnsure that #{text.bold("Pry.config.editor")} is set to your editor of choice." if !Pry.config.editor
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}#{$'}"
else
next output.puts "Error: Pry can only patch methods created with the `def` keyword."
end
temp_file do |f|
f.puts lines.join
f.flush
invoke_editor(f.path, 0)
Pry.new(:input => StringIO.new(File.read(f.path))).rep(meth.owner)
end
next
end
if is_a_c_method?(meth)
output.puts "Error: Can't edit a C method."
elsif is_a_dynamically_defined_method?(meth)
output.puts "Error: Can't edit an eval method."
# editor is invoked here
else
file, line = path_line_for(meth)
set_file_and_dir_locals(file)

View file

@ -178,37 +178,43 @@ class Pry
[doc, code_type]
end
def get_method_object(meth_name, target, options)
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))
options["instance-methods"] = true
options[:methods] = false
type = :instance
elsif meth_name =~ /(\S+)\.(\S+)\Z/
context, meth_name = $1, $2
target = Pry.binding_for(target.eval(context))
options["instance-methods"] = false
options[:methods] = true
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
if !meth_name
return nil
end
if options["instance-methods"]
def get_method_object_from_target(meth_name, target, type=nil)
case type
when :instance
target.eval("instance_method(:#{meth_name})") rescue nil
elsif options[:methods]
when :singleton
target.eval("method(:#{meth_name})") rescue nil
else
begin
target.eval("instance_method(:#{meth_name})")
rescue
target.eval("method(:#{meth_name})") rescue nil
end
get_method_object_from_target(meth_name, target, :instance) ||
get_method_object_from_target(meth_name, target, :singleton)
end
end