Skip to content

Instantly share code, notes, and snippets.

@betawaffle
Created October 25, 2011 00:56
Show Gist options
  • Save betawaffle/1310983 to your computer and use it in GitHub Desktop.
Save betawaffle/1310983 to your computer and use it in GitHub Desktop.
Pry Helpers
Pry.config.should_load_plugins = false
Pry.config.editor = proc { |file, line| "subl -w #{file}:#{line}" }
Pry.prompt = [
proc { |obj, nest_level| "#{RUBY_VERSION} (#{obj}):#{nest_level} > " },
proc { |obj, nest_level| "#{RUBY_VERSION} (#{obj}):#{nest_level} * " }
]
Pry.plugins['doc'].activate!
class BasicObject
def send_and_pry(symbol, *args)
$step = true
called = 0
tracer = lambda do |event, file, line, id, scope, klass|
if id == symbol
called += 1 if event == 'call'
called -= 1 if event == 'return'
end
return unless called > 0
return unless $step == true or $step == event
$step = nil
scope.eval("_ev_ = '#{event}'")
scope.pry
end
set_trace_func tracer
begin
ret = __send__ symbol, *args
ensure
set_trace_func nil
end
ret
end
end
class Binding
def fake(file, line)
orig = method(:eval)
define_singleton_method(:eval) do |s, f = nil, l = nil|
orig.call(s, f || file.to_s, l || line.to_i)
end
self
end
def fake_class(name)
orig = method(:eval)
define_singleton_method(:eval) do |s, f = nil, l = nil|
case s
when 'self.class'
name.to_s
else
orig.call(s, f, l)
end
end
self
end
def fake_method(name)
orig = method(:eval)
define_singleton_method(:eval) do |s, f = nil, l = nil|
case s
when '__method__'
name.to_s
else
orig.call(s, f, l)
end
end
self
end
end
Pry.commands.command('show-ex', "Show the context for the last exception") do |num|
if ex = target.eval('_ex_')
file, line, _ = ex.backtrace.first.split(':', 3)
fake = Pry.binding_for(ex).fake(file, line)
Pry.run_command("whereami #{num}", :context => fake)
end
end
Pry.commands.command('step', "Step though execution") do |event|
$step = event ? event : true
run 'exit'
end
# Point these to the actual file locations
require 'pry-meta.rb'
require 'pry-bench.rb'
require 'pry-debug.rb'
require 'pry-helpers.rb'
require 'benchmark'
include Benchmark
require 'ruby-debug'
include Debugger
def init_require_hooks
Kernel.module_eval do
alias_method :__require, :require
class << self
def require(file)
__require(file).tap { after_require(file) }
end
def after_require(file, &block)
return unless file.to_s[0] != '/'
hook = :"required_#{file.gsub('/', '_')}"
if block_given?
define_method(hook, &block)
elsif respond_to? hook
send hook
remove_method hook
end
end
end
end
def require(file)
__require(file).tap { Kernel.after_require(file) }
end
end
Kernel.instance_eval do
def after_require(file, &block)
init_require_hooks
after_require(file, &block)
end
end
def load_rails
environment = File.join(Dir.getwd, 'config', 'environment.rb')
return false unless File.exist? environment
Kernel.after_require('rails') do
puts "Rails Loaded"
init_rails_hooks
yield if block_given?
end
require environment
Rails.logger = Logger.new($stdout)
case Rails.version[0..0]
when '2'
require 'console_app'
require 'console_with_helpers'
when '3'
require 'rails/console/app'
require 'rails/console/helpers'
else
warn "Couldn't load Rails console commands."
end
load_hirb
end
alias :rails :load_rails
def init_rails_hooks
orig = Rails::Application.method(:inherited)
base = class << Rails::Application; self; end
base.instance_eval do
define_method(:__inherited, orig)
remove_method(:inherited)
define_method(:inherited) do |sub|
__inherited(sub)
puts "Rails Application Created"
file, line, _ = caller.first.split(':', 3)
Pry.binding_for(sub).fake(file, line).pry
end
end
end
def load_hirb
begin
require 'hirb'
rescue LoadError
# Missing goodies, bummer
end
init_hirb
end
def init_hirb
if defined? Hirb
extend Hirb::Console
Pry.config.print = proc do |output, value|
Hirb::View.view_or_page_output(value) || Pry::DEFAULT_PRINT.call(output, value)
end
Hirb.enable
end
end
class MethodChanged < RuntimeError
def initialize(method)
case method
when UnboundMethod
super %(The method definition for #{method.owner}##{method.name} has changed since you aquired this object.)
when Method
super %(The method definition for #{method.receiver}.#{method.name} has changed since you aquired this object.)
else
raise ArgumentError
end
end
end
class MethodIncompatible < ArgumentError
def initialize(method, other)
super %(The method supplied is not compatible.)
end
end
class Method
def append(with = nil)
assert_not_changed
old_method = self
with = with ? yield(old_method) : Proc.new if block_given?
assert_compatibly with
case with
when UnboundMethod
with = with.bind(receiver)
when Proc, Method
else
raise ArgumentError
end
new_method = lambda do |*a, &b|
ret = old_method.call(*a, &b)
with.call(*a, &b)
ret
end
redefine! new_method # Assumes method was not changed during yield
end
def append_chain(with = nil)
assert_not_changed
old_method = self
with = with ? yield(old_method) : Proc.new if block_given?
assert_compatibly with
case with
when UnboundMethod
with = with.bind(receiver)
when Proc, Method
else
raise ArgumentError
end
new_method = lambda do |*a, &b|
with.call old_method.call(*a, &b)
end
redefine! new_method # Assumes method was not changed during yield
end
def assert_compatibly(with)
raise MethodIncompatible.new(self, with) if compatible_with?(with) == false
end
def assert_not_changed
raise MethodChanged.new(self) if changed?
end
def changed?
receiver.method(name) != self
end
def compatible_with?(other)
case other
when Method
return receiver == other.receiver
when UnboundMethod
return receiver.is_a? other.owner
when Proc
return true
end
end
def current
changed? ? receiver.method(name) : self
end
def prepend(with = nil)
assert_not_changed
old_method = self
with = with ? yield(old_method) : Proc.new if block_given?
assert_compatibly with
case with
when UnboundMethod
with = with.bind(receiver)
when Proc, Method
else
raise ArgumentError
end
new_method = lambda do |*a, &b|
with.call(*a, &b)
old_method.call(*a, &b)
end
redefine! new_method # Assumes method was not changed during yield
end
def redefine(*args, &block)
assert_not_changed
redefine! *args, &block
end
def redefine!(*args, &block)
receiver.send(:define_singleton_method, name, *args, &block)
current
end
def reset!
redefine! self
end
end
class UnboundMethod
def append(with = nil)
assert_not_changed
old_method = self
with = with ? yield(old_method) : Proc.new if block_given?
assert_compatibly with
case with
when UnboundMethod
new_method = lambda do |*a, &b|
ret = old_method.bind(self).call(*a, &b)
with.bind(self).call(*a, &b)
ret
end
when Proc
new_method = lambda do |*a, &b|
ret = old_method.bind(self).call(*a, &b)
with.call(*a, &b)
ret
end
else
raise ArgumentError
end
redefine! new_method # Assumes method was not changed during yield
end
def append_chain(with = nil)
assert_not_changed
old_method = self
with = with ? yield(old_method) : Proc.new if block_given?
assert_compatibly with
case with
when UnboundMethod
new_method = lambda do |*a, &b|
with.bind(self).call old_method.bind(self).call(*a, &b)
end
when Proc
new_method = lambda do |*a, &b|
with.call old_method.bind(self).call(*a, &b)
end
else
raise ArgumentError
end
redefine! new_method # Assumes method was not changed during yield
end
def assert_compatibly(with)
raise MethodIncompatible.new(self, with) if compatible_with?(with) == false
end
def assert_not_changed
raise MethodChanged.new(self) if changed?
end
def changed?
owner.instance_method(name) != self
end
def compatible_with?(other)
case other
when UnboundMethod
return owner == other.owner # FIXME: This is too simplistic
when Method
return false
when Proc
return true
end
end
def current
changed? ? owner.instance_method(name) : self
end
def prepend(with = nil)
assert_not_changed
old_method = self
with = with ? yield(old_method) : Proc.new if block_given?
assert_compatibly with
case with
when UnboundMethod
new_method = lambda do |*a, &b|
with.bind(self).call(*a, &b)
old_method.bind(self).call(*a, &b)
end
when Proc
new_method = lambda do |*a, &b|
with.call(*a, &b)
old_method.bind(self).call(*a, &b)
end
else
raise ArgumentError
end
redefine! new_method # Assumes method was not changed during yield
end
def redefine(*args, &block)
assert_not_changed
redefine! *args, &block
end
def redefine!(*args, &block)
owner.send(:define_method, name, *args, &block)
current
end
def reset!
redefine! self
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment