# irb.rb - irb main module
# $Release Version: 0.9.5 $
# $Date: 2009-08-09 17:44:15 +0900 (Sun, 09 Aug 2009) $
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
require "irb/extend-command"
require "irb/input-method"
@RCS_ID='-$Id: irb.rb 24483 2009-08-09 08:44:15Z shyouhei $-'
class Abort < Exception;end
if v = @CONF[:VERSION] then return v end
rv = @RELEASE_VERSION.sub(/\.0/, "")
@CONF[:VERSION] = format("irb %s(%s)", rv, @LAST_UPDATE_DATE)
# initialize IRB and start TOP_LEVEL irb
def IRB.start(ap_path = nil)
$0 = File::basename(ap_path, ".rb") if ap_path
irb = Irb.new(nil, @CONF[:SCRIPT])
@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
@CONF[:MAIN_CONTEXT] = irb.context
@CONF[:AT_EXIT].each{|hook| hook.call}
def IRB.irb_exit(irb, ret)
def IRB.irb_abort(irb, exception = Abort)
irb.context.thread.raise exception, "abort then interrupt!!"
raise exception, "abort then interrupt!!"
# irb interpriter main routine
def initialize(workspace = nil, input_method = nil, output_method = nil)
@context = Context.new(self, workspace, input_method, output_method)
@context.main.extend ExtendCommandBundle
@scanner.exception_on_syntax_error = false
|ltype, indent, continue, line_no|
@context.io.prompt = p = prompt(f, ltype, indent, line_no)
@context.io.prompt = p = ""
if @context.auto_indent_mode
ind = prompt(@context.prompt_i, ltype, indent, line_no)[/.*\z/].size +
@context.io.prompt = p + " " * ind if ind > 0
@scanner.set_input(@context.io) do
signal_status(:IN_INPUT) do
print l if @context.verbose?
if @context.ignore_eof? and @context.io.readable_atfer_eof?
printf "Use \"exit\" to leave %s\n", @context.ap_name
@scanner.each_top_level_statement do |line, line_no|
signal_status(:IN_EVAL) do
@context.evaluate(line, line_no)
output_value if @context.echo?
rescue SystemExit, SignalException
print exc.class, ": ", exc, "\n"
if exc.backtrace[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/
m = @context.workspace.filter_backtrace(m) unless irb_bug
if messages.size < @context.back_trace_limit
messages.push "\tfrom "+m
if lasts.size > @context.back_trace_limit
print messages.join("\n"), "\n"
printf "... %d levels...\n", levels if levels > 0
print "Maybe IRB bug!!\n" if irb_bug
abort "Error: irb does not work for $SAFE level higher than 2"
def suspend_name(path = nil, name = nil)
@context.irb_path, back_path = path, @context.irb_path if path
@context.irb_name, back_name = name, @context.irb_name if name
yield back_path, back_name
@context.irb_path = back_path if path
@context.irb_name = back_name if name
def suspend_workspace(workspace)
@context.workspace, back_workspace = workspace, @context.workspace
@context.workspace = back_workspace
def suspend_input_method(input_method)
@context.instance_eval{@io = input_method}
@context.instance_eval{@io = back_io}
def suspend_context(context)
@context, back_context = context, @context
unless @context.ignore_sigint?
print "\nabort!!\n" if @context.verbose?
raise RubyLex::TerminateLineInput
IRB.irb_abort(self, LoadAbort)
# ignore other cases as well
def signal_status(status)
return yield if @signal_status == :IN_LOAD
signal_status_back = @signal_status
@signal_status = signal_status_back
def prompt(prompt, ltype, indent, line_no)
p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
format("%" + $1 + "d", indent)
format("%" + $1 + "d", line_no)
printf @context.return_format, @context.last_value.inspect
printf @context.return_format, @context.last_value
for iv in instance_variables
ary.push format("%s=:%s", iv, @signal_status.id2name)
ary.push format("%s=%s", iv, eval(iv).__to_s__)
ary.push format("%s=%s", iv, eval(iv))
format("#<%s: %s>", self.class, ary.join(", "))
IRB.version unless self[:VERSION]
for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name}
when :MAIN_CONTEXT, :__TMP__EHV__
array.push format("CONF[:%s]=...myself...", k.id2name)
ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"}
format(":%s=>{%s}", kk.id2name, ss.join(", "))
array.push format("CONF[:%s]={%s}", k.id2name, s.join(", "))
array.push format("CONF[:%s]=%s", k.id2name, v.inspect)