1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/lib/irb/context.rb

480 lines
15 KiB
Ruby
Raw Normal View History

# frozen_string_literal: false
#
# irb/context.rb - irb context
# $Release Version: 0.9.6$
# $Revision$
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
# --
#
#
#
require_relative "workspace"
require_relative "inspector"
require_relative "input-method"
require_relative "output-method"
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.
#
# The optional +input_method+ argument:
#
# +nil+:: uses stdin or Reidline or Readline
# +String+:: uses a File
# +other+:: uses this as InputMethod
def initialize(irb, workspace = nil, input_method = nil)
@irb = irb
if workspace
@workspace = workspace
else
@workspace = WorkSpace.new
end
@thread = Thread.current if defined? Thread
# copy of default configuration
@ap_name = IRB.conf[:AP_NAME]
@rc = IRB.conf[:RC]
@load_modules = IRB.conf[:LOAD_MODULES]
if IRB.conf.has_key?(:USE_SINGLELINE)
@use_singleline = IRB.conf[:USE_SINGLELINE]
elsif IRB.conf.has_key?(:USE_READLINE) # backward compatibility
@use_singleline = IRB.conf[:USE_READLINE]
else
@use_singleline = nil
end
if IRB.conf.has_key?(:USE_MULTILINE)
@use_multiline = IRB.conf[:USE_MULTILINE]
elsif IRB.conf.has_key?(:USE_REIDLINE) # backward compatibility
@use_multiline = IRB.conf[:USE_REIDLINE]
else
@use_multiline = nil
end
@use_colorize = IRB.conf[:USE_COLORIZE]
@verbose = IRB.conf[:VERBOSE]
@io = nil
self.inspect_mode = IRB.conf[:INSPECT_MODE]
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by rb_exec_recursive() in eval.c. * eval.c (rb_exec_recursive): new function. * array.c (rb_ary_join): use rb_exec_recursive(). * array.c (rb_ary_inspect, rb_ary_hash): ditto. * file.c (rb_file_join): ditto. * hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto. * io.c (rb_io_puts): ditto. * object.c (rb_obj_inspect): ditto * struct.c (rb_struct_inspect): ditto. * lib/set.rb (SortedSet::setup): a hack to shut up warning. [ruby-talk:132866] * lib/time.rb (Time::strptime): add new function. inspired by [ruby-talk:132815]. * lib/parsedate.rb (ParseDate::strptime): ditto. * regparse.c: move st_*_strend() functions from st.c. fixed some potential memory leaks. * exception error messages updated. [ruby-core:04497] * ext/socket/socket.c (Init_socket): add bunch of Socket constants. Patch from Sam Roberts <sroberts@uniserve.com>. [ruby-core:04409] * array.c (rb_ary_s_create): no need for negative argc check. [ruby-core:04463] * array.c (rb_ary_unshift_m): ditto. * lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass of StandardError class, not Exception class. [ruby-core:04429] * parse.y (fcall_gen): lvar(arg) will be evaluated as lvar.call(arg) when lvar is a defined local variable. [new] * object.c (rb_class_initialize): call inherited method before calling initializing block. * eval.c (rb_thread_start_1): initialize newly pushed frame. * lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE. fixed: [ruby-core:04444] * eval.c (is_defined): NODE_IASGN is an assignment. * ext/readline/readline.c (Readline.readline): use rl_outstream and rl_instream. [ruby-dev:25699] * ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check [ruby-dev:25675] * misc/ruby-mode.el: [ruby-core:04415] * lib/rdoc/generators/html_generator.rb: [ruby-core:04412] * lib/rdoc/generators/ri_generator.rb: ditto. * struct.c (make_struct): fixed: [ruby-core:04402] * ext/curses/curses.c (window_color_set): [ruby-core:04393] * ext/socket/socket.c (Init_socket): SO_REUSEPORT added. [ruby-talk:130092] * object.c: [ruby-doc:818] * parse.y (open_args): fix too verbose warnings for the space before argument parentheses. [ruby-dev:25492] * parse.y (parser_yylex): ditto. * parse.y (parser_yylex): the first expression in the parentheses should not be a command. [ruby-dev:25492] * lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330] * object.c (Init_Object): remove Object#type. [ruby-core:04335] * st.c (st_foreach): report success/failure by return value. [ruby-Bugs-1396] * parse.y: forgot to initialize parser struct. [ruby-dev:25492] * parse.y (parser_yylex): no tLABEL on EXPR_BEG. [ruby-talk:127711] * document updates - [ruby-core:04296], [ruby-core:04301], [ruby-core:04302], [ruby-core:04307] * dir.c (rb_push_glob): should work for NUL delimited patterns. * dir.c (rb_glob2): should aware of offset in the pattern. * string.c (rb_str_new4): should propagate taintedness. * env.h: rename member names in struct FRAME; last_func -> callee, orig_func -> this_func, last_class -> this_class. * struct.c (rb_struct_set): use original method name, not callee name, to retrieve member slot. [ruby-core:04268] * time.c (time_strftime): protect from format modification from GC finalizers. * object.c (Init_Object): remove rb_obj_id_obsolete() * eval.c (rb_mod_define_method): incomplete subclass check. [ruby-dev:25464] * gc.c (rb_data_object_alloc): klass may be NULL. [ruby-list:40498] * bignum.c (rb_big_rand): should return positive random number. [ruby-dev:25401] * bignum.c (rb_big_rand): do not use rb_big_modulo to generate random bignums. [ruby-dev:25396] * variable.c (rb_autoload): [ruby-dev:25373] * eval.c (svalue_to_avalue): [ruby-dev:25366] * string.c (rb_str_justify): [ruby-dev:25367] * io.c (rb_f_select): [ruby-dev:25312] * ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072] * struct.c (make_struct): [ruby-dev:25249] * dir.c (dir_open_dir): new function. [ruby-dev:25242] * io.c (rb_f_open): add type check for return value from to_open. * lib/pstore.rb (PStore#transaction): Use the empty content when a file is not found. [ruby-dev:24561] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 01:47:45 -05:00
self.use_tracer = IRB.conf[:USE_TRACER] if IRB.conf[:USE_TRACER]
self.use_loader = IRB.conf[:USE_LOADER] if IRB.conf[:USE_LOADER]
self.eval_history = IRB.conf[:EVAL_HISTORY] if IRB.conf[:EVAL_HISTORY]
@ignore_sigint = IRB.conf[:IGNORE_SIGINT]
@ignore_eof = IRB.conf[:IGNORE_EOF]
@back_trace_limit = IRB.conf[:BACK_TRACE_LIMIT]
self.prompt_mode = IRB.conf[:PROMPT_MODE]
if IRB.conf[:SINGLE_IRB] or !defined?(IRB::JobManager)
@irb_name = IRB.conf[:IRB_NAME]
else
@irb_name = IRB.conf[:IRB_NAME]+"#"+IRB.JobManager.n_jobs.to_s
end
@irb_path = "(" + @irb_name + ")"
case input_method
when nil
@io = nil
case use_multiline?
when nil
if STDIN.tty? && IRB.conf[:PROMPT_MODE] != :INF_RUBY && !use_singleline?
# Both of multiline mode and singleline mode aren't specified.
@io = ReidlineInputMethod.new
else
@io = nil
end
when false
@io = nil
when true
@io = ReidlineInputMethod.new
end
unless @io
case use_singleline?
when nil
if (defined?(ReadlineInputMethod) && STDIN.tty? &&
IRB.conf[:PROMPT_MODE] != :INF_RUBY)
@io = ReadlineInputMethod.new
else
@io = nil
end
when false
@io = nil
when true
if defined?(ReadlineInputMethod)
@io = ReadlineInputMethod.new
else
@io = nil
end
else
@io = nil
end
end
@io = StdioInputMethod.new unless @io
when String
@io = FileInputMethod.new(input_method)
@irb_name = File.basename(input_method)
@irb_path = input_method
else
@io = input_method
end
self.save_history = IRB.conf[:SAVE_HISTORY] if IRB.conf[:SAVE_HISTORY]
@echo = IRB.conf[:ECHO]
if @echo.nil?
@echo = true
end
@echo_on_assignment = IRB.conf[:ECHO_ON_ASSIGNMENT]
if @echo_on_assignment.nil?
@echo_on_assignment = false
end
@newline_before_multiline_output = IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]
if @newline_before_multiline_output.nil?
@newline_before_multiline_output = true
end
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,
# ReidlineInputMethod, 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 multiline editor mode is enabled or not.
#
# A copy of the default <code>IRB.conf[:USE_MULTILINE]</code>
attr_reader :use_multiline
# Whether singleline editor mode is enabled or not.
#
# A copy of the default <code>IRB.conf[:USE_SINGLELINE]</code>
attr_reader :use_singleline
# Whether colorization is enabled or not.
#
# A copy of the default <code>IRB.conf[:USE_COLORIZE]</code>
attr_reader :use_colorize
# 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
#
# See IRB@Customizing+the+IRB+Prompt for more information.
attr_accessor :prompt_i
# IRB prompt for continuated strings
#
# See IRB@Customizing+the+IRB+Prompt for more information.
attr_accessor :prompt_s
# IRB prompt for continuated statement (e.g. immediately after an +if+)
#
# See IRB@Customizing+the+IRB+Prompt for more information.
attr_accessor :prompt_c
# See IRB@Customizing+the+IRB+Prompt for more information.
attr_accessor :prompt_n
# Can be either the default <code>IRB.conf[:AUTO_INDENT]</code>, or the
# mode set by #prompt_mode=
#
# To disable auto-indentation in irb:
#
# IRB.conf[:AUTO_INDENT] = false
#
# or
#
# irb_context.auto_indent_mode = false
#
# or
#
# IRB.CurrentContext.auto_indent_mode = false
#
# See IRB@Configuration for more information.
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.
#
# If set to +false+, <code>^C</code> will quit irb.
#
# If set to +true+,
#
# * during input: cancel input then return to top level.
# * during execute: abandon current execution.
attr_accessor :ignore_sigint
# Whether <code>^D</code> (+control-d+) will be ignored or not.
#
# 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 <code>IRB.conf[:ECHO]</code> if available, or defaults to +true+.
#
# puts "hello"
# # hello
# #=> nil
# IRB.CurrentContext.echo = false
# puts "omg"
# # omg
attr_accessor :echo
# Whether to echo for assignment expressions
#
# Uses <code>IRB.conf[:ECHO_ON_ASSIGNMENT]</code> if available, or defaults to +false+.
#
# a = "omg"
# IRB.CurrentContext.echo_on_assignment = true
# a = "omg"
# #=> omg
attr_accessor :echo_on_assignment
# Whether a newline is put before multiline output.
#
# Uses <code>IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]</code> if available,
# or defaults to +true+.
#
# "abc\ndef"
# #=>
# abc
# def
# IRB.CurrentContext.newline_before_multiline_output = false
# "abc\ndef"
# #=> abc
# def
attr_accessor :newline_before_multiline_output
# Whether verbose messages are displayed or not.
#
# A copy of the default <code>IRB.conf[:VERBOSE]</code>
attr_accessor :verbose
# The limit of backtrace lines displayed as top +n+ and tail +n+.
#
# The default value is 16.
#
# Can also be set using the +--back-trace-limit+ command line option.
#
# See IRB@Command+line+options for more command line options.
attr_accessor :back_trace_limit
# Alias for #use_multiline
alias use_multiline? use_multiline
# Alias for #use_singleline
alias use_singleline? use_singleline
# backward compatibility
alias use_reidline use_multiline
# backward compatibility
alias use_reidline? use_multiline
# backward compatibility
alias use_readline use_singleline
# backward compatibility
alias use_readline? use_singleline
# Alias for #use_colorize
alias use_colorize? use_colorize
# Alias for #rc
alias rc? rc
alias ignore_sigint? ignore_sigint
alias ignore_eof? ignore_eof
alias echo? echo
alias echo_on_assignment? echo_on_assignment
alias newline_before_multiline_output? newline_before_multiline_output
# Returns whether messages are displayed or not.
def verbose?
if @verbose.nil?
if @io.kind_of?(ReidlineInputMethod)
false
elsif defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod)
false
elsif !STDIN.tty? or @io.kind_of?(FileInputMethod)
true
else
false
end
else
@verbose
end
end
# Whether #verbose? is +true+, and +input_method+ is either
# StdioInputMethod or ReidlineInputMethod or ReadlineInputMethod, see #io
# for more information.
def prompting?
verbose? || (STDIN.tty? && @io.kind_of?(StdioInputMethod) ||
@io.kind_of?(ReidlineInputMethod) ||
(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.local_variable_set :_, 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]
@prompt_i = pconf[:PROMPT_I]
@prompt_s = pconf[:PROMPT_S]
@prompt_c = pconf[:PROMPT_C]
@prompt_n = pconf[:PROMPT_N]
@return_format = pconf[:RETURN]
if ai = pconf.include?(:AUTO_INDENT)
@auto_indent_mode = ai
else
@auto_indent_mode = IRB.conf[:AUTO_INDENT]
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
# Specifies the inspect mode with +opt+:
#
# +true+:: display +inspect+
# +false+:: display +to_s+
# +nil+:: inspect mode in non-math mode,
# non-inspect mode in math mode
#
# See IRB::Inspector for more information.
#
# Can also be set using the +--inspect+ and +--noinspect+ command line
# options.
#
# See IRB@Command+line+options for more command line options.
def inspect_mode=(opt)
if i = Inspector::INSPECTORS[opt]
@inspect_mode = opt
@inspect_method = i
i.init
else
case opt
when nil
if Inspector.keys_with_inspector(Inspector::INSPECTORS[true]).include?(@inspect_mode)
self.inspect_mode = false
elsif Inspector.keys_with_inspector(Inspector::INSPECTORS[false]).include?(@inspect_mode)
self.inspect_mode = true
else
puts "Can't switch inspect mode."
return
end
when /^\s*\{.*\}\s*$/
begin
inspector = eval "proc#{opt}"
rescue Exception
puts "Can't switch inspect mode(#{opt})."
return
end
self.inspect_mode = inspector
when Proc
self.inspect_mode = IRB::Inspector(opt)
when Inspector
prefix = "usr%d"
i = 1
while Inspector::INSPECTORS[format(prefix, i)]; i += 1; end
@inspect_mode = format(prefix, i)
@inspect_method = opt
Inspector.def_inspector(format(prefix, i), @inspect_method)
else
puts "Can't switch inspect mode(#{opt})."
return
end
end
print "Switch to#{unless @inspect_mode; ' non';end} inspect mode.\n" if verbose?
@inspect_mode
end
def evaluate(line, line_no, exception: nil) # :nodoc:
@line_no = line_no
if exception
line_no -= 1
line = "begin ::Kernel.raise _; rescue _.class\n#{line}\n""end"
@workspace.local_variable_set(:_, exception)
end
set_last_value(@workspace.evaluate(self, line, irb_path, line_no))
end
def inspect_last_value # :nodoc:
@inspect_method.inspect_value(@last_value)
end
alias __exit__ exit
# Exits the current session, see IRB.irb_exit
def exit(ret = 0)
IRB.irb_exit(@irb, ret)
end
NOPRINTING_IVARS = ["@last_value"] # :nodoc:
NO_INSPECTING_IVARS = ["@irb", "@io"] # :nodoc:
IDNAME_IVARS = ["@prompt_mode"] # :nodoc:
alias __inspect__ inspect
def inspect # :nodoc:
array = []
for ivar in instance_variables.sort{|e1, e2| e1 <=> e2}
ivar = ivar.to_s
name = ivar.sub(/^@(.*)$/, '\1')
val = instance_eval(ivar)
case ivar
when *NOPRINTING_IVARS
array.push format("conf.%s=%s", name, "...")
when *NO_INSPECTING_IVARS
array.push format("conf.%s=%s", name, val.to_s)
when *IDNAME_IVARS
array.push format("conf.%s=:%s", name, val.id2name)
else
array.push format("conf.%s=%s", name, val.inspect)
end
end
array.join("\n")
end
alias __to_s__ to_s
alias to_s inspect
end
end