aboutsummaryrefslogtreecommitdiffstats
path: root/lib/irb.rb
diff options
context:
space:
mode:
authorknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-04-30 17:38:21 +0000
committerknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-04-30 17:38:21 +0000
commitf8ab487e4d60a14dd7f807ab146168d9d034a6ea (patch)
treef5b4f478538ea7c4cc541fda4fe5a30274e472ed /lib/irb.rb
parente32f6a82698f7909cde817ae33626660b83456d7 (diff)
downloadruby-f8ab487e4d60a14dd7f807ab146168d9d034a6ea.tar.gz
Initial revision
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1337 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/irb.rb')
-rw-r--r--lib/irb.rb317
1 files changed, 317 insertions, 0 deletions
diff --git a/lib/irb.rb b/lib/irb.rb
new file mode 100644
index 0000000000..bfeb3f8be7
--- /dev/null
+++ b/lib/irb.rb
@@ -0,0 +1,317 @@
+#
+# irb.rb - irb main module
+# $Release Version: 0.7.3 $
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(keiju@ishitsuka.com)
+#
+# --
+#
+#
+#
+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$-'
+
+ 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
+
+ # initialize IRB and start TOP_LEVEL irb
+ # (JP: IRB初期化とトップレベルirb起動)
+ def IRB.start(ap_path = nil)
+ $0 = File::basename(ap_path, ".rb") if ap_path
+
+ IRB.initialize(ap_path)
+ IRB.parse_opts
+ IRB.load_modules
+
+ if @CONF[:SCRIPT]
+ irb = Irb.new(nil, @CONF[:SCRIPT])
+ else
+ irb = Irb.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
+ # (JP: irbインタプリタ本体)
+ #
+ class Irb
+ def initialize(workspace = nil, input_method = nil)
+ @context = Context.new(self, workspace, input_method)
+ @context.main.extend ExtendCommand
+ @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_input(@context.io) do
+ signal_status(:IN_INPUT) do
+ unless l = @context.io.gets
+ 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
+
+ @scanner.set_prompt do
+ |ltype, indent, continue, line_no|
+ if ltype
+ f = @context.prompt_s
+ elsif continue
+ f = @context.prompt_c
+ else @context.prompt_i
+ f = @context.prompt_i
+ end
+ f = "" unless f
+ @context.io.prompt = p = prompt(f, ltype, indent, line_no)
+ if @context.auto_indent_mode
+ unless ltype
+ ind = prompt(@context.prompt_i, ltype, indent, line_no).size +
+ indent * 2 - p.size
+ ind += 2 if continue
+ @context.io.prompt = p + " " * ind if ind > 0
+ end
+ end
+ end
+
+ @scanner.each_top_level_statement do
+ |line, line_no|
+ signal_status(:IN_EVAL) do
+ begin
+ trace_in do
+ @context._ = @context.workspace.evaluate(line,
+ @context.irb_path,
+ line_no)
+# @context._ = irb_eval(line, @context.bind, @context.irb_path, line_no)
+ end
+
+ if @context.inspect?
+ printf @context.return_format, @context._.inspect
+ else
+ printf @context.return_format, @context._
+ end
+ rescue StandardError, ScriptError, Abort
+ $! = RuntimeError.new("unknown exception raised") unless $!
+ print $!.type, ": ", $!, "\n"
+ if $@[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && $!.type.to_s !~ /^IRB/
+ irb_bug = true
+ else
+ irb_bug = false
+ end
+
+ messages = []
+ lasts = []
+ levels = 0
+ for m in $@
+ 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
+ end
+ end
+ end
+
+# def irb_eval(line, bind, path, line_no)
+# id, str = catch(:IRB_TOPLEVEL_EVAL){
+# return eval(line, bind, path, line_no)
+# }
+# case id
+# when :EVAL_TOPLEVEL
+# eval(str, bind, "(irb_internal)", 1)
+# when :EVAL_CONTEXT
+# @context.instance_eval(str)
+# else
+# IRB.fail IllegalParameter
+# 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"
+ @scanner.initialize_input
+ print @context.io.prompt
+ when :IN_EVAL
+ IRB.irb_abort(self)
+ when :IN_LOAD
+ IRB.irb_abort(self, LoadAbort)
+ when :IN_IRB
+ # ignore (JP: 何もしない.)
+ else
+ # ignore (JP: その側苳擦陸苳詞合も何もしない.)
+ 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 trace_in
+ Tracer.on if @context.use_tracer?
+ begin
+ yield
+ ensure
+ Tracer.off if @context.use_tracer?
+ 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 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>", type, 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
+ next
+ 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