Split debrew up to faciliate test isolation

We want to be able to test the raise functionality without
monkey-patching #raise on every object in the system, which is one of
the side effects of loading debrew.rb.
This commit is contained in:
Jack Nagel 2013-02-06 18:46:36 -06:00
parent 46e49c4889
commit a75dd6e8a8
5 changed files with 128 additions and 120 deletions

View File

@ -2,88 +2,12 @@ def can_use_readline?
not ENV['HOMEBREW_NO_READLINE']
end
require 'irb' if can_use_readline?
require 'continuation' if RUBY_VERSION.to_f >= 1.9
require 'debrew/menu'
require 'debrew/raise_plus'
require 'debrew/irb' if can_use_readline?
class Menu
attr_accessor :prompt
attr_accessor :entries
def initialize
@entries = []
end
def choice(name, &action)
entries << { :name => name, :action => action }
end
end
def choose
menu = Menu.new
yield menu
choice = nil
while choice.nil?
menu.entries.each_with_index do |entry, i|
puts "#{i+1}. #{entry[:name]}"
end
print menu.prompt unless menu.prompt.nil?
reply = $stdin.gets.chomp
i = reply.to_i
if i > 0
choice = menu.entries[i-1]
else
possible = menu.entries.find_all {|e| e[:name].to_s.start_with? reply }
case possible.size
when 0 then puts "No such option"
when 1 then choice = possible.first
else puts "Multiple options match: #{possible.map{|e| e[:name]}.join(' ')}"
end
end
end
choice[:action].call
end
module IRB
@setup_done = false
def IRB.start_within(binding)
unless @setup_done
# make IRB ignore our command line arguments
saved_args = ARGV.shift(ARGV.size)
IRB.setup(nil)
ARGV.concat(saved_args)
@setup_done = true
end
workspace = WorkSpace.new(binding)
irb = Irb.new(workspace)
@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
@CONF[:MAIN_CONTEXT] = irb.context
trap("SIGINT") do
irb.signal_handle
end
begin
catch(:IRB_EXIT) do
irb.eval_input
end
ensure
irb_at_exit
end
end
end if can_use_readline?
class Exception
attr_accessor :continuation
def restart(&block)
continuation.call block
end
class Object
include RaisePlus
end
def has_debugger?
@ -131,42 +55,3 @@ def debrew(exception, formula=nil)
end
end while again
end
module RaisePlus
alias :original_raise :raise
def raise(*args)
exception = case
when args.size == 0
$!.nil? ? RuntimeError.exception : $!
when args.size == 1 && args[0].is_a?(String)
RuntimeError.exception(args[0])
when args.size == 2 && args[0].is_a?(Exception)
args[0].exception(args[1])
when args[0].is_a?(Class) && args[0].ancestors.include?(Exception)
args[0].exception(args[1])
else
args[0]
end
# passing something other than a String or Exception is illegal, but if someone does it anyway,
# that object won't have backtrace or continuation methods. in that case, let's pass it on to
# the original raise, which will reject it
return super exception unless exception.is_a?(Exception)
# keep original backtrace if reraising
exception.set_backtrace(args.size >= 3 ? args[2] : caller) if exception.backtrace.nil?
blk = callcc do |cc|
exception.continuation = cc
super exception
end
blk.call unless blk.nil?
end
alias :fail :raise
end
class Object
include RaisePlus
end

View File

@ -0,0 +1,7 @@
class Exception
attr_accessor :continuation
def restart(&block)
continuation.call block
end
end

View File

@ -0,0 +1,33 @@
require 'irb'
module IRB
@setup_done = false
def IRB.start_within(binding)
unless @setup_done
# make IRB ignore our command line arguments
saved_args = ARGV.shift(ARGV.size)
IRB.setup(nil)
ARGV.concat(saved_args)
@setup_done = true
end
workspace = WorkSpace.new(binding)
irb = Irb.new(workspace)
@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
@CONF[:MAIN_CONTEXT] = irb.context
trap("SIGINT") do
irb.signal_handle
end
begin
catch(:IRB_EXIT) do
irb.eval_input
end
ensure
irb_at_exit
end
end
end

View File

@ -0,0 +1,39 @@
class Menu
attr_accessor :prompt
attr_accessor :entries
def initialize
@entries = []
end
def choice(name, &action)
entries << { :name => name, :action => action }
end
end
def choose
menu = Menu.new
yield menu
choice = nil
while choice.nil?
menu.entries.each_with_index do |entry, i|
puts "#{i+1}. #{entry[:name]}"
end
print menu.prompt unless menu.prompt.nil?
reply = $stdin.gets.chomp
i = reply.to_i
if i > 0
choice = menu.entries[i-1]
else
possible = menu.entries.find_all {|e| e[:name].to_s.start_with? reply }
case possible.size
when 0 then puts "No such option"
when 1 then choice = possible.first
else puts "Multiple options match: #{possible.map{|e| e[:name]}.join(' ')}"
end
end
end
choice[:action].call
end

View File

@ -0,0 +1,44 @@
require 'continuation' if RUBY_VERSION.to_f >= 1.9
class Exception
attr_accessor :continuation
def restart(&block)
continuation.call block
end
end
module RaisePlus
alias :original_raise :raise
def raise(*args)
exception = case
when args.size == 0
$!.nil? ? RuntimeError.exception : $!
when args.size == 1 && args[0].is_a?(String)
RuntimeError.exception(args[0])
when args.size == 2 && args[0].is_a?(Exception)
args[0].exception(args[1])
when args[0].is_a?(Class) && args[0].ancestors.include?(Exception)
args[0].exception(args[1])
else
args[0]
end
# passing something other than a String or Exception is illegal, but if someone does it anyway,
# that object won't have backtrace or continuation methods. in that case, let's pass it on to
# the original raise, which will reject it
return super exception unless exception.is_a?(Exception)
# keep original backtrace if reraising
exception.set_backtrace(args.size >= 3 ? args[2] : caller) if exception.backtrace.nil?
blk = callcc do |cc|
exception.continuation = cc
super exception
end
blk.call unless blk.nil?
end
alias :fail :raise
end