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 :m, :methods, "Operate on methods."
opt.on :n, "no-reload", "Do not automatically reload the method's file after editing." 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 "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| opt.on :c, :context, "Select object context to run under.", true do |context|
target = Pry.binding_for(target.eval(context)) target = Pry.binding_for(target.eval(context))
end end
@ -213,20 +214,42 @@ class Pry
next if opts.help? 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 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}." output.puts "Invalid method name: #{meth_name}."
next next
end 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) if is_a_c_method?(meth)
output.puts "Error: Can't edit a C method." 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 else
file, line = path_line_for(meth) file, line = path_line_for(meth)
set_file_and_dir_locals(file) set_file_and_dir_locals(file)

View file

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