Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

357 lines (317 sloc) 7.648 kb
#
# irb.rb - irb main module
# $Release Version: 0.9.5 $
# $Revision: 15408 $
# $Date: 2008-02-08 07:44:54 -0800 (Fri, 08 Feb 2008) $
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
# --
#
#
#
require "e2mmap"
require "irb/init"
require "irb/context"
require "irb/extend-command"
#require "irb/workspace"
require "irb/ruby-lex"
require "irb/input-method"
require "irb/locale"
STDOUT.sync = true
module IRB
@RCS_ID='-$Id: irb.rb 15408 2008-02-08 15:44:54Z nobu $-'
class Abort < Exception;end
#
@CONF = {}
def IRB.conf
@CONF
end
# IRB version method
def IRB.version
if v = @CONF[:VERSION] then return v end
require "irb/version"
rv = @RELEASE_VERSION.sub(/\.0/, "")
@CONF[:VERSION] = format("irb %s(%s)", rv, @LAST_UPDATE_DATE)
end
def IRB.CurrentContext
IRB.conf[:MAIN_CONTEXT]
end
# initialize IRB and start TOP_LEVEL irb
def IRB.start(ap_path = nil)
$0 = File::basename(ap_path, ".rb") if ap_path
IRB.setup(ap_path)
if @CONF[:IRB_CLASS]
klass = @CONF[:IRB_CLASS]
else
klass = Irb
end
if @CONF[:SCRIPT]
irb = klass.new(nil, @CONF[:SCRIPT])
else
irb = klass.new
end
@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
@CONF[:MAIN_CONTEXT] = irb.context
trap("SIGINT") do
irb.signal_handle
end
catch(:IRB_EXIT) do
irb.eval_input
end
# print "\n"
end
def IRB.irb_exit(irb, ret)
throw :IRB_EXIT, ret
end
def IRB.irb_abort(irb, exception = Abort)
if defined? Thread
irb.context.thread.raise exception, "abort then interrupt!!"
else
raise exception, "abort then interrupt!!"
end
end
#
# irb interpriter main routine
#
class Irb
def initialize(workspace = nil, input_method = nil, output_method = nil)
@context = Context.new(self, workspace, input_method, output_method)
@context.main.extend ExtendCommandBundle
@signal_status = :IN_IRB
@scanner = RubyLex.new
@scanner.exception_on_syntax_error = false
end
attr_reader :context
attr_accessor :scanner
def eval_input
@scanner.set_prompt do
|ltype, indent, continue, line_no|
if ltype
f = @context.prompt_s
elsif continue
f = @context.prompt_c
elsif indent > 0
f = @context.prompt_n
else @context.prompt_i
f = @context.prompt_i
end
f = "" unless f
if @context.prompting?
@context.io.prompt = p = prompt(f, ltype, indent, line_no)
else
@context.io.prompt = p = ""
end
if @context.auto_indent_mode
unless ltype
ind = prompt(@context.prompt_i, ltype, indent, line_no)[/.*\z/].size +
indent * 2 - p.size
ind += 2 if continue
@context.io.prompt = p + " " * ind if ind > 0
end
end
end
@scanner.set_input(@context.io) do
signal_status(:IN_INPUT) do
if l = @context.io.gets
print l if @context.verbose?
else
if @context.ignore_eof? and @context.io.readable_atfer_eof?
l = "\n"
if @context.verbose?
printf "Use \"exit\" to leave %s\n", @context.ap_name
end
end
end
l
end
end
process_statements
end
def process_statements
@scanner.each_top_level_statement do |line, line_no|
signal_status(:IN_EVAL) do
begin
line.untaint
@context.evaluate(line, line_no)
output_value if @context.echo?
exc = nil
rescue Interrupt => exc
rescue SystemExit, SignalException
raise
rescue Exception => exc
end
if exc
print exc.class, ": ", exc, "\n"
if exc.backtrace[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/
irb_bug = true
else
irb_bug = false
end
messages = []
lasts = []
levels = 0
for m in exc.backtrace
m = @context.workspace.filter_backtrace(m) unless irb_bug
if m
if messages.size < @context.back_trace_limit
messages.push "\tfrom "+m
else
lasts.push "\tfrom "+m
if lasts.size > @context.back_trace_limit
lasts.shift
levels += 1
end
end
end
end
print messages.join("\n"), "\n"
unless lasts.empty?
printf "... %d levels...\n", levels if levels > 0
print lasts.join("\n")
end
print "Maybe IRB bug!!\n" if irb_bug
end
if $SAFE > 2
abort "Error: irb does not work for $SAFE level higher than 2"
end
end
end
end
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
begin
yield back_path, back_name
ensure
@context.irb_path = back_path if path
@context.irb_name = back_name if name
end
end
def suspend_workspace(workspace)
@context.workspace, back_workspace = workspace, @context.workspace
begin
yield back_workspace
ensure
@context.workspace = back_workspace
end
end
def suspend_input_method(input_method)
back_io = @context.io
@context.instance_eval{@io = input_method}
begin
yield back_io
ensure
@context.instance_eval{@io = back_io}
end
end
def suspend_context(context)
@context, back_context = context, @context
begin
yield back_context
ensure
@context = back_context
end
end
def signal_handle
unless @context.ignore_sigint?
print "\nabort!!\n" if @context.verbose?
exit
end
case @signal_status
when :IN_INPUT
print "^C\n"
raise RubyLex::TerminateLineInput
when :IN_EVAL
IRB.irb_abort(self)
when :IN_LOAD
IRB.irb_abort(self, LoadAbort)
when :IN_IRB
# ignore
else
# ignore other cases as well
end
end
def signal_status(status)
return yield if @signal_status == :IN_LOAD
signal_status_back = @signal_status
@signal_status = status
begin
yield
ensure
@signal_status = signal_status_back
end
end
def prompt(prompt, ltype, indent, line_no)
p = prompt.dup
p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
case $2
when "N"
@context.irb_name
when "m"
@context.main.to_s
when "M"
@context.main.inspect
when "l"
ltype
when "i"
if $1
format("%" + $1 + "d", indent)
else
indent.to_s
end
when "n"
if $1
format("%" + $1 + "d", line_no)
else
line_no.to_s
end
when "%"
"%"
end
end
p
end
def output_value
if @context.inspect?
printf @context.return_format, @context.last_value.inspect
else
printf @context.return_format, @context.last_value
end
end
def inspect
ary = []
for iv in instance_variables
case iv
when "@signal_status"
ary.push format("%s=:%s", iv, @signal_status.id2name)
when "@context"
ary.push format("%s=%s", iv, eval(iv).__to_s__)
else
ary.push format("%s=%s", iv, eval(iv))
end
end
format("#<%s: %s>", self.class, ary.join(", "))
end
end
# Singleton method
def @CONF.inspect
IRB.version unless self[:VERSION]
array = []
for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name}
case k
when :MAIN_CONTEXT, :__TMP__EHV__
array.push format("CONF[:%s]=...myself...", k.id2name)
when :PROMPT
s = v.collect{
|kk, vv|
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(", "))
else
array.push format("CONF[:%s]=%s", k.id2name, v.inspect)
end
end
array.join("\n")
end
end
Jump to Line
Something went wrong with that request. Please try again.