Created
October 25, 2011 00:56
-
-
Save betawaffle/1310983 to your computer and use it in GitHub Desktop.
Pry Helpers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'benchmark' | |
include Benchmark |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'ruby-debug' | |
include Debugger |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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