mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
bunch of random refactorings to different commands
This commit is contained in:
parent
dcdea09e9e
commit
4d384737a7
4 changed files with 94 additions and 43 deletions
|
@ -67,12 +67,12 @@ class Pry
|
|||
|
||||
# lookup variables and constants that are not modules
|
||||
def default_lookup
|
||||
if str !~ /\S#\S/ && target.eval("defined? #{str} ") =~ /variable|constant/
|
||||
if variable_or_constant?(str)
|
||||
obj = target.eval(str)
|
||||
|
||||
# restrict to only objects we KNOW for sure support the full API
|
||||
# Do NOT support just any object that responds to source_location
|
||||
if [::Proc, ::Method, ::UnboundMethod].any? { |o| obj.is_a?(o) }
|
||||
if sourcable_object?(obj)
|
||||
Pry::Method(obj)
|
||||
elsif !obj.is_a?(Module)
|
||||
Pry::WrappedModule(obj.class)
|
||||
|
@ -98,17 +98,39 @@ class Pry
|
|||
Pry::Method.from_str(str,target) || Pry::WrappedModule.from_str(str, target)
|
||||
end
|
||||
|
||||
sup = obj.super(super_level) if obj
|
||||
if obj && !sup
|
||||
lookup_super(obj, super_level)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sourcable_object?(obj)
|
||||
[::Proc, ::Method, ::UnboundMethod].any? { |o| obj.is_a?(o) }
|
||||
end
|
||||
|
||||
# Whether `str` represents a variable (or constant) when looked up
|
||||
# in the context of the `target` binding. This is used to
|
||||
# distinguish it from methods or expressions.
|
||||
# @param [String] str The string to lookup
|
||||
def variable_or_constant?(str)
|
||||
str !~ /\S#\S/ && target.eval("defined? #{str} ") =~ /variable|constant/
|
||||
end
|
||||
|
||||
def target_self
|
||||
target.eval('self')
|
||||
end
|
||||
|
||||
# grab the nth (`super_level`) super of `obj
|
||||
# @param [Object] obj
|
||||
# @param [Fixnum] super_level How far up the super chain to ascend.
|
||||
def lookup_super(obj, super_level)
|
||||
return nil if !obj
|
||||
|
||||
sup = obj.super(super_level)
|
||||
if !sup
|
||||
raise Pry::CommandError, "No superclass found for #{obj.wrapped}"
|
||||
else
|
||||
sup
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def target_self
|
||||
target.eval('self')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,36 +1,37 @@
|
|||
require 'forwardable'
|
||||
|
||||
class Pry
|
||||
class Command::Edit
|
||||
class MethodPatcher
|
||||
attr_accessor :method_object
|
||||
attr_accessor :target
|
||||
attr_accessor :_pry_
|
||||
extend Forwardable
|
||||
|
||||
def_delegators :@edit_context, :code_object, :target, :_pry_
|
||||
|
||||
def initialize(edit_context)
|
||||
@method_object = edit_context.code_object
|
||||
@target = edit_context.target
|
||||
@_pry_ = edit_context._pry_
|
||||
@edit_context = edit_context
|
||||
end
|
||||
|
||||
# perform the patch
|
||||
def perform_patch
|
||||
source = wrap_for_nesting(wrap_for_owner(Pry::Editor.edit_tempfile_with_content(adjusted_lines)))
|
||||
|
||||
if method_object.alias?
|
||||
if code_object.alias?
|
||||
with_method_transaction do
|
||||
_pry_.evaluate_ruby source
|
||||
Pry.binding_for(method_object.owner).eval("alias #{method_object.name} #{method_object.original_name}")
|
||||
_pry_.evaluate_ruby patched_code
|
||||
end
|
||||
else
|
||||
_pry_.evaluate_ruby source
|
||||
_pry_.evaluate_ruby patched_code
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def patched_code
|
||||
@patched_code ||= wrap(Pry::Editor.edit_tempfile_with_content(adjusted_lines))
|
||||
end
|
||||
|
||||
# The method code adjusted so that the first line is rewritten
|
||||
# so that def self.foo --> def foo
|
||||
def adjusted_lines
|
||||
lines = method_object.source.lines.to_a
|
||||
lines = code_object.source.lines.to_a
|
||||
lines[0] = definition_line_for_owner(lines.first)
|
||||
lines
|
||||
end
|
||||
|
@ -45,12 +46,13 @@ class Pry
|
|||
# @param [String] meth_name The method name before aliasing
|
||||
# @param [Module] target The owner of the method
|
||||
def with_method_transaction
|
||||
target = Pry.binding_for(method_object.owner)
|
||||
temp_name = "__pry_#{method_object.original_name}__"
|
||||
target = owner_binding
|
||||
temp_name = "__pry_#{code_object.original_name}__"
|
||||
|
||||
target.eval("alias #{temp_name} #{method_object.original_name}")
|
||||
target.eval("alias #{temp_name} #{code_object.original_name}")
|
||||
yield
|
||||
target.eval("alias #{method_object.original_name} #{temp_name}")
|
||||
target.eval("alias #{code_object.name} #{code_object.original_name}")
|
||||
target.eval("alias #{code_object.original_name} #{temp_name}")
|
||||
ensure
|
||||
target.eval("undef #{temp_name}") rescue nil
|
||||
end
|
||||
|
@ -68,13 +70,26 @@ class Pry
|
|||
# @param String The original definition line. e.g. def self.foo(bar, baz=1)
|
||||
# @return String The new definition line. e.g. def foo(bar, baz=1)
|
||||
def definition_line_for_owner(line)
|
||||
if line =~ /^def (?:.*?\.)?#{Regexp.escape(method_object.original_name)}(?=[\(\s;]|$)/
|
||||
"def #{method_object.original_name}#{$'}"
|
||||
if line =~ /^def (?:.*?\.)?#{Regexp.escape(code_object.original_name)}(?=[\(\s;]|$)/
|
||||
"def #{code_object.original_name}#{$'}"
|
||||
else
|
||||
raise CommandError, "Could not find original `def #{method_object.original_name}` line to patch."
|
||||
raise CommandError, "Could not find original `def #{code_object.original_name}` line to patch."
|
||||
end
|
||||
end
|
||||
|
||||
# Provide a binding for the `code_object`'s owner context.
|
||||
# @return [Binding]
|
||||
def owner_binding
|
||||
Pry.binding_for(code_object.owner)
|
||||
end
|
||||
|
||||
# Apply wrap_for_owner and wrap_for_nesting successively to `source`
|
||||
# @param [String] source
|
||||
# @return [String] The wrapped source.
|
||||
def wrap(source)
|
||||
wrap_for_nesting(wrap_for_owner(source))
|
||||
end
|
||||
|
||||
# Update the source code so that when it has the right owner when eval'd.
|
||||
#
|
||||
# This (combined with definition_line_for_owner) is backup for the case that
|
||||
|
@ -84,7 +99,7 @@ class Pry
|
|||
# @param [String] source The source to wrap
|
||||
# @return [String]
|
||||
def wrap_for_owner(source)
|
||||
Thread.current[:__pry_owner__] = method_object.owner
|
||||
Thread.current[:__pry_owner__] = code_object.owner
|
||||
source = "Thread.current[:__pry_owner__].class_eval do\n#{source}\nend"
|
||||
end
|
||||
|
||||
|
@ -101,7 +116,7 @@ class Pry
|
|||
# @param [String] source The source to wrap.
|
||||
# @return [String]
|
||||
def wrap_for_nesting(source)
|
||||
nesting = Pry::Code.from_file(method_object.source_file).nesting_at(method_object.source_line)
|
||||
nesting = Pry::Code.from_file(code_object.source_file).nesting_at(code_object.source_line)
|
||||
|
||||
(nesting + [source] + nesting.map{ "end" } + [""]).join("\n")
|
||||
rescue Pry::Indent::UnparseableNestingError => e
|
||||
|
|
|
@ -44,19 +44,11 @@ class Pry
|
|||
"#{@file} @ line #{@line} #{@method && @method.name_with_owner}"
|
||||
end
|
||||
|
||||
def nothing_to_do?
|
||||
opts.quiet? && (internal_binding?(target) || !code?)
|
||||
end
|
||||
|
||||
def process
|
||||
if nothing_to_do?
|
||||
return
|
||||
elsif internal_binding?(target)
|
||||
if target_self == TOPLEVEL_BINDING.eval("self")
|
||||
output.puts "At the top level."
|
||||
else
|
||||
output.puts "Inside #{Pry.view_clip(target_self)}."
|
||||
end
|
||||
handle_internal_binding
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -69,6 +61,22 @@ class Pry
|
|||
|
||||
private
|
||||
|
||||
def nothing_to_do?
|
||||
opts.quiet? && (internal_binding?(target) || !code?)
|
||||
end
|
||||
|
||||
def top_level?
|
||||
target_self == TOPLEVEL_BINDING.eval("self")
|
||||
end
|
||||
|
||||
def handle_internal_binding
|
||||
if top_level?
|
||||
output.puts "At the top level."
|
||||
else
|
||||
output.puts "Inside #{Pry.view_clip(target_self)}."
|
||||
end
|
||||
end
|
||||
|
||||
def show_method?
|
||||
args.empty? && @method && @method.source? && @method.source_range.count < 20 &&
|
||||
# These checks are needed in case of an eval with a binding and file/line
|
||||
|
|
|
@ -32,10 +32,16 @@ class Pry
|
|||
if opts.verbose?
|
||||
output.puts Pry::Code.new(_pry_.last_exception.backtrace, 0, :text).with_line_numbers.to_s
|
||||
else
|
||||
output.puts Pry::Code.new(_pry_.last_exception.backtrace.first([captures[0].size, 0.5].max * 10), 0, :text).with_line_numbers.to_s
|
||||
end
|
||||
output.puts Pry::Code.new(_pry_.last_exception.backtrace.first(size_of_backtrace), 0, :text).with_line_numbers.to_s
|
||||
end
|
||||
end
|
||||
|
||||
Pry::Commands.add_command(Pry::Command::Wtf)
|
||||
private
|
||||
|
||||
def size_of_backtrace
|
||||
[captures[0].size, 0.5].max * 10
|
||||
end
|
||||
end
|
||||
|
||||
Pry::Commands.add_command(Pry::Command::Wtf)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue