2 # irb.rb - irb main module
3 # $Release Version: 0.9.5 $
5 # $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $
6 # by Keiju ISHITSUKA(keiju@ruby-lang.org)
16 require "irb/extend-command"
17 #require "irb/workspace"
19 require "irb/ruby-lex"
20 require "irb/input-method"
26 @RCS_ID='-$Id: irb.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
28 class Abort < Exception;end
39 if v = @CONF[:VERSION] then return v end
42 rv = @RELEASE_VERSION.sub(/\.0/, "")
43 @CONF[:VERSION] = format("irb %s(%s)", rv, @LAST_UPDATE_DATE)
46 def IRB.CurrentContext
47 IRB.conf[:MAIN_CONTEXT]
50 # initialize IRB and start TOP_LEVEL irb
51 def IRB.start(ap_path = nil)
52 $0 = File::basename(ap_path, ".rb") if ap_path
57 klass = @CONF[:IRB_CLASS]
63 irb = klass.new(nil, @CONF[:SCRIPT])
68 @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
69 @CONF[:MAIN_CONTEXT] = irb.context
81 def IRB.irb_exit(irb, ret)
85 def IRB.irb_abort(irb, exception = Abort)
87 irb.context.thread.raise exception, "abort then interrupt!!"
89 raise exception, "abort then interrupt!!"
94 # irb interpriter main routine
97 def initialize(workspace = nil, input_method = nil, output_method = nil)
98 @context = Context.new(self, workspace, input_method, output_method)
99 @context.main.extend ExtendCommandBundle
100 @signal_status = :IN_IRB
102 @scanner = RubyLex.new
103 @scanner.exception_on_syntax_error = false
106 attr_accessor :scanner
109 @scanner.set_prompt do
110 |ltype, indent, continue, line_no|
112 f = @context.prompt_s
114 f = @context.prompt_c
116 f = @context.prompt_n
117 else @context.prompt_i
118 f = @context.prompt_i
121 if @context.prompting?
122 @context.io.prompt = p = prompt(f, ltype, indent, line_no)
124 @context.io.prompt = p = ""
126 if @context.auto_indent_mode
128 ind = prompt(@context.prompt_i, ltype, indent, line_no)[/.*\z/].size +
131 @context.io.prompt = p + " " * ind if ind > 0
136 @scanner.set_input(@context.io) do
137 signal_status(:IN_INPUT) do
138 if l = @context.io.gets
139 print l if @context.verbose?
141 if @context.ignore_eof? and @context.io.readable_atfer_eof?
144 printf "Use \"exit\" to leave %s\n", @context.ap_name
155 def process_statements
156 @scanner.each_top_level_statement do |line, line_no|
157 signal_status(:IN_EVAL) do
160 @context.evaluate(line, line_no)
161 output_value if @context.echo?
162 rescue StandardError, ScriptError, Abort
163 $! = RuntimeError.new("unknown exception raised") unless $!
164 print $!.class, ": ", $!, "\n"
165 if $@[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && $!.class.to_s !~ /^IRB/
175 m = @context.workspace.filter_backtrace(m) unless irb_bug
177 if messages.size < @context.back_trace_limit
178 messages.push "\tfrom "+m
180 lasts.push "\tfrom "+m
181 if lasts.size > @context.back_trace_limit
188 print messages.join("\n"), "\n"
190 printf "... %d levels...\n", levels if levels > 0
191 print lasts.join("\n")
193 print "Maybe IRB bug!!\n" if irb_bug
196 warn "Error: irb does not work for $SAFE level higher than 2"
203 def suspend_name(path = nil, name = nil)
204 @context.irb_path, back_path = path, @context.irb_path if path
205 @context.irb_name, back_name = name, @context.irb_name if name
207 yield back_path, back_name
209 @context.irb_path = back_path if path
210 @context.irb_name = back_name if name
214 def suspend_workspace(workspace)
215 @context.workspace, back_workspace = workspace, @context.workspace
219 @context.workspace = back_workspace
223 def suspend_input_method(input_method)
224 back_io = @context.io
225 @context.instance_eval{@io = input_method}
229 @context.instance_eval{@io = back_io}
233 def suspend_context(context)
234 @context, back_context = context, @context
238 @context = back_context
243 unless @context.ignore_sigint?
244 print "\nabort!!\n" if @context.verbose?
251 raise RubyLex::TerminateLineInput
255 IRB.irb_abort(self, LoadAbort)
259 # ignore other cases as well
263 def signal_status(status)
264 return yield if @signal_status == :IN_LOAD
266 signal_status_back = @signal_status
267 @signal_status = status
271 @signal_status = signal_status_back
275 def prompt(prompt, ltype, indent, line_no)
277 p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
284 @context.main.inspect
289 format("%" + $1 + "d", indent)
295 format("%" + $1 + "d", line_no)
308 printf @context.return_format, @context.last_value.inspect
310 printf @context.return_format, @context.last_value
316 for iv in instance_variables
318 when "@signal_status"
319 ary.push format("%s=:%s", iv, @signal_status.id2name)
321 ary.push format("%s=%s", iv, eval(iv).__to_s__)
323 ary.push format("%s=%s", iv, eval(iv))
326 format("#<%s: %s>", self.class, ary.join(", "))
332 IRB.version unless self[:VERSION]
335 for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name}
337 when :MAIN_CONTEXT, :__TMP__EHV__
338 array.push format("CONF[:%s]=...myself...", k.id2name)
342 ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"}
343 format(":%s=>{%s}", kk.id2name, ss.join(", "))
345 array.push format("CONF[:%s]={%s}", k.id2name, s.join(", "))
347 array.push format("CONF[:%s]=%s", k.id2name, v.inspect)