summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorzzak <zzak@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-12-21 05:45:50 +0000
committerzzak <zzak@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-12-21 05:45:50 +0000
commit7e9eb32669348b7e0a5775c8e0fc9566be11fc31 (patch)
tree96be4fc975e7afab8dbf4c85e04d552760dab34c /lib
parent4f7a6aafa57bf57ce4b0b5e323548f0a6385d527 (diff)
* lib/irb.rb, lib/irb/*: Documentation for IRB
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/irb.rb97
-rw-r--r--lib/irb/completion.rb5
-rw-r--r--lib/irb/context.rb65
-rw-r--r--lib/irb/ext/change-ws.rb1
-rw-r--r--lib/irb/ext/history.rb3
-rw-r--r--lib/irb/ext/loader.rb14
-rw-r--r--lib/irb/ext/multi-irb.rb43
-rw-r--r--lib/irb/ext/save-history.rb11
-rw-r--r--lib/irb/ext/tracer.rb11
-rw-r--r--lib/irb/ext/use-loader.rb4
-rw-r--r--lib/irb/ext/workspaces.rb3
-rw-r--r--lib/irb/extend-command.rb71
-rw-r--r--lib/irb/frame.rb16
-rw-r--r--lib/irb/help.rb1
-rw-r--r--lib/irb/input-method.rb65
-rw-r--r--lib/irb/inspector.rb48
-rw-r--r--lib/irb/notifier.rb89
-rw-r--r--lib/irb/output-method.rb40
-rw-r--r--lib/irb/workspace.rb4
-rw-r--r--lib/irb/xmp.rb76
20 files changed, 607 insertions, 60 deletions
diff --git a/lib/irb.rb b/lib/irb.rb
index e56b69bae0..d212a314f8 100644
--- a/lib/irb.rb
+++ b/lib/irb.rb
@@ -149,6 +149,52 @@ STDOUT.sync = true
# :RETURN => "%s\n" # used to printf
# }
#
+# irb comes with a number of available modes:
+#
+# # :NULL:
+# # :PROMPT_I:
+# # :PROMPT_N:
+# # :PROMPT_S:
+# # :PROMPT_C:
+# # :RETURN: |
+# # %s
+# # :DEFAULT:
+# # :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* '
+# # :RETURN: |
+# # => %s
+# # :CLASSIC:
+# # :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* '
+# # :RETURN: |
+# # %s
+# # :SIMPLE:
+# # :PROMPT_I: ! '>> '
+# # :PROMPT_N: ! '>> '
+# # :PROMPT_S:
+# # :PROMPT_C: ! '?> '
+# # :RETURN: |
+# # => %s
+# # :INF_RUBY:
+# # :PROMPT_I: ! '%N(%m):%03n:%i> '
+# # :PROMPT_N:
+# # :PROMPT_S:
+# # :PROMPT_C:
+# # :RETURN: |
+# # %s
+# # :AUTO_INDENT: true
+# # :XMP:
+# # :PROMPT_I:
+# # :PROMPT_N:
+# # :PROMPT_S:
+# # :PROMPT_C:
+# # :RETURN: |2
+# # ==>%s
+#
# == Restrictions
#
# Because irb evaluates input immediately after it is syntactically complete,
@@ -185,7 +231,8 @@ STDOUT.sync = true
# A few commands for loading files within the session are also available:
#
# +source+::
-# Loads a given file in the current session, see IrbLoader#source_file
+# Loads a given file in the current session and displays the source lines,
+# see IrbLoader#source_file
# +irb_load+::
# Loads the given file similarly to Kernel#load, see IrbLoader#irb_load
# +irb_require+::
@@ -279,6 +326,7 @@ STDOUT.sync = true
module IRB
@RCS_ID='-$Id$-'
+ # An exception raised by IRB.irb_abort
class Abort < Exception;end
@CONF = {}
@@ -287,11 +335,14 @@ module IRB
# Displays current configuration.
#
# Modifing the configuration is achieved by sending a message to IRB.conf.
+ #
+ # See IRB@Configuration for more information.
def IRB.conf
@CONF
end
- # IRB version method
+ # Returns the current version of IRB, including release version and last
+ # updated date.
def IRB.version
if v = @CONF[:VERSION] then return v end
@@ -300,11 +351,16 @@ module IRB
@CONF[:VERSION] = format("irb %s(%s)", rv, @LAST_UPDATE_DATE)
end
+ # The current IRB::Context of the session, see IRB.conf
+ #
+ # irb
+ # irb(main):001:0> IRB.CurrentContext.irb_name = "foo"
+ # foo(main):002:0> IRB.conf[:MAIN_CONTEXT].irb_name #=> "foo"
def IRB.CurrentContext
IRB.conf[:MAIN_CONTEXT]
end
- # initialize IRB and start TOP_LEVEL irb
+ # 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
@@ -333,7 +389,7 @@ module IRB
# print "\n"
end
- # Calls each of the IRB.conf[:AT_EXIT] hooks when the current session quits.
+ # Calls each event hook of IRB.conf[:AT_EXIT] when the current session quits.
def IRB.irb_at_exit
@CONF[:AT_EXIT].each{|hook| hook.call}
end
@@ -343,6 +399,9 @@ module IRB
throw :IRB_EXIT, ret
end
+ # Aborts then interrupts irb.
+ #
+ # Will raise an Abort exception, or the given +exception+.
def IRB.irb_abort(irb, exception = Abort)
if defined? Thread
irb.context.thread.raise exception, "abort then interrupt!"
@@ -351,8 +410,8 @@ module IRB
end
end
- # irb interpreter main routine
class Irb
+ # 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
@@ -361,9 +420,12 @@ module IRB
@scanner = RubyLex.new
@scanner.exception_on_syntax_error = false
end
+ # Returns the current context of this irb session
attr_reader :context
+ # The lexer used by this irb session
attr_accessor :scanner
+ # Evaluates input for this session.
def eval_input
@scanner.set_prompt do
|ltype, indent, continue, line_no|
@@ -462,6 +524,11 @@ module IRB
end
end
+ # Evaluates the given block using the given +path+ as the Context#irb_path
+ # and +name+ as the Context#irb_name.
+ #
+ # Used by the irb command +source+, see IRB@IRB+Sessions for more
+ # information.
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
@@ -473,6 +540,11 @@ module IRB
end
end
+ # Evaluates the given block using the given +workspace+ as the
+ # Context#workspace.
+ #
+ # Used by the irb command +irb_load+, see IRB@IRB+Sessions for more
+ # information.
def suspend_workspace(workspace)
@context.workspace, back_workspace = workspace, @context.workspace
begin
@@ -482,6 +554,11 @@ module IRB
end
end
+ # Evaluates the given block using the given +input_method+ as the
+ # Context#io.
+ #
+ # Used by the irb commands +source+ and +irb_load+, see IRB@IRB+Sessions
+ # for more information.
def suspend_input_method(input_method)
back_io = @context.io
@context.instance_eval{@io = input_method}
@@ -492,6 +569,7 @@ module IRB
end
end
+ # Evaluates the given block using the given +context+ as the Context.
def suspend_context(context)
@context, back_context = context, @context
begin
@@ -501,6 +579,7 @@ module IRB
end
end
+ # Handler for the signal SIGINT, see Kernel#trap for more information.
def signal_handle
unless @context.ignore_sigint?
print "\nabort!\n" if @context.verbose?
@@ -522,6 +601,7 @@ module IRB
end
end
+ # Evaluates the given block using the given +status+.
def signal_status(status)
return yield if @signal_status == :IN_LOAD
@@ -534,7 +614,7 @@ module IRB
end
end
- def prompt(prompt, ltype, indent, line_no)
+ def prompt(prompt, ltype, indent, line_no) # :nodoc:
p = prompt.dup
p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
case $2
@@ -565,10 +645,12 @@ module IRB
p
end
- def output_value
+ def output_value # :nodoc:
printf @context.return_format, @context.inspect_last_value
end
+ # Outputs the local variables to this current session, including
+ # #signal_status and #context, using IRB::Locale.
def inspect
ary = []
for iv in instance_variables
@@ -585,7 +667,6 @@ module IRB
end
end
- # Singleton method
def @CONF.inspect
IRB.version unless self[:VERSION]
diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb
index 3f886f507c..3b4a07186f 100644
--- a/lib/irb/completion.rb
+++ b/lib/irb/completion.rb
@@ -9,10 +9,12 @@
require "readline"
module IRB
- module InputCompletor
+ module InputCompletor # :nodoc:
@RCS_ID='-$Id$-'
+ # Set of reserved words used by Ruby, you should not use these for
+ # constants or variables
ReservedWords = [
"BEGIN", "END",
"alias", "and",
@@ -208,6 +210,7 @@ module IRB
end
}
+ # Set of available operators in Ruby
Operators = ["%", "&", "*", "**", "+", "-", "/",
"<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
"[]", "[]=", "^", "!", "!=", "!~"]
diff --git a/lib/irb/context.rb b/lib/irb/context.rb
index 0da8395640..cd191d253e 100644
--- a/lib/irb/context.rb
+++ b/lib/irb/context.rb
@@ -12,6 +12,8 @@ require "irb/workspace"
require "irb/inspector"
module IRB
+ # A class that wraps the current state of the irb session, including the
+ # configuration of IRB.conf.
class Context
# Creates a new IRB context.
#
@@ -101,28 +103,49 @@ module IRB
@debug_level = IRB.conf[:DEBUG_LEVEL]
end
+ # The top-level workspace, see WorkSpace#main
def main
@workspace.main
end
+ # The toplevel workspace, see #home_workspace
attr_reader :workspace_home
+ # WorkSpace in the current context
attr_accessor :workspace
+ # The current thread in this context
attr_reader :thread
+ # The current input method
+ #
+ # Can be either StdioInputMethod, ReadlineInputMethod, FileInputMethod or
+ # other specified when the context is created. See ::new for more
+ # information on +input_method+.
attr_accessor :io
+ # Current irb session
attr_accessor :irb
+ # A copy of the default <code>IRB.conf[:AP_NAME]</code>
attr_accessor :ap_name
+ # A copy of the default <code>IRB.conf[:RC]</code>
attr_accessor :rc
+ # A copy of the default <code>IRB.conf[:LOAD_MODULES]</code>
attr_accessor :load_modules
+ # Can be either name from <code>IRB.conf[:IRB_NAME]</code>, or the number of
+ # the current job set by JobManager, such as <code>irb#2</code>
attr_accessor :irb_name
+ # Can be either the #irb_name surrounded by parenthesis, or the
+ # +input_method+ passed to Context.new
attr_accessor :irb_path
# Whether +Readline+ is enabled or not.
#
+ # A copy of the default <code>IRB.conf[:USE_READLINE]</code>
+ #
# See #use_readline= for more information.
attr_reader :use_readline
+ # A copy of the default <code>IRB.conf[:INSPECT_MODE]</code>
attr_reader :inspect_mode
+ # A copy of the default <code>IRB.conf[:PROMPT_MODE]</code>
attr_reader :prompt_mode
# Standard IRB prompt
#
@@ -138,7 +161,11 @@ module IRB
attr_accessor :prompt_c
# See IRB@Customizing+the+IRB+Prompt for more information.
attr_accessor :prompt_n
+ # Can be either the deafult <code>IRB.conf[:AUTO_INDENT]</code>, or the
+ # mode set by #prompt_mode=
attr_accessor :auto_indent_mode
+ # The format of the return statement, set by #prompt_mode= using the
+ # +:RETURN+ of the +mode+ passed to set the current #prompt_mode.
attr_accessor :return_format
# Whether <code>^C</code> (+control-c+) will be ignored or not.
@@ -154,8 +181,20 @@ module IRB
#
# If set to +false+, <code>^D</code> will quit irb.
attr_accessor :ignore_eof
+ # Whether to echo the return value to output or not.
+ #
+ # Uses IRB.conf[:ECHO] if available, or defaults to +true+.
+ #
+ # puts "hello"
+ # # hello
+ # #=> nil
+ # IRB.CurrentContext.echo = false
+ # puts "omg"
+ # # omg
attr_accessor :echo
# Whether verbose messages are displayed or not.
+ #
+ # A copy of the default <code>IRB.conf[:VERBOSE]</code>
attr_accessor :verbose
# The debug level of irb
#
@@ -194,18 +233,26 @@ module IRB
end
end
+ # Whether #verbose? is +true+, and +input_method+ is either
+ # StdioInputMethod or ReadlineInputMethod, see #io for more information.
def prompting?
verbose? || (STDIN.tty? && @io.kind_of?(StdioInputMethod) ||
(defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod)))
end
+ # The return value of the last statement evaluated.
attr_reader :last_value
+ # Sets the return value from the last statement evaluated in this context
+ # to #last_value.
def set_last_value(value)
@last_value = value
@workspace.evaluate self, "_ = IRB.CurrentContext.last_value"
end
+ # Sets the +mode+ of the prompt in this context.
+ #
+ # See IRB@Customizing+the+IRB+Prompt for more information.
def prompt_mode=(mode)
@prompt_mode = mode
pconf = IRB.conf[:PROMPT][mode]
@@ -221,10 +268,13 @@ module IRB
end
end
+ # Whether #inspect_mode is set or not, see #inspect_mode= for more detail.
def inspect?
@inspect_mode.nil? or @inspect_mode
end
+ # Whether #io uses a File for the +input_method+ passed when creating the
+ # current context, see ::new
def file_input?
@io.class == FileInputMethod
end
@@ -236,6 +286,8 @@ module IRB
# +nil+:: inspect mode in non-math mode,
# non-inspect mode in math mode
#
+ # See IRB::INSPECTORS for more information.
+ #
# Can also be set using the +--inspect+ and +--noinspect+ command line
# options.
#
@@ -311,18 +363,19 @@ module IRB
SLex.debug_level = value
end
+ # Whether or not debug mode is enabled, see #debug_level=.
def debug?
@debug_level > 0
end
- def evaluate(line, line_no)
+ def evaluate(line, line_no) # :nodoc:
@line_no = line_no
set_last_value(@workspace.evaluate(self, line, irb_path, line_no))
# @workspace.evaluate("_ = IRB.conf[:MAIN_CONTEXT]._")
# @_ = @workspace.evaluate(line, irb_path, line_no)
end
- def inspect_last_value
+ def inspect_last_value # :nodoc:
@inspect_method.inspect_value(@last_value)
end
@@ -332,12 +385,12 @@ module IRB
IRB.irb_exit(@irb, ret)
end
- NOPRINTING_IVARS = ["@last_value"]
- NO_INSPECTING_IVARS = ["@irb", "@io"]
- IDNAME_IVARS = ["@prompt_mode"]
+ NOPRINTING_IVARS = ["@last_value"] # :nodoc:
+ NO_INSPECTING_IVARS = ["@irb", "@io"] # :nodoc:
+ IDNAME_IVARS = ["@prompt_mode"] # :nodoc:
alias __inspect__ inspect
- def inspect
+ def inspect # :nodoc:
array = []
for ivar in instance_variables.sort{|e1, e2| e1 <=> e2}
ivar = ivar.to_s
diff --git a/lib/irb/ext/change-ws.rb b/lib/irb/ext/change-ws.rb
index a28754e378..ce921eb5e3 100644
--- a/lib/irb/ext/change-ws.rb
+++ b/lib/irb/ext/change-ws.rb
@@ -12,6 +12,7 @@
module IRB # :nodoc:
class Context
+ # Inherited from +TOPLEVEL_BINDING+.
def home_workspace
if defined? @home_workspace
@home_workspace
diff --git a/lib/irb/ext/history.rb b/lib/irb/ext/history.rb
index 4d036e7cf0..3239c57a6c 100644
--- a/lib/irb/ext/history.rb
+++ b/lib/irb/ext/history.rb
@@ -15,6 +15,7 @@ module IRB # :nodoc:
NOPRINTING_IVARS.push "@eval_history_values"
+ # See #set_last_value
alias _set_last_value set_last_value
def set_last_value(value)
@@ -57,7 +58,7 @@ module IRB # :nodoc:
end
end
- class History
+ class History # :nodoc:
@RCS_ID='-$Id$-'
def initialize(size = 16)
diff --git a/lib/irb/ext/loader.rb b/lib/irb/ext/loader.rb
index 2058a2fa29..6cdc8ec898 100644
--- a/lib/irb/ext/loader.rb
+++ b/lib/irb/ext/loader.rb
@@ -14,12 +14,16 @@ module IRB # :nodoc:
# Raised in the event of an exception in a file loaded from an Irb session
class LoadAbort < Exception;end
+ # Provides a few commands for loading files within an irb session.
+ #
+ # See ExtendCommandBundle for more information.
module IrbLoader
@RCS_ID='-$Id$-'
alias ruby_load load
alias ruby_require require
+ # Loads the given file similarly to Kernel#load
def irb_load(fn, priv = nil)
path = search_file_from_ruby_path(fn)
raise LoadError, "No such file to load -- #{fn}" unless path
@@ -27,7 +31,7 @@ module IRB # :nodoc:
load_file(path, priv)
end
- def search_file_from_ruby_path(fn)
+ def search_file_from_ruby_path(fn) # :nodoc:
if /^#{Regexp.quote(File::Separator)}/ =~ fn
return fn if File.exist?(fn)
return nil
@@ -41,6 +45,9 @@ module IRB # :nodoc:
return nil
end
+ # Loads a given file in the current session and displays the source lines
+ #
+ # See Irb#suspend_input_method for more information.
def source_file(path)
irb.suspend_name(path, File.basename(path)) do
irb.suspend_input_method(FileInputMethod.new(path)) do
@@ -60,6 +67,9 @@ module IRB # :nodoc:
end
end
+ # Loads the given file in the current session's context and evaluates it.
+ #
+ # See Irb#suspend_input_method for more information.
def load_file(path, priv = nil)
irb.suspend_name(path, File.basename(path)) do
@@ -88,7 +98,7 @@ module IRB # :nodoc:
end
end
- def old
+ def old # :nodoc:
back_io = @io
back_path = @irb_path
back_name = @irb_name
diff --git a/lib/irb/ext/multi-irb.rb b/lib/irb/ext/multi-irb.rb
index 473a4361b7..e49a158fa3 100644
--- a/lib/irb/ext/multi-irb.rb
+++ b/lib/irb/ext/multi-irb.rb
@@ -12,44 +12,61 @@ IRB.fail CantShiftToMultiIrbMode unless defined?(Thread)
require "thread"
module IRB
- # job management class
class JobManager
@RCS_ID='-$Id$-'
+ # Creates a new JobManager object
def initialize
# @jobs = [[thread, irb],...]
@jobs = []
@current_job = nil
end
+ # The active irb session
attr_accessor :current_job
+ # The total number of irb sessions, used to set +irb_name+ of the current
+ # Context.
def n_jobs
@jobs.size
end
+ # Returns the thread for the given +key+ object, see #search for more
+ # information.
def thread(key)
th, = search(key)
th
end
+ # Returns the irb session for the given +key+ object, see #search for more
+ # information.
def irb(key)
_, irb = search(key)
irb
end
+ # Returns the top level thread.
def main_thread
@jobs[0][0]
end
+ # Returns the top level irb session.
def main_irb
@jobs[0][1]
end
+ # Add the given +irb+ session to the jobs Array.
def insert(irb)
@jobs.push [Thread.current, irb]
end
+ # Changes the current active irb session to the given +key+ in the jobs
+ # Array.
+ #
+ # Raises an IrbAlreadyDead exception if the given +key+ is no longer alive.
+ #
+ # If the given irb session is already active, an IrbSwitchedToCurrentThread
+ # exception is raised.
def switch(key)
th, irb = search(key)
IRB.fail IrbAlreadyDead unless th.alive?
@@ -60,6 +77,12 @@ module IRB
@current_job = irb(Thread.current)
end
+ # Terminates the irb sessions specified by the given +keys+.
+ #
+ # Raises an IrbAlreadyDead exception if one of the given +keys+ is already
+ # terminated.
+ #
+ # See Thread#exit for more information.
def kill(*keys)
for key in keys
th, _ = search(key)
@@ -68,6 +91,20 @@ module IRB
end
end
+ # Returns the associated job for the given +key+.
+ #
+ # If given an Integer, it will return the +key+ index for the jobs Array.
+ #
+ # When an instance of Irb is given, it will return the irb session
+ # associated with +key+.
+ #
+ # If given an instance of Thread, it will return the associated thread
+ # +key+ using Object#=== on the jobs Array.
+ #
+ # Otherwise returns the irb session with the same top-level binding as the
+ # given +key+.
+ #
+ # Raises a NoSuchJob exception if no job can be found with the given +key+.
def search(key)
job = case key
when Integer
@@ -83,6 +120,7 @@ module IRB
job
end
+ # Deletes the job at the given +key+.
def delete(key)
case key
when Integer
@@ -106,6 +144,7 @@ module IRB
@jobs.push assoc
end
+ # Outputs a list of jobs, see the irb command +irb_jobs+, or +jobs+.
def inspect
ary = []
@jobs.each_index do
@@ -135,10 +174,12 @@ module IRB
@JobManager = JobManager.new
+ # The current JobManager in the session
def IRB.JobManager
@JobManager
end
+ # The current Context in this session
def IRB.CurrentContext
IRB.JobManager.irb(Thread.current).context
end
diff --git a/lib/irb/ext/save-history.rb b/lib/irb/ext/save-history.rb
index f9c983ac11..3e0740d6fa 100644
--- a/lib/irb/ext/save-history.rb
+++ b/lib/irb/ext/save-history.rb
@@ -11,21 +11,24 @@
require "readline"
module IRB
- module HistorySavingAbility
+ module HistorySavingAbility # :nodoc:
@RCS_ID='-$Id$-'
end
class Context
- def init_save_history
+ def init_save_history# :nodoc:
unless (class<<@io;self;end).include?(HistorySavingAbility)
@io.extend(HistorySavingAbility)
end
end
+ # A copy of the default <code>IRB.conf[:SAVE_HISTORY]</code>
def save_history
IRB.conf[:SAVE_HISTORY]
end
+ # Sets <code>IRB.conf[:SAVE_HISTORY]</code> to the given +val+ and calls
+ # #init_save_history with this context.
def save_history=(val)
IRB.conf[:SAVE_HISTORY] = val
if val
@@ -35,16 +38,18 @@ module IRB
end
end
+ # A copy of the default <code>IRB.conf[:HISTORY_FILE]</code>
def history_file
IRB.conf[:HISTORY_FILE]
end
+ # Set <code>IRB.conf[:HISTORY_FILE]</code> to the given +hist+.
def history_file=(hist)
IRB.conf[:HISTORY_FILE] = hist
end
end
- module HistorySavingAbility
+ module HistorySavingAbility # :nodoc:
include Readline
# def HistorySavingAbility.create_finalizer
diff --git a/lib/irb/ext/tracer.rb b/lib/irb/ext/tracer.rb
index 46a9d53a2e..8c9083dbad 100644
--- a/lib/irb/ext/tracer.rb
+++ b/lib/irb/ext/tracer.rb
@@ -23,9 +23,16 @@ module IRB
end
class Context
+ # Whether Tracer is used when evaluating statements in this context.
+ #
+ # See +lib/tracer.rb+ for more information.
attr_reader :use_tracer
alias use_tracer? use_tracer
+ # Sets whether or not to use the Tracer library when evaluating statements
+ # in this context.
+ #
+ # See +lib/tracer.rb+ for more information.
def use_tracer=(opt)
if opt
Tracer.set_get_line_procs(@irb_path) {
@@ -41,6 +48,10 @@ module IRB
class WorkSpace
alias __evaluate__ evaluate
+ # Evaluate the context of this workspace and use the Tracer library to
+ # output the exact lines of code are being executed in chronological order.
+ #
+ # See +lib/tracer.rb+ for more information.
def evaluate(context, statements, file = nil, line = nil)
if context.use_tracer? && file != nil && line != nil
Tracer.on
diff --git a/lib/irb/ext/use-loader.rb b/lib/irb/ext/use-loader.rb
index 913a64116f..4e98f5b7a2 100644
--- a/lib/irb/ext/use-loader.rb
+++ b/lib/irb/ext/use-loader.rb
@@ -18,16 +18,16 @@ class Object
end
module IRB
- # :stopdoc:
module ExtendCommandBundle
+ # Loads the given file similarly to Kernel#load, see IrbLoader#irb_load
def irb_load(*opts, &b)
ExtendCommand::Load.execute(irb_context, *opts, &b)
end
+ # Loads the given file similarly to Kernel#require
def irb_require(*opts, &b)
ExtendCommand::Require.execute(irb_context, *opts, &b)
end
end
- # :startdoc:
class Context
diff --git a/lib/irb/ext/workspaces.rb b/lib/irb/ext/workspaces.rb
index 1232fee84f..641befbdf3 100644
--- a/lib/irb/ext/workspaces.rb
+++ b/lib/irb/ext/workspaces.rb
@@ -12,11 +12,12 @@
module IRB # :nodoc:
class Context
+ # Size of the current WorkSpace stack
def irb_level
workspace_stack.size
end
- # Workspaces in the current stack
+ # WorkSpaces in the current stack
def workspaces
if defined? @workspaces
@workspaces
diff --git a/lib/irb/extend-command.rb b/lib/irb/extend-command.rb
index 3f37d39950..487c0bbeff 100644
--- a/lib/irb/extend-command.rb
+++ b/lib/irb/extend-command.rb
@@ -9,16 +9,22 @@
#
#
module IRB # :nodoc:
- #
- # IRB extended command
- #
+ # Installs the default irb extensions command bundle.
module ExtendCommandBundle
- EXCB = ExtendCommandBundle
+ EXCB = ExtendCommandBundle # :nodoc:
+ # See #install_alias_method.
NO_OVERRIDE = 0
+ # See #install_alias_method.
OVERRIDE_PRIVATE_ONLY = 0x01
+ # See #install_alias_method.
OVERRIDE_ALL = 0x02
+ # Quits the current irb context
+ #
+ # +ret+ is the optional signal or message to send to Context#exit
+ #
+ # Same as <code>IRB.CurrentContext.exit</code>.
def irb_exit(ret = 0)
irb_context.exit(ret)
end
@@ -108,13 +114,33 @@ module IRB # :nodoc:
]
+ # Installs the default irb commands:
+ #
+ # +irb_current_working_workspace+:: Context#main
+ # +irb_change_workspace+:: Context#change_workspace
+ # +irb_workspaces+:: Context#workspaces
+ # +irb_push_workspace+:: Context#push_workspace
+ # +irb_pop_workspace+:: Context#pop_workspace
+ # +irb_load+:: #irb_load
+ # +irb_require+:: #irb_require
+ # +irb_source+:: IrbLoader#source_file
+ # +irb+:: IRB.irb
+ # +irb_jobs+:: JobManager
+ # +irb_fg+:: JobManager#switch
+ # +irb_kill+:: JobManager#kill
+ # +irb_help+:: IRB@Command+line+options
def self.install_extend_commands
for args in @EXTEND_COMMANDS
def_extend_command(*args)
end
end
- # aliases = [commands_alias, flag], ...
+ # Evaluate the given +cmd_name+ on the given +cmd_class+ Class.
+ #
+ # Will also define any given +aliases+ for the method.
+ #
+ # The optional +load_file+ parameter will be required within the method
+ # definition.
def self.def_extend_command(cmd_name, cmd_class, load_file = nil, *aliases)
case cmd_class
when Symbol
@@ -154,7 +180,8 @@ module IRB # :nodoc:
end
end
- # override = {NO_OVERRIDE, OVERRIDE_PRIVATE_ONLY, OVERRIDE_ALL}
+ # Installs alias methods for the default irb commands, see
+ # ::install_extend_commands.
def install_alias_method(to, from, override = NO_OVERRIDE)
to = to.id2name unless to.kind_of?(String)
from = from.id2name unless from.kind_of?(String)
@@ -175,10 +202,12 @@ module IRB # :nodoc:
end
end
- def self.irb_original_method_name(method_name)
+ def self.irb_original_method_name(method_name) # :nodoc:
"irb_" + method_name + "_org"
end
+ # Installs alias methods for the default irb commands on the given object
+ # using #install_alias_method.
def self.extend_object(obj)
unless (class << obj; ancestors; end).include?(EXCB)
super
@@ -191,9 +220,9 @@ module IRB # :nodoc:
install_extend_commands
end
- # extension support for Context
+ # Extends methods for the Context module
module ContextExtender
- CE = ContextExtender
+ CE = ContextExtender # :nodoc:
@EXTEND_COMMANDS = [
[:eval_history=, "irb/ext/history.rb"],
@@ -203,12 +232,23 @@ module IRB # :nodoc:
[:save_history=, "irb/ext/save-history.rb"],
]
+ # Installs the default context extensions as irb commands:
+ #
+ # Context#eval_history=:: +irb/ext/history.rb+
+ # Context#use_tracer=:: +irb/ext/tracer.rb+
+ # Context#math_mode=:: +irb/ext/math-mode.rb+
+ # Context#use_loader=:: +irb/ext/use-loader.rb+
+ # Context#save_history=:: +irb/ext/save-history.rb+
def self.install_extend_commands
for args in @EXTEND_COMMANDS
def_extend_command(*args)
end
end
+ # Evaluate the given +command+ from the given +load_file+ on the Context
+ # module.
+ #
+ # Will also define any given +aliases+ for the method.
def self.def_extend_command(cmd_name, load_file, *aliases)
line = __LINE__; Context.module_eval %[
def #{cmd_name}(*opts, &b)
@@ -225,7 +265,10 @@ module IRB # :nodoc:
CE.install_extend_commands
end
+ # A convenience module for extending Ruby methods.
module MethodExtender
+ # Extends the given +base_method+ with a prefix call to the given
+ # +extend_method+.
def def_pre_proc(base_method, extend_method)
base_method = base_method.to_s
extend_method = extend_method.to_s
@@ -240,6 +283,8 @@ module IRB # :nodoc:
]
end
+ # Extends the given +base_method+ with a postfix call to the given
+ # +extend_method+.
def def_post_proc(base_method, extend_method)
base_method = base_method.to_s
extend_method = extend_method.to_s
@@ -254,7 +299,13 @@ module IRB # :nodoc:
]
end
- # return #{prefix}#{name}#{postfix}<num>
+ # Returns a unique method name to use as an alias for the given +name+.
+ #
+ # Usually returns <code>#{prefix}#{name}#{postfix}<num></code>, example:
+ #
+ # new_alias_name('foo') #=> __alias_of__foo__
+ # def bar; end
+ # new_alias_name('bar') #=> __alias_of__bar__2
def new_alias_name(name, prefix = "__alias_of__", postfix = "__")
base_name = "#{prefix}#{name}#{postfix}"
all_methods = instance_methods(true) + private_instance_methods(true)
diff --git a/lib/irb/frame.rb b/lib/irb/frame.rb
index 8814b47a9d..bcfa3a3140 100644
--- a/lib/irb/frame.rb
+++ b/lib/irb/frame.rb
@@ -17,13 +17,17 @@ module IRB
def_exception :FrameOverflow, "frame overflow"
def_exception :FrameUnderflow, "frame underflow"
+ # Default number of stack frames
INIT_STACK_TIMES = 3
+ # Default number of frames offset
CALL_STACK_OFFSET = 3
+ # Creates a new stack frame
def initialize
@frames = [TOPLEVEL_BINDING] * INIT_STACK_TIMES
end
+ # Used by Kernel#set_trace_func to register each event in the call stack
def trace_func(event, file, line, id, binding)
case event
when 'call', 'class'
@@ -33,27 +37,37 @@ module IRB
end
end
+ # Returns the +n+ number of frames on the call stack from the last frame
+ # initialized.
+ #
+ # Raises FrameUnderflow if there are no frames in the given stack range.
def top(n = 0)
bind = @frames[-(n + CALL_STACK_OFFSET)]
Fail FrameUnderflow unless bind
bind
end
+ # Returns the +n+ number of frames on the call stack from the first frame
+ # initialized.
+ #
+ # Raises FrameOverflow if there are no frames in the given stack range.
def bottom(n = 0)
bind = @frames[n]
Fail FrameOverflow unless bind
bind
end
- # singleton functions
+ # Convenience method for Frame#bottom
def Frame.bottom(n = 0)
@backtrace.bottom(n)
end
+ # Convenience method for Frame#top
def Frame.top(n = 0)
@backtrace.top(n)
end
+ # Returns the binding context of the caller from the last frame initialized
def Frame.sender
eval "self", @backtrace.top
end
diff --git a/lib/irb/help.rb b/lib/irb/help.rb
index 4a308b6e46..9fd734038f 100644
--- a/lib/irb/help.rb
+++ b/lib/irb/help.rb
@@ -12,6 +12,7 @@
require 'irb/magic-file'
module IRB
+ # Outputs the irb help message, see IRB@Command+line+options.
def IRB.print_usage
lc = IRB.conf[:LC_MESSAGES]
path = lc.find("irb/help-message")
diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb
index 7227df4ca0..e1a680847c 100644
--- a/lib/irb/input-method.rb
+++ b/lib/irb/input-method.rb
@@ -12,34 +12,39 @@ require 'irb/src_encoding'
require 'irb/magic-file'
module IRB
- #
- # InputMethod
- # StdioInputMethod
- # FileInputMethod
- # (ReadlineInputMethod)
- #
- STDIN_FILE_NAME = "(line)"
+ STDIN_FILE_NAME = "(line)" # :nodoc:
class InputMethod
@RCS_ID='-$Id$-'
+ # Creates a new input method object
def initialize(file = STDIN_FILE_NAME)
@file_name = file
end
+ # The file name of this input method, usually given during initialization.
attr_reader :file_name
+ # The irb prompt associated with this input method
attr_accessor :prompt
+ # Reads the next line from this input method.
+ #
+ # See IO#gets for more information.
def gets
IRB.fail NotImplementedError, "gets"
end
public :gets
+ # Whether this input method is still readable when there is no more data to
+ # read.
+ #
+ # See IO#eof for more information.
def readable_atfer_eof?
false
end
end
class StdioInputMethod < InputMethod
+ # Creates a new input method object
def initialize
super
@line_no = 0
@@ -48,40 +53,67 @@ module IRB
@stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
end
+ # Reads the next line from this input method.
+ #
+ # See IO#gets for more information.
def gets
print @prompt
line = @stdin.gets
@line[@line_no += 1] = line
end
+ # Whether the end of this input method has been reached, returns +true+ if
+ # there is no more data to read.
+ #
+ # See IO#eof? for more information.
def eof?
@stdin.eof?
end
+ # Whether this input method is still readable when there is no more data to
+ # read.
+ #
+ # See IO#eof for more information.
def readable_atfer_eof?
true
end
+ # Returns the current line number for #io.
+ #
+ # #line counts the number of times #gets is called.
+ #
+ # See IO#lineno for more information.
def line(line_no)
@line[line_no]
end
+ # The external encoding for standard input.
def encoding
@stdin.external_encoding
end
end
+ # Use a File for IO with irb, see InputMethod
class FileInputMethod < InputMethod
+ # Creates a new input method object
def initialize(file)
super
@io = IRB::MagicFile.open(file)
end
+ # The file name of this input method, usually given during initialization.
attr_reader :file_name
+ # Whether the end of this input method has been reached, returns +true+ if
+ # there is no more data to read.
+ #
+ # See IO#eof? for more information.
def eof?
@io.eof?
end
+ # Reads the next line from this input method.
+ #
+ # See IO#gets for more information.
def gets
print @prompt
l = @io.gets
@@ -89,6 +121,7 @@ module IRB
l
end
+ # The external encoding for standard input.
def encoding
@io.external_encoding
end
@@ -98,6 +131,7 @@ module IRB
require "readline"
class ReadlineInputMethod < InputMethod
include Readline
+ # Creates a new input method object using Readline
def initialize
super
@@ -109,6 +143,9 @@ module IRB
@stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
end
+ # Reads the next line from this input method.
+ #
+ # See IO#gets for more information.
def gets
Readline.input = @stdin
Readline.output = @stdout
@@ -121,18 +158,32 @@ module IRB
end
end
+ # Whether the end of this input method has been reached, returns +true+
+ # if there is no more data to read.
+ #
+ # See IO#eof? for more information.
def eof?
@eof
end
+ # Whether this input method is still readable when there is no more data to
+ # read.
+ #
+ # See IO#eof for more information.
def readable_atfer_eof?
true
end
+ # Returns the current line number for #io.
+ #
+ # #line counts the number of times #gets is called.
+ #
+ # See IO#lineno for more information.
def line(line_no)
@line[line_no]
end
+ # The external encoding for standard input.
def encoding
@stdin.external_encoding
end
diff --git a/lib/irb/inspector.rb b/lib/irb/inspector.rb
index 6e93d3ccb9..94f42d5217 100644
--- a/lib/irb/inspector.rb
+++ b/lib/irb/inspector.rb
@@ -12,37 +12,73 @@
module IRB # :nodoc:
+
+ # Convenience method to create a new Inspector, using the given +inspect+
+ # proc, and optional +init+ proc and passes them to Inspector.new
+ #
+ # irb(main):001:0> ins = IRB::Inspector(proc{ |v| "omg! #{v}" })
+ # irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! #<IRB::Inspector:0x007f46f7ba7d28>
+ # irb(main):001:0> "what?" #=> omg! what?
+ #
def IRB::Inspector(inspect, init = nil)
Inspector.new(inspect, init)
end
+ # An irb inspector
+ #
+ # In order to create your own custom inspector there are two things you
+ # should be aware of:
+ #
+ # Inspector uses #inspect_value, or +inspect_proc+, for output of return values.
+ #
+ # This also allows for an optional #init+, or +init_proc+, which is called
+ # when the inspector is activated.
+ #
+ # Knowing this, you can create a rudimentary inspector as follows:
+ #
+ # irb(main):001:0> ins = IRB::Inspector.new(proc{ |v| "omg! #{v}" })
+ # irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! #<IRB::Inspector:0x007f46f7ba7d28>
+ # irb(main):001:0> "what?" #=> omg! what?
+ #
class Inspector
+ # Creates a new inspector object, using the given +inspect_proc+ when
+ # output return values in irb.
def initialize(inspect_proc, init_proc = nil)
@init = init_proc
@inspect = inspect_proc
end
+ # Proc to call when the inspector is activated, good for requiring
+ # dependant libraries.
def init
@init.call if @init
end
+ # Proc to call when the input is evaluated and output in irb.
def inspect_value(v)
@inspect.call(v)
end
end
+ # Default inspectors available to irb, this includes:
+ #
+ # +:pp+:: Using Kernel#pretty_inspect
+ # +:yaml+:: Using YAML.dump
+ # +:marshal+:: Using Marshal.dump
INSPECTORS = {}
+ # Determines the inspector to use where +inspector+ is one of the keys passed
+ # during inspector definition.
def INSPECTORS.keys_with_inspector(inspector)
select{|k,v| v == inspector}.collect{|k, v| k}
end
- # ex)
- # INSPECTORS.def_inspector(key, init_p=nil){|v| v.inspect}
- # INSPECTORS.def_inspector([key1,..], init_p=nil){|v| v.inspect}
- # INSPECTORS.def_inspector(key, inspector)
- # INSPECTORS.def_inspector([key1,...], inspector)
-
+ # Example
+ #
+ # INSPECTORS.def_inspector(key, init_p=nil){|v| v.inspect}
+ # INSPECTORS.def_inspector([key1,..], init_p=nil){|v| v.inspect}
+ # INSPECTORS.def_inspector(key, inspector)
+ # INSPECTORS.def_inspector([key1,...], inspector)
def INSPECTORS.def_inspector(key, arg=nil, &block)
# if !block_given?
# case arg
diff --git a/lib/irb/notifier.rb b/lib/irb/notifier.rb
index d20679da4a..effb12c30d 100644
--- a/lib/irb/notifier.rb
+++ b/lib/irb/notifier.rb
@@ -13,6 +13,7 @@ require "e2mmap"
require "irb/output-method"
module IRB
+ # An output formatter used internally by the lexer.
module Notifier
extend Exception2MessageMapper
def_exception :ErrUndefinedNotifier,
@@ -20,59 +21,100 @@ module IRB
def_exception :ErrUnrecognizedLevel,
"unrecognized notifier level: %s is specified"
+ # Define a new Notifier output source, returning a new CompositeNotifier
+ # with the given +prefix+ and +output_method+.
+ #
+ # The optional +prefix+ will be appended to all objects being inspected
+ # during output, using the given +output_method+ as the output source. If
+ # no +output_method+ is given, StdioOuputMethod will be used, and all
+ # expressions will be sent directly to STDOUT without any additional
+ # formatting.
def def_notifier(prefix = "", output_method = StdioOutputMethod.new)
CompositeNotifier.new(prefix, output_method)
end
module_function :def_notifier
+ # An abstract class, or superclass, for CompositeNotifier and
+ # LeveledNotifier to inherit. It provides several wrapper methods for the
+ # OutputMethod object used by the Notifier.
class AbstractNotifier
+ # Creates a new Notifier object
def initialize(prefix, base_notifier)
@prefix = prefix
@base_notifier = base_notifier
end
+ # The +prefix+ for this Notifier, which is appended to all objects being
+ # inspected during output.
attr_reader :prefix
+ # A wrapper method used to determine whether notifications are enabled.
+ #
+ # Defaults to +true+.
def notify?
true
end
+ # See OutputMethod#print for more detail.
def print(*opts)
@base_notifier.print prefix, *opts if notify?
end
+ # See OutputMethod#printn for more detail.
def printn(*opts)
@base_notifier.printn prefix, *opts if notify?
end
+ # See OutputMethod#printf for more detail.
def printf(format, *opts)
@base_notifier.printf(prefix + format, *opts) if notify?
end
+ # See OutputMethod#puts for more detail.
def puts(*objs)
if notify?
@base_notifier.puts(*objs.collect{|obj| prefix + obj.to_s})
end
end
+ # Same as #ppx, except it uses the #prefix given during object
+ # initialization.
+ # See OutputMethod#ppx for more detail.
def pp(*objs)
if notify?
@base_notifier.ppx @prefix, *objs
end
end
+ # Same as #pp, except it concatenates the given +prefix+ with the #prefix
+ # given during object initialization.
+ #
+ # See OutputMethod#ppx for more detail.
def ppx(prefix, *objs)
if notify?
@base_notifier.ppx @prefix+prefix, *objs
end
end
+ # Execute the given block if notifications are enabled.
def exec_if
yield(@base_notifier) if notify?
end
end
+ # A class that can be used to create a group of notifier objects with the
+ # intent of representing a leveled notification system for irb.
+ #
+ # This class will allow you to generate other notifiers, and assign them
+ # the appropriate level for output.
+ #
+ # The Notifier class provides a class-method Notifier.def_notifier to
+ # create a new composite notifier. Using the first composite notifier
+ # object you create, sibling notifiers can be initialized with
+ # #def_notifier.
class CompositeNotifier<AbstractNotifier
+ # Create a new composite notifier object with the given +prefix+, and
+ # +base_notifier+ to use for output.
def initialize(prefix, base_notifier)
super
@@ -80,17 +122,39 @@ module IRB
@level_notifier = D_NOMSG
end
+ # List of notifiers in the group
attr_reader :notifiers
+ # Creates a new LeveledNotifier in the composite #notifiers group.
+ #
+ # The given +prefix+ will be assigned to the notifier, and +level+ will
+ # be used as the index of the #notifiers Array.
+ #
+ # This method returns the newly created instance.
def def_notifier(level, prefix = "")
notifier = LeveledNotifier.new(self, level, prefix)
@notifiers[level] = notifier
notifier
end
+ # Returns the leveled notifier for this object
attr_reader :level_notifier
alias level level_notifier
+ # Sets the leveled notifier for this object.
+ #
+ # When the given +value+ is an instance of AbstractNotifier,
+ # #level_notifier is set to the given object.
+ #
+ # When an Integer is given, #level_notifier is set to the notifier at the
+ # index +value+ in the #notifiers Array.
+ #
+ # If no notifier exists at the index +value+ in the #notifiers Array, an
+ # ErrUndefinedNotifier exception is raised.
+ #
+ # An ErrUnrecognizedLevel exception is raised if the given +value+ is not
+ # found in the existing #notifiers Array, or an instance of
+ # AbstractNotifier
def level_notifier=(value)
case value
when AbstractNotifier
@@ -107,38 +171,61 @@ module IRB
alias level= level_notifier=
end
+ # A leveled notifier is comparable to the composite group from
+ # CompositeNotifier#notifiers.
class LeveledNotifier<AbstractNotifier
include Comparable
+ # Create a new leveled notifier with the given +base+, and +prefix+ to
+ # send to AbstractNotifier.new
+ #
+ # The given +level+ is used to compare other leveled notifiers in the
+ # CompositeNotifier group to determine whether or not to output
+ # notifications.
def initialize(base, level, prefix)
super(prefix, base)
@level = level
end
+ # The current level of this notifier object
attr_reader :level
+ # Compares the level of this notifier object with the given +other+
+ # notifier.
+ #
+ # See the Comparable module for more information.
def <=>(other)
@level <=> other.level
end
+ # Whether to output messages to the output method, depending on the level
+ # of this notifier object.
def notify?
@base_notifier.level >= self
end
end
+ # NoMsgNotifier is a LeveledNotifier that's used as the default notifier
+ # when creating a new CompositeNotifier.
+ #
+ # This notifier is used as the +zero+ index, or level +0+, for
+ # CompositeNotifier#notifiers, and will not output messages of any sort.
class NoMsgNotifier<LeveledNotifier
+ # Creates a new notifier that should not be used to output messages.
def initialize
@base_notifier = nil
@level = 0
@prefix = ""
end
+ # Ensures notifications are ignored, see AbstractNotifier#notify? for
+ # more information.
def notify?
false
end
end
- D_NOMSG = NoMsgNotifier.new
+ D_NOMSG = NoMsgNotifier.new # :nodoc:
end
end
diff --git a/lib/irb/output-method.rb b/lib/irb/output-method.rb
index 7c0df935a9..541c83f24d 100644
--- a/lib/irb/output-method.rb
+++ b/lib/irb/output-method.rb
@@ -12,21 +12,25 @@
require "e2mmap"
module IRB
- # OutputMethod
- # StdioOutputMethod
-
+ # An abstract output class for IO in irb. This is mainly used internally by
+ # IRB::Notifier. You can define your own output method to use with Irb.new,
+ # or Context.new
class OutputMethod
@RCS_ID='-$Id$-'
+ # Open this method to implement your own output method, raises a
+ # NotImplementedError if you don't define #print in your own class.
def print(*opts)
IRB.fail NotImplementedError, "print"
end
+ # Prints the given +opts+, with a newline delimiter.
def printn(*opts)
print opts.join(" "), "\n"
end
- # extend printf
+ # Extends IO#printf to format the given +opts+ for Kernel#sprintf using
+ # #parse_printf_format
def printf(format, *opts)
if /(%*)%I/ =~ format
format, opts = parse_printf_format(format, opts)
@@ -34,16 +38,22 @@ module IRB
print sprintf(format, *opts)
end
- # %
- # <flag> [#0- +]
- # <minimum field width> (\*|\*[1-9][0-9]*\$|[1-9][0-9]*)
- # <precision>.(\*|\*[1-9][0-9]*\$|[1-9][0-9]*|)?
- # #<length modifier>(hh|h|l|ll|L|q|j|z|t)
- # <conversion specifier>[diouxXeEfgGcsb%]
+ # Returns an array of the given +format+ and +opts+ to be used by
+ # Kernel#sprintf, if there was a successful Regexp match in the given
+ # +format+ from #printf
+ #
+ # %
+ # <flag> [#0- +]
+ # <minimum field width> (\*|\*[1-9][0-9]*\$|[1-9][0-9]*)
+ # <precision>.(\*|\*[1-9][0-9]*\$|[1-9][0-9]*|)?
+ # #<length modifier>(hh|h|l|ll|L|q|j|z|t)
+ # <conversion specifier>[diouxXeEfgGcsb%]
def parse_printf_format(format, opts)
return format, opts if $1.size % 2 == 1
end
+ # Calls #print on each element in the given +objs+, followed by a newline
+ # character.
def puts(*objs)
for obj in objs
print(*obj)
@@ -51,17 +61,27 @@ module IRB
end
end
+ # Prints the given +objs+ calling Object#inspect on each.
+ #
+ # See #puts for more detail.
def pp(*objs)
puts(*objs.collect{|obj| obj.inspect})
end
+ # Prints the given +objs+ calling Object#inspect on each and appending the
+ # given +prefix+.
+ #
+ # See #puts for more detail.
def ppx(prefix, *objs)
puts(*objs.collect{|obj| prefix+obj.inspect})
end
end
+ # A standard output printer
class StdioOutputMethod<OutputMethod
+ # Prints the given +opts+ to standard output, see IO#print for more
+ # information.
def print(*opts)
STDOUT.print(*opts)
end
diff --git a/lib/irb/workspace.rb b/lib/irb/workspace.rb
index 04490ba7c6..d26e43df57 100644
--- a/lib/irb/workspace.rb
+++ b/lib/irb/workspace.rb
@@ -75,9 +75,13 @@ EOF
eval("_=nil", @binding)
end
+ # The Binding of this workspace
attr_reader :binding
+ # The top-level workspace of this context, also available as
+ # <code>IRB.conf[:__MAIN__]</code>
attr_reader :main
+ # Evaluate the given +statements+ within the context of this workspace.
def evaluate(context, statements, file = __FILE__, line = __LINE__)
eval(statements, @binding, file, line)
end
diff --git a/lib/irb/xmp.rb b/lib/irb/xmp.rb
index bcef964020..947d2cf5a2 100644
--- a/lib/irb/xmp.rb
+++ b/lib/irb/xmp.rb
@@ -12,9 +12,46 @@
require "irb"
require "irb/frame"
+# An example printer for irb.
+#
+# It's much like the standard library PrettyPrint, that shows the value of each
+# expression as it runs.
+#
+# In order to use this library, you must first require it:
+#
+# require 'irb/xmp'
+#
+# Now, you can take advantage of the Object#xmp convenience method.
+#
+# xmp <<END
+# foo = "bar"
+# baz = 42
+# END
+# #=> foo = "bar"
+# #==>"bar"
+# #=> baz = 42
+# #==>42
+#
+# You can also create an XMP object, with an optional binding to print
+# expressions in the given binding:
+#
+# ctx = binding
+# x = XMP.new ctx
+# x.puts
+# #=> today = "a good day"
+# #==>"a good day"
+# ctx.eval 'today # is what?'
+# #=> "a good day"
class XMP
@RCS_ID='-$Id$-'
+ # Creates a new XMP object.
+ #
+ # The top-level binding or, optional +bind+ parameter will be used when
+ # creating the workspace. See WorkSpace.new for more information.
+ #
+ # This uses the +:XMP+ prompt mode, see IRB@Customizing+the+IRB+Prompt for
+ # full detail.
def initialize(bind = nil)
IRB.init_config(nil)
#IRB.parse_opts
@@ -32,6 +69,17 @@ class XMP
IRB.conf[:MAIN_CONTEXT] = @irb.context
end
+ # Evaluates the given +exps+, for example:
+ #
+ # require 'irb/xmp'
+ # x = XMP.new
+ #
+ # x.puts '{:a => 1, :b => 2, :c => 3}'
+ # #=> {:a => 1, :b => 2, :c => 3}
+ # # ==>{:a=>1, :b=>2, :c=>3}
+ # x.puts 'foo = "bar"'
+ # # => foo = "bar"
+ # # ==>"bar"
def puts(exps)
@io.puts exps
@@ -51,16 +99,22 @@ class XMP
end
end
+ # A custom InputMethod class used by XMP for evaluating string io.
class StringInputMethod < IRB::InputMethod
+ # Creates a new StringInputMethod object
def initialize
super
@exps = []
end
+ # Whether there are any expressions left in this printer.
def eof?
@exps.empty?
end
+ # Reads the next expression from this printer.
+ #
+ # See IO#gets for more information.
def gets
while l = @exps.shift
next if /^\s+$/ =~ l
@@ -71,6 +125,10 @@ class XMP
l
end
+ # Concatenates all expressions in this printer, separated by newlines.
+ #
+ # An Encoding::CompatibilityError is raised of the given +exps+'s encoding
+ # doesn't match the previous expression evaluated.
def puts(exps)
if @encoding and exps.encoding != @encoding
enc = Encoding.compatible?(@exps.join("\n"), exps)
@@ -85,10 +143,28 @@ class XMP
@exps.concat exps.split(/\n/)
end
+ # Returns the encoding of last expression printed by #puts.
attr_reader :encoding
end
end
+# A convenience method that's only available when the you require the IRB::XMP standard library.
+#
+# Creates a new XMP object, using the given expressions as the +exps+
+# parameter, and optional binding as +bind+ or uses the top-level binding. Then
+# evaluates the given expressions using the +:XMP+ prompt mode.
+#
+# For example:
+#
+# require 'irb/xmp'
+# ctx = binding
+# xmp 'foo = "bar"', ctx
+# #=> foo = "bar"
+# #==>"bar"
+# ctx.eval 'foo'
+# #=> "bar"
+#
+# See XMP.new for more information.
def xmp(exps, bind = nil)
bind = IRB::Frame.top(1) unless bind
xmp = XMP.new(bind)