# frozen_string_literal: false
# irb.rb - irb main module
# $Release Version: 0.9.6 $
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
require "irb/extend-command"
require "irb/input-method"
# IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby
# expressions read from the standard input.
# The +irb+ command from your shell will start the interpreter.
# Use of irb is easy if you know Ruby.
# When executing irb, prompts are displayed as follows. Then, enter the Ruby
# expression. An input is executed when it is syntactically complete.
# irb(main):002:0> class Foo
# irb(main):003:1> def foo
# irb(main):004:2> print 1
# The Readline extension module can be used with irb. Use of Readline is
# default if it's installed.
# == Command line options
# Usage: irb.rb [options] [programfile] [arguments]
# -f Suppress read of ~/.irbrc
# -d Set $DEBUG to true (same as `ruby -d')
# -r load-module Same as `ruby -r'
# -I path Specify $LOAD_PATH directory
# -E enc Same as `ruby -E`
# -W[level=2] Same as `ruby -W`
# --inspect Use `inspect' for output (default except for bc mode)
# --noinspect Don't use inspect for output
# --readline Use Readline extension module
# --noreadline Don't use Readline extension module
# --prompt-mode prompt-mode
# Switch prompt mode. Pre-defined prompt modes are
# `default', `simple', `xmp' and `inf-ruby'
# --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
# --simple-prompt Simple prompt mode
# --noprompt No prompt mode
# --tracer Display trace for each execution of commands.
# Display backtrace top n and tail n. The default
# --irb_debug n Set internal debug level to n (not for popular use)
# -v, --version Print the version of irb
# IRB reads from <code>~/.irbrc</code> when it's invoked.
# If <code>~/.irbrc</code> doesn't exist, +irb+ will try to read in the following order:
# The following are alternatives to the command line options. To use them type
# as follows in an +irb+ session:
# IRB.conf[:IRB_NAME]="irb"
# IRB.conf[:INSPECT_MODE]=nil
# IRB.conf[:IRB_RC] = nil
# IRB.conf[:BACK_TRACE_LIMIT]=16
# IRB.conf[:USE_LOADER] = false
# IRB.conf[:USE_READLINE] = nil
# IRB.conf[:USE_TRACER] = false
# IRB.conf[:IGNORE_SIGINT] = true
# IRB.conf[:IGNORE_EOF] = false
# IRB.conf[:PROMPT_MODE] = :DEFAULT
# IRB.conf[:PROMPT] = {...}
# IRB.conf[:DEBUG_LEVEL]=0
# To enable auto-indent mode in irb, add the following to your +.irbrc+:
# IRB.conf[:AUTO_INDENT] = true
# To enable autocompletion for irb, add the following to your +.irbrc+:
# require 'irb/completion'
# By default, irb disables history and will not store any commands you used.
# If you want to enable history, add the following to your +.irbrc+:
# IRB.conf[:SAVE_HISTORY] = 1000
# This will now store the last 1000 commands in <code>~/.irb_history</code>.
# See IRB::Context#save_history= for more information.
# == Customizing the IRB Prompt
# In order to customize the prompt, you can change the following Hash:
# This example can be used in your +.irbrc+
# IRB.conf[:PROMPT][:MY_PROMPT] = { # name of prompt mode
# :AUTO_INDENT => true, # enables auto-indent mode
# :PROMPT_I => ">> ", # simple prompt
# :PROMPT_S => nil, # prompt for continuated strings
# :PROMPT_C => nil, # prompt for continuated statement
# :RETURN => " ==>%s\n" # format to return value
# IRB.conf[:PROMPT_MODE] = :MY_PROMPT
# Or, invoke irb with the above prompt mode by:
# Constants +PROMPT_I+, +PROMPT_S+ and +PROMPT_C+ specify the format. In the
# prompt specification, some special strings are available:
# %N # command name which is running
# %m # to_s of main object (self)
# %M # inspect of main object (self)
# %l # type of string(", ', /, ]), `]' is inner %w[...]
# %NNi # indent level. NN is digits and means as same as printf("%NNd").
# For instance, the default prompt mode is defined as follows:
# IRB.conf[:PROMPT_MODE][:DEFAULT] = {
# :PROMPT_I => "%N(%m):%03n:%i> ",
# :PROMPT_S => "%N(%m):%03n:%i%l ",
# :PROMPT_C => "%N(%m):%03n:%i* ",
# :RETURN => "%s\n" # used to printf
# irb comes with a number of available modes:
# # :PROMPT_I: ! '%N(%m):%03n:%i> '
# # :PROMPT_N: ! '%N(%m):%03n:%i> '
# # :PROMPT_S: ! '%N(%m):%03n:%i%l '
# # :PROMPT_C: ! '%N(%m):%03n:%i* '
# # :PROMPT_I: ! '%N(%m):%03n:%i> '
# # :PROMPT_N: ! '%N(%m):%03n:%i> '
# # :PROMPT_S: ! '%N(%m):%03n:%i%l '
# # :PROMPT_C: ! '%N(%m):%03n:%i* '
# # :PROMPT_I: ! '%N(%m):%03n:%i> '
# Because irb evaluates input immediately after it is syntactically complete,
# the results may be slightly different than directly using Ruby.
# IRB has a special feature, that allows you to manage many sessions at once.
# You can create new sessions with Irb.irb, and get a list of current sessions
# with the +jobs+ command in the prompt.
# JobManager provides commands to handle the current sessions:
# jobs # List of current sessions
# fg # Switches to the session of the given number
# kill # Kills the session with the given number
# The +exit+ command, or ::irb_exit, will quit the current session and call any
# exit hooks with IRB.irb_at_exit.
# A few commands for loading files within the session are also available:
# Loads a given file in the current session and displays the source lines,
# see IrbLoader#source_file
# Loads the given file similarly to Kernel#load, see IrbLoader#irb_load
# Loads the given file similarly to Kernel#require
# The command line options, or IRB.conf, specify the default behavior of
# On the other hand, each conf in IRB@Command+line+options is used to
# individually configure IRB.irb.
# If a proc is set for IRB.conf[:IRB_RC], its will be invoked after execution
# of that proc with the context of the current session as its argument. Each
# session can be configured using this mechanism.
# There are a few variables in every Irb session that can come in handy:
# The value command executed, as a local variable
# The history of evaluated commands
# <code>__[line_no]</code>::
# Returns the evaluation value at the given line number, +line_no+.
# If +line_no+ is a negative, the return value +line_no+ many lines before
# the most recent return value.
# === Example using IRB Sessions
# irb.1(main):001:0> jobs
# #0->irb on main (#<Thread:0x400fb7e4> : stop)
# #1->irb#1 on main (#<Thread:0x40125d64> : running)
# # change the active session
# irb.1(main):002:0> fg 0
# # define class Foo in top-level session
# irb(main):002:0> class Foo;end
# # invoke a new session with the context of Foo
# irb(main):003:0> irb Foo
# irb.2(Foo):001:0> def foo
# irb.2(Foo):002:1> print 1
# # change the active session
# #0->irb on main (#<Thread:0x400fb7e4> : running)
# #1->irb#1 on main (#<Thread:0x40125d64> : stop)
# #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
# # check if Foo#foo is available
# irb(main):005:0> Foo.instance_methods #=> [:foo, ...]
# # change the active sesssion
# # define Foo#bar in the context of Foo
# irb.2(Foo):005:0> def bar
# irb.2(Foo):006:1> print "bar"
# irb.2(Foo):010:0> Foo.instance_methods #=> [:bar, :foo, ...]
# # change the active session
# irb(main):007:0> f = Foo.new #=> #<Foo:0x4010af3c>
# # invoke a new session with the context of f (instance of Foo)
# irb.3(<Foo:0x4010af3c>):001:0> jobs
# #0->irb on main (#<Thread:0x400fb7e4> : stop)
# #1->irb#1 on main (#<Thread:0x40125d64> : stop)
# #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
# #3->irb#3 on #<Foo:0x4010af3c> (#<Thread:0x4010a1e0> : running)
# irb.3(<Foo:0x4010af3c>):002:0> foo #=> 1 => nil
# irb.3(<Foo:0x4010af3c>):003:0> bar #=> bar => nil
# # kill jobs 1, 2, and 3
# irb.3(<Foo:0x4010af3c>):004:0> kill 1, 2, 3
# # list open sessions, should only include main session
# #0->irb on main (#<Thread:0x400fb7e4> : running)
# An exception raised by IRB.irb_abort
class Abort < Exception;end
# Displays current configuration.
# Modifying the configuration is achieved by sending a message to IRB.conf.
# See IRB@Configuration for more information.
# Returns the current version of IRB, including release version and last
if v = @CONF[:VERSION] then return v end
rv = @RELEASE_VERSION.sub(/\.0/, "")
@CONF[:VERSION] = format("irb %s(%s)", rv, @LAST_UPDATE_DATE)
# The current IRB::Context of the session, see IRB.conf
# irb(main):001:0> IRB.CurrentContext.irb_name = "foo"
# foo(main):002:0> IRB.conf[:MAIN_CONTEXT].irb_name #=> "foo"
# Initializes IRB and creates a new Irb.irb object at the +TOPLEVEL_BINDING+
def IRB.start(ap_path = nil)
$0 = File::basename(ap_path, ".rb") if ap_path
irb = Irb.new(nil, @CONF[:SCRIPT])
# Calls each event hook of IRB.conf[:AT_EXIT] when the current session quits.
@CONF[:AT_EXIT].each{|hook| hook.call}
def IRB.irb_exit(irb, ret)
# Aborts then interrupts irb.
# Will raise an Abort exception, or the given +exception+.
def IRB.irb_abort(irb, exception = Abort)
irb.context.thread.raise exception, "abort then interrupt!"
raise exception, "abort then interrupt!"
# Creates a new irb session
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
conf[:IRB_RC].call(context) if conf[:IRB_RC]
conf[:MAIN_CONTEXT] = context
conf[:AT_EXIT].each{|hook| hook.call}
# Returns the current context of this irb session
# The lexer used by this irb session
# Evaluates input for this session.
|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_after_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
if exc.backtrace && exc.backtrace[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&