Class: IRB::Irb

Inherits:
Object
  • Object
show all
Defined in:
lib/virb/default.rb

Overview

irb interpreter main routine

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(workspace = nil, input_method = StdioInputMethod.new, output_method = nil) ⇒ Irb

Returns a new instance of Irb.



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/virb/default.rb', line 165

def initialize(workspace = nil, input_method = StdioInputMethod.new , output_method = nil)

  # input_method is hard to override

  @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
  
  @outfile = File.open($outfile, 'w')
  $stderr = @outfile
  $stdout = @outfile
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



180
181
182
# File 'lib/virb/default.rb', line 180

def context
  @context
end

#scannerObject

Returns the value of attribute scanner.



181
182
183
# File 'lib/virb/default.rb', line 181

def scanner
  @scanner
end

Instance Method Details

#eval_inputObject



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'lib/virb/default.rb', line 183

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
      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

  # puts @context.io.inspect
  fd = IO.sysopen($infifo)
  @newio = IO.new(fd)
  @context.io.instance_variable_set(:@stdin, @newio)
  #@context.io.instance_variable_set(:@stdout, @outfile)

  @scanner.set_input(@context.io) do
    signal_status(:IN_INPUT) do

      if @newio.nil? || @newio.eof?
        fd = IO.sysopen($infifo)
        @newio = IO.new(fd)
        @context.io.instance_variable_set(:@stdin, @newio)
      end

      if l = @context.io.gets
        print l if @context.verbose?
      else
        if @context.ignore_eof? and @context.io.readable_after_eof?
          l = "\n"
          if @context.verbose?
            printf "Use \"exit\" to leave %s\n", @context.ap_name
          end
        else
          print "\n"
        end
      end
      l
    end
  end

  @scanner.each_top_level_statement do |line, line_no|
    signal_status(:IN_EVAL) do
      begin
        line.untaint

        # This is to handle puts etc which print to stdout instead
        # of returning a value
        stringio = StringIO.new
        $stdout = stringio
        @context.evaluate(line, line_no)
        $stdout = @outfile

        stringio.rewind
        print stringio.read
        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/ &&
            !(SyntaxError === exc)
          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

#inspectObject



419
420
421
422
423
424
425
426
427
428
429
430
431
432
# File 'lib/virb/default.rb', line 419

def inspect
  ary = []
  for iv in instance_variables
    case (iv = iv.to_s)
    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

#output_valueObject



413
414
415
416
417
# File 'lib/virb/default.rb', line 413

def output_value
  # printf @context.return_format, @context.inspect_last_value
  r = sprintf @context.return_format, @context.inspect_last_value
  print r
end

DANCHOI



305
306
307
308
# File 'lib/virb/default.rb', line 305

def print *s
  @outfile.print *s
  @outfile.flush
end

#prompt(prompt, ltype, indent, line_no) ⇒ Object



382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
# File 'lib/virb/default.rb', line 382

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

#signal_handleObject



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
# File 'lib/virb/default.rb', line 349

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

#signal_status(status) ⇒ Object



370
371
372
373
374
375
376
377
378
379
380
# File 'lib/virb/default.rb', line 370

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

#suspend_context(context) ⇒ Object



340
341
342
343
344
345
346
347
# File 'lib/virb/default.rb', line 340

def suspend_context(context)
  @context, back_context = context, @context
  begin
    yield back_context
  ensure
    @context = back_context
  end
end

#suspend_input_method(input_method) ⇒ Object



330
331
332
333
334
335
336
337
338
# File 'lib/virb/default.rb', line 330

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

#suspend_name(path = nil, name = nil) ⇒ Object



310
311
312
313
314
315
316
317
318
319
# File 'lib/virb/default.rb', line 310

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

#suspend_workspace(workspace) ⇒ Object



321
322
323
324
325
326
327
328
# File 'lib/virb/default.rb', line 321

def suspend_workspace(workspace)
  @context.workspace, back_workspace = workspace, @context.workspace
  begin
    yield back_workspace
  ensure
    @context.workspace = back_workspace
  end
end