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:
parent
078594ba83
commit
f19e6a9073
2 changed files with 51 additions and 22 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue