summaryrefslogtreecommitdiff
path: root/lib/irb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/irb')
-rw-r--r--lib/irb/.document1
-rw-r--r--lib/irb/cmd/backtrace.rb21
-rw-r--r--lib/irb/cmd/break.rb21
-rw-r--r--lib/irb/cmd/catch.rb21
-rw-r--r--lib/irb/cmd/chws.rb36
-rw-r--r--lib/irb/cmd/continue.rb17
-rw-r--r--lib/irb/cmd/debug.rb136
-rw-r--r--lib/irb/cmd/delete.rb17
-rw-r--r--lib/irb/cmd/edit.rb61
-rw-r--r--lib/irb/cmd/finish.rb17
-rw-r--r--lib/irb/cmd/fork.rb34
-rw-r--r--lib/irb/cmd/help.rb57
-rw-r--r--lib/irb/cmd/info.rb21
-rw-r--r--lib/irb/cmd/irb_info.rb37
-rw-r--r--lib/irb/cmd/load.rb76
-rw-r--r--lib/irb/cmd/ls.rb116
-rw-r--r--lib/irb/cmd/measure.rb48
-rw-r--r--lib/irb/cmd/next.rb17
-rw-r--r--lib/irb/cmd/nop.rb66
-rw-r--r--lib/irb/cmd/pushws.rb45
-rw-r--r--lib/irb/cmd/show_cmds.rb39
-rw-r--r--lib/irb/cmd/show_source.rb112
-rw-r--r--lib/irb/cmd/step.rb17
-rw-r--r--lib/irb/cmd/subirb.rb66
-rw-r--r--lib/irb/cmd/whereami.rb25
-rw-r--r--lib/irb/color.rb266
-rw-r--r--lib/irb/color_printer.rb50
-rw-r--r--lib/irb/completion.rb483
-rw-r--r--lib/irb/context.rb555
-rw-r--r--lib/irb/easter-egg.rb138
-rw-r--r--lib/irb/ext/change-ws.rb39
-rw-r--r--lib/irb/ext/history.rb149
-rw-r--r--lib/irb/ext/loader.rb148
-rw-r--r--lib/irb/ext/multi-irb.rb258
-rw-r--r--lib/irb/ext/save-history.rb125
-rw-r--r--lib/irb/ext/tracer.rb79
-rw-r--r--lib/irb/ext/use-loader.rb69
-rw-r--r--lib/irb/ext/workspaces.rb60
-rw-r--r--lib/irb/extend-command.rb428
-rw-r--r--lib/irb/frame.rb80
-rw-r--r--lib/irb/help.rb30
-rw-r--r--lib/irb/init.rb444
-rw-r--r--lib/irb/input-method.rb478
-rw-r--r--lib/irb/inspector.rb121
-rw-r--r--lib/irb/irb.gemspec40
-rw-r--r--lib/irb/lc/error.rb62
-rw-r--r--lib/irb/lc/help-message51
-rw-r--r--lib/irb/lc/ja/encoding_aliases.rb13
-rw-r--r--lib/irb/lc/ja/error.rb63
-rw-r--r--lib/irb/lc/ja/help-message45
-rw-r--r--lib/irb/locale.rb186
-rw-r--r--lib/irb/magic-file.rb38
-rw-r--r--lib/irb/notifier.rb230
-rw-r--r--lib/irb/output-method.rb86
-rw-r--r--lib/irb/ruby-lex.rb851
-rw-r--r--lib/irb/ruby_logo.aa37
-rw-r--r--lib/irb/src_encoding.rb7
-rw-r--r--lib/irb/version.rb11
-rw-r--r--lib/irb/workspace.rb167
-rw-r--r--lib/irb/ws-for-case-2.rb9
-rw-r--r--lib/irb/xmp.rb164
61 files changed, 0 insertions, 7184 deletions
diff --git a/lib/irb/.document b/lib/irb/.document
deleted file mode 100644
index 3b0d6fa4ed..0000000000
--- a/lib/irb/.document
+++ /dev/null
@@ -1 +0,0 @@
-**/*.rb
diff --git a/lib/irb/cmd/backtrace.rb b/lib/irb/cmd/backtrace.rb
deleted file mode 100644
index f632894618..0000000000
--- a/lib/irb/cmd/backtrace.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Backtrace < DebugCommand
- def self.transform_args(args)
- args&.dump
- end
-
- def execute(*args)
- super(pre_cmds: ["backtrace", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/break.rb b/lib/irb/cmd/break.rb
deleted file mode 100644
index df259a90ca..0000000000
--- a/lib/irb/cmd/break.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Break < DebugCommand
- def self.transform_args(args)
- args&.dump
- end
-
- def execute(args = nil)
- super(pre_cmds: "break #{args}")
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/catch.rb b/lib/irb/cmd/catch.rb
deleted file mode 100644
index 40b62c7533..0000000000
--- a/lib/irb/cmd/catch.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Catch < DebugCommand
- def self.transform_args(args)
- args&.dump
- end
-
- def execute(*args)
- super(pre_cmds: ["catch", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/chws.rb b/lib/irb/cmd/chws.rb
deleted file mode 100644
index 44712fa445..0000000000
--- a/lib/irb/cmd/chws.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: false
-#
-# change-ws.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "nop"
-require_relative "../ext/change-ws"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
-
- class CurrentWorkingWorkspace < Nop
- category "IRB"
- description "Show the current workspace."
-
- def execute(*obj)
- irb_context.main
- end
- end
-
- class ChangeWorkspace < Nop
- category "IRB"
- description "Change the current workspace to an object."
-
- def execute(*obj)
- irb_context.change_workspace(*obj)
- irb_context.main
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/continue.rb b/lib/irb/cmd/continue.rb
deleted file mode 100644
index 9136177eef..0000000000
--- a/lib/irb/cmd/continue.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Continue < DebugCommand
- def execute(*args)
- super(do_cmds: ["continue", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/debug.rb b/lib/irb/cmd/debug.rb
deleted file mode 100644
index 7d39b9fa27..0000000000
--- a/lib/irb/cmd/debug.rb
+++ /dev/null
@@ -1,136 +0,0 @@
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Debug < Nop
- category "Debugging"
- description "Start the debugger of debug.gem."
-
- BINDING_IRB_FRAME_REGEXPS = [
- '<internal:prelude>',
- binding.method(:irb).source_location.first,
- ].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ }
- IRB_DIR = File.expand_path('..', __dir__)
-
- def execute(pre_cmds: nil, do_cmds: nil)
- unless binding_irb?
- puts "`debug` command is only available when IRB is started with binding.irb"
- return
- end
-
- unless setup_debugger
- puts <<~MSG
- You need to install the debug gem before using this command.
- If you use `bundle exec`, please add `gem "debug"` into your Gemfile.
- MSG
- return
- end
-
- options = { oneshot: true, hook_call: false }
- if pre_cmds || do_cmds
- options[:command] = ['irb', pre_cmds, do_cmds]
- end
- if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src])
- options[:skip_src] = true
- end
-
- # To make debugger commands like `next` or `continue` work without asking
- # the user to quit IRB after that, we need to exit IRB first and then hit
- # a TracePoint on #debug_break.
- file, lineno = IRB::Irb.instance_method(:debug_break).source_location
- DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, **options)
- # exit current Irb#run call
- throw :IRB_EXIT
- end
-
- private
-
- def binding_irb?
- caller.any? do |frame|
- BINDING_IRB_FRAME_REGEXPS.any? do |regexp|
- frame.match?(regexp)
- end
- end
- end
-
- module SkipPathHelperForIRB
- def skip_internal_path?(path)
- # The latter can be removed once https://github.com/ruby/debug/issues/866 is resolved
- super || path.match?(IRB_DIR) || path.match?('<internal:prelude>')
- end
- end
-
- def setup_debugger
- unless defined?(DEBUGGER__::SESSION)
- begin
- require "debug/session"
- rescue LoadError # debug.gem is not written in Gemfile
- return false unless load_bundled_debug_gem
- end
- DEBUGGER__.start(nonstop: true)
- end
-
- unless DEBUGGER__.respond_to?(:capture_frames_without_irb)
- DEBUGGER__.singleton_class.send(:alias_method, :capture_frames_without_irb, :capture_frames)
-
- def DEBUGGER__.capture_frames(*args)
- frames = capture_frames_without_irb(*args)
- frames.reject! do |frame|
- frame.realpath&.start_with?(IRB_DIR) || frame.path == "<internal:prelude>"
- end
- frames
- end
-
- DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB)
- end
-
- true
- end
-
- # This is used when debug.gem is not written in Gemfile. Even if it's not
- # installed by `bundle install`, debug.gem is installed by default because
- # it's a bundled gem. This method tries to activate and load that.
- def load_bundled_debug_gem
- # Discover latest debug.gem under GEM_PATH
- debug_gem = Gem.paths.path.flat_map { |path| Dir.glob("#{path}/gems/debug-*") }.select do |path|
- File.basename(path).match?(/\Adebug-\d+\.\d+\.\d+(\w+)?\z/)
- end.sort_by do |path|
- Gem::Version.new(File.basename(path).delete_prefix('debug-'))
- end.last
- return false unless debug_gem
-
- # Discover debug/debug.so under extensions for Ruby 3.2+
- ext_name = "/debug/debug.#{RbConfig::CONFIG['DLEXT']}"
- ext_path = Gem.paths.path.flat_map do |path|
- Dir.glob("#{path}/extensions/**/#{File.basename(debug_gem)}#{ext_name}")
- end.first
-
- # Attempt to forcibly load the bundled gem
- if ext_path
- $LOAD_PATH << ext_path.delete_suffix(ext_name)
- end
- $LOAD_PATH << "#{debug_gem}/lib"
- begin
- require "debug/session"
- puts "Loaded #{File.basename(debug_gem)}"
- true
- rescue LoadError
- false
- end
- end
- end
-
- class DebugCommand < Debug
- def self.category
- "Debugging"
- end
-
- def self.description
- command_name = self.name.split("::").last.downcase
- "Start the debugger of debug.gem and run its `#{command_name}` command."
- end
- end
- end
-end
diff --git a/lib/irb/cmd/delete.rb b/lib/irb/cmd/delete.rb
deleted file mode 100644
index aeb26d2572..0000000000
--- a/lib/irb/cmd/delete.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Delete < DebugCommand
- def execute(*args)
- super(pre_cmds: ["delete", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/edit.rb b/lib/irb/cmd/edit.rb
deleted file mode 100644
index 0103891cf4..0000000000
--- a/lib/irb/cmd/edit.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-require 'shellwords'
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Edit < Nop
- category "Misc"
- description 'Open a file with the editor command defined with `ENV["EDITOR"]`.'
-
- class << self
- def transform_args(args)
- # Return a string literal as is for backward compatibility
- if args.nil? || args.empty? || string_literal?(args)
- args
- else # Otherwise, consider the input as a String for convenience
- args.strip.dump
- end
- end
- end
-
- def execute(*args)
- path = args.first
-
- if path.nil? && (irb_path = @irb_context.irb_path)
- path = irb_path
- end
-
- if !File.exist?(path)
- require_relative "show_source"
-
- source =
- begin
- ShowSource.find_source(path, @irb_context)
- rescue NameError
- # if user enters a path that doesn't exist, it'll cause NameError when passed here because find_source would try to evaluate it as well
- # in this case, we should just ignore the error
- end
-
- if source && File.exist?(source.file)
- path = source.file
- else
- puts "Can not find file: #{path}"
- return
- end
- end
-
- if editor = ENV['EDITOR']
- puts "command: '#{editor}'"
- puts " path: #{path}"
- system(*Shellwords.split(editor), path)
- else
- puts "Can not find editor setting: ENV['EDITOR']"
- end
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/finish.rb b/lib/irb/cmd/finish.rb
deleted file mode 100644
index 29f100feb5..0000000000
--- a/lib/irb/cmd/finish.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Finish < DebugCommand
- def execute(*args)
- super(do_cmds: ["finish", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/fork.rb b/lib/irb/cmd/fork.rb
deleted file mode 100644
index 1cd235997f..0000000000
--- a/lib/irb/cmd/fork.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: false
-#
-# fork.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Fork < Nop
- def execute
- pid = __send__ ExtendCommand.irb_original_method_name("fork")
- unless pid
- class << self
- alias_method :exit, ExtendCommand.irb_original_method_name('exit')
- end
- if block_given?
- begin
- yield
- ensure
- exit
- end
- end
- end
- pid
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/help.rb b/lib/irb/cmd/help.rb
deleted file mode 100644
index 9896fa9db1..0000000000
--- a/lib/irb/cmd/help.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: false
-#
-# help.rb - helper using ri
-#
-
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Help < Nop
- class << self
- def transform_args(args)
- # Return a string literal as is for backward compatibility
- if args.empty? || string_literal?(args)
- args
- else # Otherwise, consider the input as a String for convenience
- args.strip.dump
- end
- end
- end
-
- category "Context"
- description "Enter the mode to look up RI documents."
-
- def execute(*names)
- require 'rdoc/ri/driver'
- opts = RDoc::RI::Driver.process_args([])
- IRB::ExtendCommand::Help.const_set(:Ri, RDoc::RI::Driver.new(opts))
- rescue LoadError, SystemExit
- IRB::ExtendCommand::Help.remove_method(:execute)
- # raise NoMethodError in ensure
- else
- def execute(*names)
- if names.empty?
- Ri.interactive
- return
- end
- names.each do |name|
- begin
- Ri.display_name(name.to_s)
- rescue RDoc::RI::Error
- puts $!.message
- end
- end
- nil
- end
- nil
- ensure
- execute(*names)
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/info.rb b/lib/irb/cmd/info.rb
deleted file mode 100644
index 2c0a32b34f..0000000000
--- a/lib/irb/cmd/info.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Info < DebugCommand
- def self.transform_args(args)
- args&.dump
- end
-
- def execute(*args)
- super(pre_cmds: ["info", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/irb_info.rb b/lib/irb/cmd/irb_info.rb
deleted file mode 100644
index da11e8d40b..0000000000
--- a/lib/irb/cmd/irb_info.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class IrbInfo < Nop
- category "IRB"
- description "Show information about IRB."
-
- def execute
- Class.new {
- def inspect
- str = "Ruby version: #{RUBY_VERSION}\n"
- str += "IRB version: #{IRB.version}\n"
- str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
- str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
- str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
- str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
- str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
- str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
- if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
- codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
- str += "Code page: #{codepage}\n"
- end
- str
- end
- alias_method :to_s, :inspect
- }.new
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/load.rb b/lib/irb/cmd/load.rb
deleted file mode 100644
index a3e797a7e0..0000000000
--- a/lib/irb/cmd/load.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: false
-#
-# load.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "nop"
-require_relative "../ext/loader"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class LoaderCommand < Nop
- include IrbLoader
-
- def raise_cmd_argument_error
- raise CommandArgumentError.new("Please specify the file name.")
- end
- end
-
- class Load < LoaderCommand
- category "IRB"
- description "Load a Ruby file."
-
- def execute(file_name = nil, priv = nil)
- raise_cmd_argument_error unless file_name
- irb_load(file_name, priv)
- end
- end
-
- class Require < LoaderCommand
- category "IRB"
- description "Require a Ruby file."
- def execute(file_name = nil)
- raise_cmd_argument_error unless file_name
-
- rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
- return false if $".find{|f| f =~ rex}
-
- case file_name
- when /\.rb$/
- begin
- if irb_load(file_name)
- $".push file_name
- return true
- end
- rescue LoadError
- end
- when /\.(so|o|sl)$/
- return ruby_require(file_name)
- end
-
- begin
- irb_load(f = file_name + ".rb")
- $".push f
- return true
- rescue LoadError
- return ruby_require(file_name)
- end
- end
- end
-
- class Source < LoaderCommand
- category "IRB"
- description "Loads a given file in the current session."
-
- def execute(file_name = nil)
- raise_cmd_argument_error unless file_name
-
- source_file(file_name)
- end
- end
- end
- # :startdoc:
-end
diff --git a/lib/irb/cmd/ls.rb b/lib/irb/cmd/ls.rb
deleted file mode 100644
index b65fae2bf1..0000000000
--- a/lib/irb/cmd/ls.rb
+++ /dev/null
@@ -1,116 +0,0 @@
-# frozen_string_literal: true
-
-require "reline"
-require_relative "nop"
-require_relative "../color"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Ls < Nop
- category "Context"
- description "Show methods, constants, and variables. `-g [query]` or `-G [query]` allows you to filter out the output."
-
- def self.transform_args(args)
- if match = args&.match(/\A(?<args>.+\s|)(-g|-G)\s+(?<grep>[^\s]+)\s*\n\z/)
- args = match[:args]
- "#{args}#{',' unless args.chomp.empty?} grep: /#{match[:grep]}/"
- else
- args
- end
- end
-
- def execute(*arg, grep: nil)
- o = Output.new(grep: grep)
-
- obj = arg.empty? ? irb_context.workspace.main : arg.first
- locals = arg.empty? ? irb_context.workspace.binding.local_variables : []
- klass = (obj.class == Class || obj.class == Module ? obj : obj.class)
-
- o.dump("constants", obj.constants) if obj.respond_to?(:constants)
- dump_methods(o, klass, obj)
- o.dump("instance variables", obj.instance_variables)
- o.dump("class variables", klass.class_variables)
- o.dump("locals", locals)
- nil
- end
-
- def dump_methods(o, klass, obj)
- singleton_class = begin obj.singleton_class; rescue TypeError; nil end
- maps = class_method_map((singleton_class || klass).ancestors)
- maps.each do |mod, methods|
- name = mod == singleton_class ? "#{klass}.methods" : "#{mod}#methods"
- o.dump(name, methods)
- end
- end
-
- def class_method_map(classes)
- dumped = Array.new
- classes.reject { |mod| mod >= Object }.map do |mod|
- methods = mod.public_instance_methods(false).select do |m|
- dumped.push(m) unless dumped.include?(m)
- end
- [mod, methods]
- end.reverse
- end
-
- class Output
- MARGIN = " "
-
- def initialize(grep: nil)
- @grep = grep
- @line_width = screen_width - MARGIN.length # right padding
- end
-
- def dump(name, strs)
- strs = strs.grep(@grep) if @grep
- strs = strs.sort
- return if strs.empty?
-
- # Attempt a single line
- print "#{Color.colorize(name, [:BOLD, :BLUE])}: "
- if fits_on_line?(strs, cols: strs.size, offset: "#{name}: ".length)
- puts strs.join(MARGIN)
- return
- end
- puts
-
- # Dump with the largest # of columns that fits on a line
- cols = strs.size
- until fits_on_line?(strs, cols: cols, offset: MARGIN.length) || cols == 1
- cols -= 1
- end
- widths = col_widths(strs, cols: cols)
- strs.each_slice(cols) do |ss|
- puts ss.map.with_index { |s, i| "#{MARGIN}%-#{widths[i]}s" % s }.join
- end
- end
-
- private
-
- def fits_on_line?(strs, cols:, offset: 0)
- width = col_widths(strs, cols: cols).sum + MARGIN.length * (cols - 1)
- width <= @line_width - offset
- end
-
- def col_widths(strs, cols:)
- cols.times.map do |col|
- (col...strs.size).step(cols).map do |i|
- strs[i].length
- end.max
- end
- end
-
- def screen_width
- Reline.get_screen_size.last
- rescue Errno::EINVAL # in `winsize': Invalid argument - <STDIN>
- 80
- end
- end
- private_constant :Output
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/measure.rb b/lib/irb/cmd/measure.rb
deleted file mode 100644
index 9122e2dac9..0000000000
--- a/lib/irb/cmd/measure.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Measure < Nop
- category "Misc"
- description "`measure` enables the mode to measure processing time. `measure :off` disables it."
-
- def initialize(*args)
- super(*args)
- end
-
- def execute(type = nil, arg = nil, &block)
- # Please check IRB.init_config in lib/irb/init.rb that sets
- # IRB.conf[:MEASURE_PROC] to register default "measure" methods,
- # "measure :time" (abbreviated as "measure") and "measure :stackprof".
- case type
- when :off
- IRB.conf[:MEASURE] = nil
- IRB.unset_measure_callback(arg)
- when :list
- IRB.conf[:MEASURE_CALLBACKS].each do |type_name, _, arg_val|
- puts "- #{type_name}" + (arg_val ? "(#{arg_val.inspect})" : '')
- end
- when :on
- IRB.conf[:MEASURE] = true
- added = IRB.set_measure_callback(type, arg)
- puts "#{added[0]} is added." if added
- else
- if block_given?
- IRB.conf[:MEASURE] = true
- added = IRB.set_measure_callback(&block)
- puts "#{added[0]} is added." if added
- else
- IRB.conf[:MEASURE] = true
- added = IRB.set_measure_callback(type, arg)
- puts "#{added[0]} is added." if added
- end
- end
- nil
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/next.rb b/lib/irb/cmd/next.rb
deleted file mode 100644
index d29c82e7fc..0000000000
--- a/lib/irb/cmd/next.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Next < DebugCommand
- def execute(*args)
- super(do_cmds: ["next", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/nop.rb b/lib/irb/cmd/nop.rb
deleted file mode 100644
index 34facc7578..0000000000
--- a/lib/irb/cmd/nop.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: false
-#
-# nop.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class CommandArgumentError < StandardError; end
-
- class Nop
- class << self
- def category(category = nil)
- @category = category if category
- @category
- end
-
- def description(description = nil)
- @description = description if description
- @description
- end
-
- private
-
- def string_literal?(args)
- sexp = Ripper.sexp(args)
- sexp && sexp.size == 2 && sexp.last&.first&.first == :string_literal
- end
- end
-
- if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0"
- def self.execute(conf, *opts, **kwargs, &block)
- command = new(conf)
- command.execute(*opts, **kwargs, &block)
- rescue CommandArgumentError => e
- puts e.message
- end
- else
- def self.execute(conf, *opts, &block)
- command = new(conf)
- command.execute(*opts, &block)
- rescue CommandArgumentError => e
- puts e.message
- end
- end
-
- def initialize(conf)
- @irb_context = conf
- end
-
- attr_reader :irb_context
-
- def irb
- @irb_context.irb
- end
-
- def execute(*opts)
- #nop
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/pushws.rb b/lib/irb/cmd/pushws.rb
deleted file mode 100644
index d64d822182..0000000000
--- a/lib/irb/cmd/pushws.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: false
-#
-# change-ws.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "nop"
-require_relative "../ext/workspaces"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Workspaces < Nop
- category "IRB"
- description "Show workspaces."
-
- def execute(*obj)
- irb_context.workspaces.collect{|ws| ws.main}
- end
- end
-
- class PushWorkspace < Workspaces
- category "IRB"
- description "Push an object to the workspace stack."
-
- def execute(*obj)
- irb_context.push_workspace(*obj)
- super
- end
- end
-
- class PopWorkspace < Workspaces
- category "IRB"
- description "Pop a workspace from the workspace stack."
-
- def execute(*obj)
- irb_context.pop_workspace(*obj)
- super
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/show_cmds.rb b/lib/irb/cmd/show_cmds.rb
deleted file mode 100644
index acced27d48..0000000000
--- a/lib/irb/cmd/show_cmds.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require "stringio"
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class ShowCmds < Nop
- category "IRB"
- description "List all available commands and their description."
-
- def execute(*args)
- commands_info = IRB::ExtendCommandBundle.all_commands_info
- commands_grouped_by_categories = commands_info.group_by { |cmd| cmd[:category] }
- longest_cmd_name_length = commands_info.map { |c| c[:display_name] }.max { |a, b| a.length <=> b.length }.length
-
- output = StringIO.new
-
- commands_grouped_by_categories.each do |category, cmds|
- output.puts Color.colorize(category, [:BOLD])
-
- cmds.each do |cmd|
- output.puts " #{cmd[:display_name].to_s.ljust(longest_cmd_name_length)} #{cmd[:description]}"
- end
-
- output.puts
- end
-
- puts output.string
-
- nil
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/show_source.rb b/lib/irb/cmd/show_source.rb
deleted file mode 100644
index eb21533b56..0000000000
--- a/lib/irb/cmd/show_source.rb
+++ /dev/null
@@ -1,112 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "nop"
-require_relative "../color"
-require_relative "../ruby-lex"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class ShowSource < Nop
- category "Context"
- description "Show the source code of a given method or constant."
-
- class << self
- def transform_args(args)
- # Return a string literal as is for backward compatibility
- if args.empty? || string_literal?(args)
- args
- else # Otherwise, consider the input as a String for convenience
- args.strip.dump
- end
- end
-
- def find_source(str, irb_context)
- case str
- when /\A[A-Z]\w*(::[A-Z]\w*)*\z/ # Const::Name
- eval(str, irb_context.workspace.binding) # trigger autoload
- base = irb_context.workspace.binding.receiver.yield_self { |r| r.is_a?(Module) ? r : Object }
- file, line = base.const_source_location(str) if base.respond_to?(:const_source_location) # Ruby 2.7+
- when /\A(?<owner>[A-Z]\w*(::[A-Z]\w*)*)#(?<method>[^ :.]+)\z/ # Class#method
- owner = eval(Regexp.last_match[:owner], irb_context.workspace.binding)
- method = Regexp.last_match[:method]
- if owner.respond_to?(:instance_method) && owner.instance_methods.include?(method.to_sym)
- file, line = owner.instance_method(method).source_location
- end
- when /\A((?<receiver>.+)(\.|::))?(?<method>[^ :.]+)\z/ # method, receiver.method, receiver::method
- receiver = eval(Regexp.last_match[:receiver] || 'self', irb_context.workspace.binding)
- method = Regexp.last_match[:method]
- file, line = receiver.method(method).source_location if receiver.respond_to?(method)
- end
- if file && line
- Source.new(file: file, first_line: line, last_line: find_end(file, line, irb_context))
- end
- end
-
- private
-
- def find_end(file, first_line, irb_context)
- return first_line unless File.exist?(file)
- lex = RubyLex.new(irb_context)
- lines = File.read(file).lines[(first_line - 1)..-1]
- tokens = RubyLex.ripper_lex_without_warning(lines.join)
- prev_tokens = []
-
- # chunk with line number
- tokens.chunk { |tok| tok.pos[0] }.each do |lnum, chunk|
- code = lines[0..lnum].join
- prev_tokens.concat chunk
- continue = lex.process_continue(prev_tokens)
- code_block_open = lex.check_code_block(code, prev_tokens)
- if !continue && !code_block_open
- return first_line + lnum
- end
- end
- first_line
- end
- end
-
- def execute(str = nil)
- unless str.is_a?(String)
- puts "Error: Expected a string but got #{str.inspect}"
- return
- end
-
- source = self.class.find_source(str, @irb_context)
- if source && File.exist?(source.file)
- show_source(source)
- else
- puts "Error: Couldn't locate a definition for #{str}"
- end
- nil
- end
-
- private
-
- # @param [IRB::ExtendCommand::ShowSource::Source] source
- def show_source(source)
- puts
- puts "#{bold("From")}: #{source.file}:#{source.first_line}"
- puts
- code = IRB::Color.colorize_code(File.read(source.file))
- puts code.lines[(source.first_line - 1)...source.last_line].join
- puts
- end
-
- def bold(str)
- Color.colorize(str, [:BOLD])
- end
-
- Source = Struct.new(
- :file, # @param [String] - file name
- :first_line, # @param [String] - first line
- :last_line, # @param [String] - last line
- keyword_init: true,
- )
- private_constant :Source
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/step.rb b/lib/irb/cmd/step.rb
deleted file mode 100644
index 2bc74a9d79..0000000000
--- a/lib/irb/cmd/step.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Step < DebugCommand
- def execute(*args)
- super(do_cmds: ["step", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/subirb.rb b/lib/irb/cmd/subirb.rb
deleted file mode 100644
index 5f3e02c988..0000000000
--- a/lib/irb/cmd/subirb.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: false
-#
-# multi.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class MultiIRBCommand < Nop
- def initialize(conf)
- super
- extend_irb_context
- end
-
- private
-
- def extend_irb_context
- # this extension patches IRB context like IRB.CurrentContext
- require_relative "../ext/multi-irb"
- end
- end
-
- class IrbCommand < MultiIRBCommand
- category "IRB"
- description "Start a child IRB."
-
- def execute(*obj)
- IRB.irb(nil, *obj)
- end
- end
-
- class Jobs < MultiIRBCommand
- category "IRB"
- description "List of current sessions."
-
- def execute
- IRB.JobManager
- end
- end
-
- class Foreground < MultiIRBCommand
- category "IRB"
- description "Switches to the session of the given number."
-
- def execute(key = nil)
- raise CommandArgumentError.new("Please specify the id of target IRB job (listed in the `jobs` command).") unless key
- IRB.JobManager.switch(key)
- end
- end
-
- class Kill < MultiIRBCommand
- category "IRB"
- description "Kills the session with the given number."
-
- def execute(*keys)
- IRB.JobManager.kill(*keys)
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/whereami.rb b/lib/irb/cmd/whereami.rb
deleted file mode 100644
index 8f56ba073d..0000000000
--- a/lib/irb/cmd/whereami.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Whereami < Nop
- category "Context"
- description "Show the source code around binding.irb again."
-
- def execute(*)
- code = irb_context.workspace.code_around_binding
- if code
- puts code
- else
- puts "The current context doesn't have code."
- end
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/color.rb b/lib/irb/color.rb
deleted file mode 100644
index 6378e14856..0000000000
--- a/lib/irb/color.rb
+++ /dev/null
@@ -1,266 +0,0 @@
-# frozen_string_literal: true
-require 'reline'
-require 'ripper'
-require_relative 'ruby-lex'
-
-module IRB # :nodoc:
- module Color
- CLEAR = 0
- BOLD = 1
- UNDERLINE = 4
- REVERSE = 7
- RED = 31
- GREEN = 32
- YELLOW = 33
- BLUE = 34
- MAGENTA = 35
- CYAN = 36
-
- TOKEN_KEYWORDS = {
- on_kw: ['nil', 'self', 'true', 'false', '__FILE__', '__LINE__', '__ENCODING__'],
- on_const: ['ENV'],
- }
- private_constant :TOKEN_KEYWORDS
-
- # A constant of all-bit 1 to match any Ripper's state in #dispatch_seq
- ALL = -1
- private_constant :ALL
-
- begin
- # Following pry's colors where possible, but sometimes having a compromise like making
- # backtick and regexp as red (string's color, because they're sharing tokens).
- TOKEN_SEQ_EXPRS = {
- on_CHAR: [[BLUE, BOLD], ALL],
- on_backtick: [[RED, BOLD], ALL],
- on_comment: [[BLUE, BOLD], ALL],
- on_const: [[BLUE, BOLD, UNDERLINE], ALL],
- on_embexpr_beg: [[RED], ALL],
- on_embexpr_end: [[RED], ALL],
- on_embvar: [[RED], ALL],
- on_float: [[MAGENTA, BOLD], ALL],
- on_gvar: [[GREEN, BOLD], ALL],
- on_heredoc_beg: [[RED], ALL],
- on_heredoc_end: [[RED], ALL],
- on_ident: [[BLUE, BOLD], Ripper::EXPR_ENDFN],
- on_imaginary: [[BLUE, BOLD], ALL],
- on_int: [[BLUE, BOLD], ALL],
- on_kw: [[GREEN], ALL],
- on_label: [[MAGENTA], ALL],
- on_label_end: [[RED, BOLD], ALL],
- on_qsymbols_beg: [[RED, BOLD], ALL],
- on_qwords_beg: [[RED, BOLD], ALL],
- on_rational: [[BLUE, BOLD], ALL],
- on_regexp_beg: [[RED, BOLD], ALL],
- on_regexp_end: [[RED, BOLD], ALL],
- on_symbeg: [[YELLOW], ALL],
- on_symbols_beg: [[RED, BOLD], ALL],
- on_tstring_beg: [[RED, BOLD], ALL],
- on_tstring_content: [[RED], ALL],
- on_tstring_end: [[RED, BOLD], ALL],
- on_words_beg: [[RED, BOLD], ALL],
- on_parse_error: [[RED, REVERSE], ALL],
- compile_error: [[RED, REVERSE], ALL],
- on_assign_error: [[RED, REVERSE], ALL],
- on_alias_error: [[RED, REVERSE], ALL],
- on_class_name_error:[[RED, REVERSE], ALL],
- on_param_error: [[RED, REVERSE], ALL],
- on___end__: [[GREEN], ALL],
- }
- rescue NameError
- # Give up highlighting Ripper-incompatible older Ruby
- TOKEN_SEQ_EXPRS = {}
- end
- private_constant :TOKEN_SEQ_EXPRS
-
- ERROR_TOKENS = TOKEN_SEQ_EXPRS.keys.select { |k| k.to_s.end_with?('error') }
- private_constant :ERROR_TOKENS
-
- class << self
- def colorable?
- supported = $stdout.tty? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
-
- # because ruby/debug also uses irb's color module selectively,
- # irb won't be activated in that case.
- if IRB.respond_to?(:conf)
- supported && IRB.conf.fetch(:USE_COLORIZE, true)
- else
- supported
- end
- end
-
- def inspect_colorable?(obj, seen: {}.compare_by_identity)
- case obj
- when String, Symbol, Regexp, Integer, Float, FalseClass, TrueClass, NilClass
- true
- when Hash
- without_circular_ref(obj, seen: seen) do
- obj.all? { |k, v| inspect_colorable?(k, seen: seen) && inspect_colorable?(v, seen: seen) }
- end
- when Array
- without_circular_ref(obj, seen: seen) do
- obj.all? { |o| inspect_colorable?(o, seen: seen) }
- end
- when Range
- inspect_colorable?(obj.begin, seen: seen) && inspect_colorable?(obj.end, seen: seen)
- when Module
- !obj.name.nil?
- else
- false
- end
- end
-
- def clear(colorable: colorable?)
- return '' unless colorable
- "\e[#{CLEAR}m"
- end
-
- def colorize(text, seq, colorable: colorable?)
- return text unless colorable
- seq = seq.map { |s| "\e[#{const_get(s)}m" }.join('')
- "#{seq}#{text}#{clear(colorable: colorable)}"
- end
-
- # If `complete` is false (code is incomplete), this does not warn compile_error.
- # This option is needed to avoid warning a user when the compile_error is happening
- # because the input is not wrong but just incomplete.
- def colorize_code(code, complete: true, ignore_error: false, colorable: colorable?, local_variables: [])
- return code unless colorable
-
- symbol_state = SymbolState.new
- colored = +''
- lvars_code = RubyLex.generate_local_variables_assign_code(local_variables)
- code_with_lvars = lvars_code ? "#{lvars_code}\n#{code}" : code
-
- scan(code_with_lvars, allow_last_error: !complete) do |token, str, expr|
- # handle uncolorable code
- if token.nil?
- colored << Reline::Unicode.escape_for_print(str)
- next
- end
-
- # IRB::ColorPrinter skips colorizing fragments with any invalid token
- if ignore_error && ERROR_TOKENS.include?(token)
- return Reline::Unicode.escape_for_print(code)
- end
-
- in_symbol = symbol_state.scan_token(token)
- str.each_line do |line|
- line = Reline::Unicode.escape_for_print(line)
- if seq = dispatch_seq(token, expr, line, in_symbol: in_symbol)
- colored << seq.map { |s| "\e[#{s}m" }.join('')
- colored << line.sub(/\Z/, clear(colorable: colorable))
- else
- colored << line
- end
- end
- end
-
- if lvars_code
- raise "#{lvars_code.dump} should have no \\n" if lvars_code.include?("\n")
- colored.sub!(/\A.+\n/, '') # delete_prefix lvars_code with colors
- end
- colored
- end
-
- private
-
- def without_circular_ref(obj, seen:, &block)
- return false if seen.key?(obj)
- seen[obj] = true
- block.call
- ensure
- seen.delete(obj)
- end
-
- def scan(code, allow_last_error:)
- verbose, $VERBOSE = $VERBOSE, nil
- RubyLex.compile_with_errors_suppressed(code) do |inner_code, line_no|
- lexer = Ripper::Lexer.new(inner_code, '(ripper)', line_no)
- byte_pos = 0
- line_positions = [0]
- inner_code.lines.each do |line|
- line_positions << line_positions.last + line.bytesize
- end
-
- on_scan = proc do |elem|
- start_pos = line_positions[elem.pos[0] - 1] + elem.pos[1]
-
- # yield uncolorable code
- if byte_pos < start_pos
- yield(nil, inner_code.byteslice(byte_pos...start_pos), nil)
- end
-
- if byte_pos <= start_pos
- str = elem.tok
- yield(elem.event, str, elem.state)
- byte_pos = start_pos + str.bytesize
- end
- end
-
- if lexer.respond_to?(:scan) # Ruby 2.7+
- lexer.scan.each do |elem|
- next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message
- on_scan.call(elem)
- end
- else
- lexer.parse.sort_by(&:pos).each do |elem|
- on_scan.call(elem)
- end
- end
- # yield uncolorable DATA section
- yield(nil, inner_code.byteslice(byte_pos...inner_code.bytesize), nil) if byte_pos < inner_code.bytesize
- end
- ensure
- $VERBOSE = verbose
- end
-
- def dispatch_seq(token, expr, str, in_symbol:)
- if ERROR_TOKENS.include?(token)
- TOKEN_SEQ_EXPRS[token][0]
- elsif in_symbol
- [YELLOW]
- elsif TOKEN_KEYWORDS.fetch(token, []).include?(str)
- [CYAN, BOLD]
- elsif (seq, exprs = TOKEN_SEQ_EXPRS[token]; (expr & (exprs || 0)) != 0)
- seq
- else
- nil
- end
- end
- end
-
- # A class to manage a state to know whether the current token is for Symbol or not.
- class SymbolState
- def initialize
- # Push `true` to detect Symbol. `false` to increase the nest level for non-Symbol.
- @stack = []
- end
-
- # Return true if the token is a part of Symbol.
- def scan_token(token)
- prev_state = @stack.last
- case token
- when :on_symbeg, :on_symbols_beg, :on_qsymbols_beg
- @stack << true
- when :on_ident, :on_op, :on_const, :on_ivar, :on_cvar, :on_gvar, :on_kw
- if @stack.last # Pop only when it's Symbol
- @stack.pop
- return prev_state
- end
- when :on_tstring_beg
- @stack << false
- when :on_embexpr_beg
- @stack << false
- return prev_state
- when :on_tstring_end # :on_tstring_end may close Symbol
- @stack.pop
- return prev_state
- when :on_embexpr_end
- @stack.pop
- end
- @stack.last
- end
- end
- private_constant :SymbolState
- end
-end
diff --git a/lib/irb/color_printer.rb b/lib/irb/color_printer.rb
deleted file mode 100644
index 1127bcecb4..0000000000
--- a/lib/irb/color_printer.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-require 'pp'
-require_relative 'color'
-
-module IRB
- class ColorPrinter < ::PP
- class << self
- def pp(obj, out = $>, width = screen_width)
- q = ColorPrinter.new(out, width)
- q.guard_inspect_key {q.pp obj}
- q.flush
- out << "\n"
- end
-
- private
-
- def screen_width
- Reline.get_screen_size.last
- rescue Errno::EINVAL # in `winsize': Invalid argument - <STDIN>
- 79
- end
- end
-
- def pp(obj)
- if obj.is_a?(String)
- # Avoid calling Ruby 2.4+ String#pretty_print that splits a string by "\n"
- text(obj.inspect)
- else
- super
- end
- end
-
- def text(str, width = nil)
- unless str.is_a?(String)
- str = str.inspect
- end
- width ||= str.length
-
- case str
- when ''
- when ',', '=>', '[', ']', '{', '}', '..', '...', /\A@\w+\z/
- super(str, width)
- when /\A#</, '=', '>'
- super(Color.colorize(str, [:GREEN]), width)
- else
- super(Color.colorize_code(str, ignore_error: true), width)
- end
- end
- end
-end
diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb
deleted file mode 100644
index 97f97dfafe..0000000000
--- a/lib/irb/completion.rb
+++ /dev/null
@@ -1,483 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/completion.rb -
-# by Keiju ISHITSUKA(keiju@ishitsuka.com)
-# From Original Idea of shugo@ruby-lang.org
-#
-
-require_relative 'ruby-lex'
-
-module IRB
- module InputCompletor # :nodoc:
- using Module.new {
- refine ::Binding do
- def eval_methods
- ::Kernel.instance_method(:methods).bind(eval("self")).call
- end
-
- def eval_private_methods
- ::Kernel.instance_method(:private_methods).bind(eval("self")).call
- end
-
- def eval_instance_variables
- ::Kernel.instance_method(:instance_variables).bind(eval("self")).call
- end
-
- def eval_global_variables
- ::Kernel.instance_method(:global_variables).bind(eval("self")).call
- end
-
- def eval_class_constants
- ::Module.instance_method(:constants).bind(eval("self.class")).call
- end
- end
- }
-
- # Set of reserved words used by Ruby, you should not use these for
- # constants or variables
- ReservedWords = %w[
- __ENCODING__ __LINE__ __FILE__
- BEGIN END
- alias and
- begin break
- case class
- def defined? do
- else elsif end ensure
- false for
- if in
- module
- next nil not
- or
- redo rescue retry return
- self super
- then true
- undef unless until
- when while
- yield
- ]
-
- BASIC_WORD_BREAK_CHARACTERS = " \t\n`><=;|&{("
-
- def self.absolute_path?(p) # TODO Remove this method after 2.6 EOL.
- if File.respond_to?(:absolute_path?)
- File.absolute_path?(p)
- else
- File.absolute_path(p) == p
- end
- end
-
- GEM_PATHS =
- if defined?(Gem::Specification)
- Gem::Specification.latest_specs(true).map { |s|
- s.require_paths.map { |p|
- if absolute_path?(p)
- p
- else
- File.join(s.full_gem_path, p)
- end
- }
- }.flatten
- else
- []
- end.freeze
-
- def self.retrieve_gem_and_system_load_path
- candidates = (GEM_PATHS | $LOAD_PATH)
- candidates.map do |p|
- if p.respond_to?(:to_path)
- p.to_path
- else
- String(p) rescue nil
- end
- end.compact.sort
- end
-
- def self.retrieve_files_to_require_from_load_path
- @@files_from_load_path ||=
- (
- shortest = []
- rest = retrieve_gem_and_system_load_path.each_with_object([]) { |path, result|
- begin
- names = Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: path)
- rescue Errno::ENOENT
- nil
- end
- next if names.empty?
- names.map! { |n| n.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '') }.sort!
- shortest << names.shift
- result.concat(names)
- }
- shortest.sort! | rest
- )
- end
-
- def self.retrieve_files_to_require_relative_from_current_dir
- @@files_from_current_dir ||= Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path|
- path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
- }
- end
-
- CompletionRequireProc = lambda { |target, preposing = nil, postposing = nil|
- if target =~ /\A(['"])([^'"]+)\Z/
- quote = $1
- actual_target = $2
- else
- return nil # It's not String literal
- end
- tokens = RubyLex.ripper_lex_without_warning(preposing.gsub(/\s*\z/, ''))
- tok = nil
- tokens.reverse_each do |t|
- unless [:on_lparen, :on_sp, :on_ignored_sp, :on_nl, :on_ignored_nl, :on_comment].include?(t.event)
- tok = t
- break
- end
- end
- result = []
- if tok && tok.event == :on_ident && tok.state == Ripper::EXPR_CMDARG
- case tok.tok
- when 'require'
- result = retrieve_files_to_require_from_load_path.select { |path|
- path.start_with?(actual_target)
- }.map { |path|
- quote + path
- }
- when 'require_relative'
- result = retrieve_files_to_require_relative_from_current_dir.select { |path|
- path.start_with?(actual_target)
- }.map { |path|
- quote + path
- }
- end
- end
- result
- }
-
- CompletionProc = lambda { |target, preposing = nil, postposing = nil|
- if preposing && postposing
- result = CompletionRequireProc.(target, preposing, postposing)
- unless result
- result = retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
- end
- result
- else
- retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
- end
- }
-
- def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding, doc_namespace: false)
- case input
- when /^((["'`]).*\2)\.([^.]*)$/
- # String
- receiver = $1
- message = $3
-
- if doc_namespace
- "String.#{message}"
- else
- candidates = String.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates)
- end
-
- when /^(\/[^\/]*\/)\.([^.]*)$/
- # Regexp
- receiver = $1
- message = $2
-
- if doc_namespace
- "Regexp.#{message}"
- else
- candidates = Regexp.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates)
- end
-
- when /^([^\]]*\])\.([^.]*)$/
- # Array
- receiver = $1
- message = $2
-
- if doc_namespace
- "Array.#{message}"
- else
- candidates = Array.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates)
- end
-
- when /^([^\}]*\})\.([^.]*)$/
- # Proc or Hash
- receiver = $1
- message = $2
-
- if doc_namespace
- ["Proc.#{message}", "Hash.#{message}"]
- else
- proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
- hash_candidates = Hash.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, proc_candidates | hash_candidates)
- end
-
- when /^(:[^:.]*)$/
- # Symbol
- if doc_namespace
- nil
- else
- sym = $1
- candidates = Symbol.all_symbols.collect do |s|
- ":" + s.id2name.encode(Encoding.default_external)
- rescue EncodingError
- # ignore
- end
- candidates.grep(/^#{Regexp.quote(sym)}/)
- end
- when /^::([A-Z][^:\.\(\)]*)$/
- # Absolute Constant or class methods
- receiver = $1
-
- candidates = Object.constants.collect{|m| m.to_s}
-
- if doc_namespace
- candidates.find { |i| i == receiver }
- else
- candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
- end
-
- when /^([A-Z].*)::([^:.]*)$/
- # Constant or class methods
- receiver = $1
- message = $2
-
- if doc_namespace
- "#{receiver}::#{message}"
- else
- begin
- candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
- candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
- rescue Exception
- candidates = []
- end
-
- select_message(receiver, message, candidates.sort, "::")
- end
-
- when /^(:[^:.]+)(\.|::)([^.]*)$/
- # Symbol
- receiver = $1
- sep = $2
- message = $3
-
- if doc_namespace
- "Symbol.#{message}"
- else
- candidates = Symbol.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates, sep)
- end
-
- when /^(?<num>-?(?:0[dbo])?[0-9_]+(?:\.[0-9_]+)?(?:(?:[eE][+-]?[0-9]+)?i?|r)?)(?<sep>\.|::)(?<mes>[^.]*)$/
- # Numeric
- receiver = $~[:num]
- sep = $~[:sep]
- message = $~[:mes]
-
- begin
- instance = eval(receiver, bind)
-
- if doc_namespace
- "#{instance.class.name}.#{message}"
- else
- candidates = instance.methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates, sep)
- end
- rescue Exception
- if doc_namespace
- nil
- else
- []
- end
- end
-
- when /^(-?0x[0-9a-fA-F_]+)(\.|::)([^.]*)$/
- # Numeric(0xFFFF)
- receiver = $1
- sep = $2
- message = $3
-
- begin
- instance = eval(receiver, bind)
- if doc_namespace
- "#{instance.class.name}.#{message}"
- else
- candidates = instance.methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates, sep)
- end
- rescue Exception
- if doc_namespace
- nil
- else
- []
- end
- end
-
- when /^(\$[^.]*)$/
- # global var
- gvar = $1
- all_gvars = global_variables.collect{|m| m.to_s}
-
- if doc_namespace
- all_gvars.find{ |i| i == gvar }
- else
- all_gvars.grep(Regexp.new(Regexp.quote(gvar)))
- end
-
- when /^([^.:"].*)(\.|::)([^.]*)$/
- # variable.func or func.func
- receiver = $1
- sep = $2
- message = $3
-
- gv = bind.eval_global_variables.collect{|m| m.to_s}.push("true", "false", "nil")
- lv = bind.local_variables.collect{|m| m.to_s}
- iv = bind.eval_instance_variables.collect{|m| m.to_s}
- cv = bind.eval_class_constants.collect{|m| m.to_s}
-
- if (gv | lv | iv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
- # foo.func and foo is var. OR
- # foo::func and foo is var. OR
- # foo::Const and foo is var. OR
- # Foo::Bar.func
- begin
- candidates = []
- rec = eval(receiver, bind)
- if sep == "::" and rec.kind_of?(Module)
- candidates = rec.constants.collect{|m| m.to_s}
- end
- candidates |= rec.methods.collect{|m| m.to_s}
- rescue Exception
- candidates = []
- end
- else
- # func1.func2
- candidates = []
- to_ignore = ignored_modules
- ObjectSpace.each_object(Module){|m|
- next if (to_ignore.include?(m) rescue true)
- next unless m.respond_to?(:instance_methods) # JRuby has modules that represent java packages. They don't include many common ruby methods
- candidates.concat m.instance_methods(false).collect{|x| x.to_s}
- }
- candidates.sort!
- candidates.uniq!
- end
-
- if doc_namespace
- rec_class = rec.is_a?(Module) ? rec : rec.class
- "#{rec_class.name}#{sep}#{candidates.find{ |i| i == message }}"
- else
- select_message(receiver, message, candidates, sep)
- end
-
- when /^\.([^.]*)$/
- # unknown(maybe String)
-
- receiver = ""
- message = $1
-
- candidates = String.instance_methods(true).collect{|m| m.to_s}
-
- if doc_namespace
- "String.#{candidates.find{ |i| i == message }}"
- else
- select_message(receiver, message, candidates.sort)
- end
-
- else
- if doc_namespace
- vars = (bind.local_variables | bind.eval_instance_variables).collect{|m| m.to_s}
- perfect_match_var = vars.find{|m| m.to_s == input}
- if perfect_match_var
- eval("#{perfect_match_var}.class.name", bind)
- else
- candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
- candidates |= ReservedWords
- candidates.find{ |i| i == input }
- end
- else
- candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
- candidates |= ReservedWords
- candidates.grep(/^#{Regexp.quote(input)}/).sort
- end
- end
- end
-
- PerfectMatchedProc = ->(matched, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding) {
- begin
- require 'rdoc'
- rescue LoadError
- return
- end
-
- RDocRIDriver ||= RDoc::RI::Driver.new
-
- if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
- IRB.__send__(:easter_egg)
- return
- end
-
- namespace = retrieve_completion_data(matched, bind: bind, doc_namespace: true)
- return unless namespace
-
- if namespace.is_a?(Array)
- out = RDoc::Markup::Document.new
- namespace.each do |m|
- begin
- RDocRIDriver.add_method(out, m)
- rescue RDoc::RI::Driver::NotFoundError
- end
- end
- RDocRIDriver.display(out)
- else
- begin
- RDocRIDriver.display_names([namespace])
- rescue RDoc::RI::Driver::NotFoundError
- end
- end
- }
-
- # Set of available operators in Ruby
- Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~]
-
- def self.select_message(receiver, message, candidates, sep = ".")
- candidates.grep(/^#{Regexp.quote(message)}/).collect do |e|
- case e
- when /^[a-zA-Z_]/
- receiver + sep + e
- when /^[0-9]/
- when *Operators
- #receiver + " " + e
- end
- end
- end
-
- def self.ignored_modules
- # We could cache the result, but this is very fast already.
- # By using this approach, we avoid Module#name calls, which are
- # relatively slow when there are a lot of anonymous modules defined.
- s = {}
-
- scanner = lambda do |m|
- next if s.include?(m) # IRB::ExtendCommandBundle::EXCB recurses.
- s[m] = true
- m.constants(false).each do |c|
- value = m.const_get(c)
- scanner.call(value) if value.is_a?(Module)
- end
- end
-
- %i(IRB RubyLex).each do |sym|
- next unless Object.const_defined?(sym)
- scanner.call(Object.const_get(sym))
- end
-
- s.delete(IRB::Context) if defined?(IRB::Context)
-
- s
- end
- end
-end
diff --git a/lib/irb/context.rb b/lib/irb/context.rb
deleted file mode 100644
index a8031d0294..0000000000
--- a/lib/irb/context.rb
+++ /dev/null
@@ -1,555 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/context.rb - irb context
-# 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 Reline 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
-
- # 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_RELINE) # backward compatibility
- warn <<~MSG.strip
- USE_RELINE is deprecated, please use USE_MULTILINE instead.
- MSG
- @use_multiline = IRB.conf[:USE_RELINE]
- elsif IRB.conf.has_key?(:USE_REIDLINE)
- warn <<~MSG.strip
- USE_REIDLINE is deprecated, please use USE_MULTILINE instead.
- MSG
- @use_multiline = IRB.conf[:USE_REIDLINE]
- else
- @use_multiline = nil
- end
- @use_autocomplete = IRB.conf[:USE_AUTOCOMPLETE]
- @verbose = IRB.conf[:VERBOSE]
- @io = nil
-
- self.inspect_mode = IRB.conf[:INSPECT_MODE]
- 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 = RelineInputMethod.new
- else
- @io = nil
- end
- when false
- @io = nil
- when true
- @io = RelineInputMethod.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 '-'
- @io = FileInputMethod.new($stdin)
- @irb_name = '-'
- @irb_path = '-'
- 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]
-
- @extra_doc_dirs = IRB.conf[:EXTRA_DOC_DIRS]
-
- @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 = :truncate
- end
-
- @newline_before_multiline_output = IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]
- if @newline_before_multiline_output.nil?
- @newline_before_multiline_output = true
- end
-
- @command_aliases = IRB.conf[:COMMAND_ALIASES]
- 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,
- # RelineInputMethod, 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_AUTOCOMPLETE]</code>
- attr_reader :use_autocomplete
- # 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
- # Specify the installation locations of the ri file to be displayed in the
- # document dialog.
- attr_accessor :extra_doc_dirs
- # 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.
- #
- # If set to +false+, the value of assignment will not be shown.
- #
- # If set to +true+, the value of assignment will be shown.
- #
- # If set to +:truncate+, the value of assignment will be shown and truncated.
- #
- # It defaults to +:truncate+.
- #
- # a = "omg"
- # #=> omg
- #
- # a = "omg" * 10
- # #=> omgomgomgomgomgomgomg...
- #
- # IRB.CurrentContext.echo_on_assignment = false
- # a = "omg"
- #
- # IRB.CurrentContext.echo_on_assignment = true
- # a = "omg" * 10
- # #=> omgomgomgomgomgomgomgomgomgomg
- #
- # To set the behaviour of showing on assignment in irb:
- #
- # IRB.conf[:ECHO_ON_ASSIGNMENT] = :truncate or true or false
- #
- # or
- #
- # irb_context.echo_on_assignment = :truncate or true or false
- #
- # or
- #
- # IRB.CurrentContext.echo_on_assignment = :truncate or true or false
- 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
-
- # User-defined IRB command aliases
- attr_accessor :command_aliases
-
- # Alias for #use_multiline
- alias use_multiline? use_multiline
- # Alias for #use_singleline
- alias use_singleline? use_singleline
- # backward compatibility
- alias use_reline use_multiline
- # backward compatibility
- alias use_reline? use_multiline
- # backward compatibility
- alias use_readline use_singleline
- # backward compatibility
- alias use_readline? use_singleline
- # Alias for #use_autocomplete
- alias use_autocomplete? use_autocomplete
- # 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?(RelineInputMethod)
- 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 RelineInputMethod or ReadlineInputMethod, see #io
- # for more information.
- def prompting?
- verbose? || (STDIN.tty? && @io.kind_of?(StdioInputMethod) ||
- @io.kind_of?(RelineInputMethod) ||
- (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]
- @return_format = "%s\n" if @return_format == nil
- 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
-
- # Transform a non-identifier alias (@, $) or keywords (next, break)
- command, args = line.split(/\s/, 2)
- if original = command_aliases[command.to_sym]
- line = line.gsub(/\A#{Regexp.escape(command)}/, original.to_s)
- command = original
- end
-
- # Hook command-specific transformation
- command_class = ExtendCommandBundle.load_command(command)
- if command_class&.respond_to?(:transform_args)
- line = "#{command} #{command_class.transform_args(args)}"
- 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)
- rescue UncaughtThrowError
- super
- 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
-
- def local_variables # :nodoc:
- workspace.binding.local_variables
- end
-
- # Return true if it's aliased from the argument and it's not an identifier.
- def symbol_alias?(command)
- return nil if command.match?(/\A\w+\z/)
- command_aliases.key?(command.to_sym)
- end
-
- # Return true if the command supports transforming args
- def transform_args?(command)
- command = command_aliases.fetch(command.to_sym, command)
- ExtendCommandBundle.load_command(command)&.respond_to?(:transform_args)
- end
- end
-end
diff --git a/lib/irb/easter-egg.rb b/lib/irb/easter-egg.rb
deleted file mode 100644
index 3e79692de9..0000000000
--- a/lib/irb/easter-egg.rb
+++ /dev/null
@@ -1,138 +0,0 @@
-require "reline"
-
-module IRB
- class << self
- class Vec
- def initialize(x, y, z)
- @x, @y, @z = x, y, z
- end
-
- attr_reader :x, :y, :z
-
- def sub(other)
- Vec.new(@x - other.x, @y - other.y, @z - other.z)
- end
-
- def dot(other)
- @x*other.x + @y*other.y + @z*other.z
- end
-
- def cross(other)
- ox, oy, oz = other.x, other.y, other.z
- Vec.new(@y*oz-@z*oy, @z*ox-@x*oz, @x*oy-@y*ox)
- end
-
- def normalize
- r = Math.sqrt(self.dot(self))
- Vec.new(@x / r, @y / r, @z / r)
- end
- end
-
- class Canvas
- def initialize((h, w))
- @data = (0..h-2).map { [0] * w }
- @scale = [w / 2.0, h-2].min
- @center = Complex(w / 2, h-2)
- end
-
- def line((x1, y1), (x2, y2))
- p1 = Complex(x1, y1) / 2 * @scale + @center
- p2 = Complex(x2, y2) / 2 * @scale + @center
- line0(p1, p2)
- end
-
- private def line0(p1, p2)
- mid = (p1 + p2) / 2
- if (p1 - p2).abs < 1
- x, y = mid.rect
- @data[y / 2][x] |= (y % 2 > 1 ? 2 : 1)
- else
- line0(p1, mid)
- line0(p2, mid)
- end
- end
-
- def draw
- @data.each {|row| row.fill(0) }
- yield
- @data.map {|row| row.map {|n| " ',;"[n] }.join }.join("\n")
- end
- end
-
- class RubyModel
- def initialize
- @faces = init_ruby_model
- end
-
- def init_ruby_model
- cap_vertices = (0..5).map {|i| Vec.new(*Complex.polar(1, i * Math::PI / 3).rect, 1) }
- middle_vertices = (0..5).map {|i| Vec.new(*Complex.polar(2, (i + 0.5) * Math::PI / 3).rect, 0) }
- bottom_vertex = Vec.new(0, 0, -2)
-
- faces = [cap_vertices]
- 6.times do |j|
- i = j-1
- faces << [cap_vertices[i], middle_vertices[i], cap_vertices[j]]
- faces << [cap_vertices[j], middle_vertices[i], middle_vertices[j]]
- faces << [middle_vertices[i], bottom_vertex, middle_vertices[j]]
- end
-
- faces
- end
-
- def render_frame(i)
- angle = i / 10.0
- dir = Vec.new(*Complex.polar(1, angle).rect, Math.sin(angle)).normalize
- dir2 = Vec.new(*Complex.polar(1, angle - Math::PI/2).rect, 0)
- up = dir.cross(dir2)
- nm = dir.cross(up)
- @faces.each do |vertices|
- v0, v1, v2, = vertices
- if v1.sub(v0).cross(v2.sub(v0)).dot(dir) > 0
- points = vertices.map {|p| [nm.dot(p), up.dot(p)] }
- (points + [points[0]]).each_cons(2) do |p1, p2|
- yield p1, p2
- end
- end
- end
- end
- end
-
- private def easter_egg(type = nil)
- type ||= [:logo, :dancing].sample
- case type
- when :logo
- File.open(File.join(__dir__, 'ruby_logo.aa')) do |f|
- require "rdoc"
- RDoc::RI::Driver.new.page do |io|
- IO.copy_stream(f, io)
- end
- end
- when :dancing
- begin
- canvas = Canvas.new(Reline.get_screen_size)
- Reline::IOGate.set_winch_handler do
- canvas = Canvas.new(Reline.get_screen_size)
- end
- ruby_model = RubyModel.new
- print "\e[?1049h"
- 0.step do |i| # TODO (0..).each needs Ruby 2.6 or later
- buff = canvas.draw do
- ruby_model.render_frame(i) do |p1, p2|
- canvas.line(p1, p2)
- end
- end
- buff[0, 20] = "\e[0mPress Ctrl+C to stop\e[31m\e[1m"
- print "\e[H" + buff
- sleep 0.05
- end
- rescue Interrupt
- ensure
- print "\e[0m\e[?1049l"
- end
- end
- end
- end
-end
-
-IRB.__send__(:easter_egg, ARGV[0]&.to_sym) if $0 == __FILE__
diff --git a/lib/irb/ext/change-ws.rb b/lib/irb/ext/change-ws.rb
deleted file mode 100644
index c0f810a4c8..0000000000
--- a/lib/irb/ext/change-ws.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/ext/cb.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
- class Context
-
- # Inherited from +TOPLEVEL_BINDING+.
- def home_workspace
- if defined? @home_workspace
- @home_workspace
- else
- @home_workspace = @workspace
- end
- end
-
- # Changes the current workspace to given object or binding.
- #
- # If the optional argument is omitted, the workspace will be
- # #home_workspace which is inherited from +TOPLEVEL_BINDING+ or the main
- # object, <code>IRB.conf[:MAIN_CONTEXT]</code> when irb was initialized.
- #
- # See IRB::WorkSpace.new for more information.
- def change_workspace(*_main)
- if _main.empty?
- @workspace = home_workspace
- return main
- end
-
- @workspace = WorkSpace.new(_main[0])
-
- if !(class<<main;ancestors;end).include?(ExtendCommandBundle)
- main.extend ExtendCommandBundle
- end
- end
- end
-end
diff --git a/lib/irb/ext/history.rb b/lib/irb/ext/history.rb
deleted file mode 100644
index 59aa9cb0c7..0000000000
--- a/lib/irb/ext/history.rb
+++ /dev/null
@@ -1,149 +0,0 @@
-# frozen_string_literal: false
-#
-# history.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
-
- class Context
-
- NOPRINTING_IVARS.push "@eval_history_values"
-
- # See #set_last_value
- alias _set_last_value set_last_value
-
- def set_last_value(value)
- _set_last_value(value)
-
- if defined?(@eval_history) && @eval_history
- @eval_history_values.push @line_no, @last_value
- @workspace.evaluate self, "__ = IRB.CurrentContext.instance_eval{@eval_history_values}"
- end
-
- @last_value
- end
-
- remove_method :eval_history= if method_defined?(:eval_history=)
- # The command result history limit. This method is not available until
- # #eval_history= was called with non-nil value (directly or via
- # setting <code>IRB.conf[:EVAL_HISTORY]</code> in <code>.irbrc</code>).
- attr_reader :eval_history
- # Sets command result history limit. Default value is set from
- # <code>IRB.conf[:EVAL_HISTORY]</code>.
- #
- # +no+ is an Integer or +nil+.
- #
- # Returns +no+ of history items if greater than 0.
- #
- # If +no+ is 0, the number of history items is unlimited.
- #
- # If +no+ is +nil+, execution result history isn't used (default).
- #
- # History values are available via <code>__</code> variable, see
- # IRB::History.
- def eval_history=(no)
- if no
- if defined?(@eval_history) && @eval_history
- @eval_history_values.size(no)
- else
- @eval_history_values = History.new(no)
- IRB.conf[:__TMP__EHV__] = @eval_history_values
- @workspace.evaluate(self, "__ = IRB.conf[:__TMP__EHV__]")
- IRB.conf.delete(:__TMP_EHV__)
- end
- else
- @eval_history_values = nil
- end
- @eval_history = no
- end
- end
-
- # Represents history of results of previously evaluated commands.
- #
- # Available via <code>__</code> variable, only if <code>IRB.conf[:EVAL_HISTORY]</code>
- # or <code>IRB::CurrentContext().eval_history</code> is non-nil integer value
- # (by default it is +nil+).
- #
- # Example (in `irb`):
- #
- # # Initialize history
- # IRB::CurrentContext().eval_history = 10
- # # => 10
- #
- # # Perform some commands...
- # 1 + 2
- # # => 3
- # puts 'x'
- # # x
- # # => nil
- # raise RuntimeError
- # # ...error raised
- #
- # # Inspect history (format is "<item number> <evaluated value>":
- # __
- # # => 1 10
- # # 2 3
- # # 3 nil
- #
- # __[1]
- # # => 10
- #
- class History
-
- def initialize(size = 16) # :nodoc:
- @size = size
- @contents = []
- end
-
- def size(size) # :nodoc:
- if size != 0 && size < @size
- @contents = @contents[@size - size .. @size]
- end
- @size = size
- end
-
- # Get one item of the content (both positive and negative indexes work).
- def [](idx)
- begin
- if idx >= 0
- @contents.find{|no, val| no == idx}[1]
- else
- @contents[idx][1]
- end
- rescue NameError
- nil
- end
- end
-
- def push(no, val) # :nodoc:
- @contents.push [no, val]
- @contents.shift if @size != 0 && @contents.size > @size
- end
-
- alias real_inspect inspect
-
- def inspect # :nodoc:
- if @contents.empty?
- return real_inspect
- end
-
- unless (last = @contents.pop)[1].equal?(self)
- @contents.push last
- last = nil
- end
- str = @contents.collect{|no, val|
- if val.equal?(self)
- "#{no} ...self-history..."
- else
- "#{no} #{val.inspect}"
- end
- }.join("\n")
- if str == ""
- str = "Empty."
- end
- @contents.push last if last
- str
- end
- end
-end
diff --git a/lib/irb/ext/loader.rb b/lib/irb/ext/loader.rb
deleted file mode 100644
index 0a599ee802..0000000000
--- a/lib/irb/ext/loader.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-# frozen_string_literal: false
-#
-# loader.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-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
-
- 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
-
- load_file(path, priv)
- end
-
- if File.respond_to?(:absolute_path?)
- def absolute_path?(path)
- File.absolute_path?(path)
- end
- else
- separator =
- if File::ALT_SEPARATOR
- "[#{Regexp.quote(File::SEPARATOR + File::ALT_SEPARATOR)}]"
- else
- File::SEPARATOR
- end
- ABSOLUTE_PATH_PATTERN = # :nodoc:
- case Dir.pwd
- when /\A\w:/, /\A#{separator}{2}/
- /\A(?:\w:|#{separator})#{separator}/
- else
- /\A#{separator}/
- end
- def absolute_path?(path)
- ABSOLUTE_PATH_PATTERN =~ path
- end
- end
-
- def search_file_from_ruby_path(fn) # :nodoc:
- if absolute_path?(fn)
- return fn if File.exist?(fn)
- return nil
- end
-
- for path in $:
- if File.exist?(f = File.join(path, fn))
- return f
- end
- end
- 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
- FileInputMethod.open(path) do |io|
- irb.suspend_input_method(io) do
- |back_io|
- irb.signal_status(:IN_LOAD) do
- if back_io.kind_of?(FileInputMethod)
- irb.eval_input
- else
- begin
- irb.eval_input
- rescue LoadAbort
- print "load abort!!\n"
- end
- end
- end
- end
- end
- 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
-
- if priv
- ws = WorkSpace.new(Module.new)
- else
- ws = WorkSpace.new
- end
- irb.suspend_workspace(ws) do
- FileInputMethod.open(path) do |io|
- irb.suspend_input_method(io) do
- |back_io|
- irb.signal_status(:IN_LOAD) do
- if back_io.kind_of?(FileInputMethod)
- irb.eval_input
- else
- begin
- irb.eval_input
- rescue LoadAbort
- print "load abort!!\n"
- end
- end
- end
- end
- end
- end
- end
- end
-
- def old # :nodoc:
- back_io = @io
- back_path = @irb_path
- back_name = @irb_name
- back_scanner = @irb.scanner
- begin
- @io = FileInputMethod.new(path)
- @irb_name = File.basename(path)
- @irb_path = path
- @irb.signal_status(:IN_LOAD) do
- if back_io.kind_of?(FileInputMethod)
- @irb.eval_input
- else
- begin
- @irb.eval_input
- rescue LoadAbort
- print "load abort!!\n"
- end
- end
- end
- ensure
- @io = back_io
- @irb_name = back_name
- @irb_path = back_path
- @irb.scanner = back_scanner
- end
- end
- end
-end
diff --git a/lib/irb/ext/multi-irb.rb b/lib/irb/ext/multi-irb.rb
deleted file mode 100644
index 1c20489137..0000000000
--- a/lib/irb/ext/multi-irb.rb
+++ /dev/null
@@ -1,258 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/multi-irb.rb - multiple irb module
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- class JobManager
-
- # Creates a new JobManager object
- def initialize
- @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)
- fail IrbAlreadyDead unless th.alive?
- fail IrbSwitchedToCurrentThread if th == Thread.current
- @current_job = irb
- th.run
- Thread.stop
- @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)
- fail IrbAlreadyDead unless th.alive?
- th.exit
- 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
- @jobs[key]
- when Irb
- @jobs.find{|k, v| v.equal?(key)}
- when Thread
- @jobs.assoc(key)
- else
- @jobs.find{|k, v| v.context.main.equal?(key)}
- end
- fail NoSuchJob, key if job.nil?
- job
- end
-
- # Deletes the job at the given +key+.
- def delete(key)
- case key
- when Integer
- fail NoSuchJob, key unless @jobs[key]
- @jobs[key] = nil
- else
- catch(:EXISTS) do
- @jobs.each_index do
- |i|
- if @jobs[i] and (@jobs[i][0] == key ||
- @jobs[i][1] == key ||
- @jobs[i][1].context.main.equal?(key))
- @jobs[i] = nil
- throw :EXISTS
- end
- end
- fail NoSuchJob, key
- end
- end
- until assoc = @jobs.pop; end unless @jobs.empty?
- @jobs.push assoc
- end
-
- # Outputs a list of jobs, see the irb command +irb_jobs+, or +jobs+.
- def inspect
- ary = []
- @jobs.each_index do
- |i|
- th, irb = @jobs[i]
- next if th.nil?
-
- if th.alive?
- if th.stop?
- t_status = "stop"
- else
- t_status = "running"
- end
- else
- t_status = "exited"
- end
- ary.push format("#%d->%s on %s (%s: %s)",
- i,
- irb.context.irb_name,
- irb.context.main,
- th,
- t_status)
- end
- ary.join("\n")
- end
- end
-
- @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
-
- # Creates a new IRB session, see Irb.new.
- #
- # The optional +file+ argument is given to Context.new, along with the
- # workspace created with the remaining arguments, see WorkSpace.new
- def IRB.irb(file = nil, *main)
- workspace = WorkSpace.new(*main)
- parent_thread = Thread.current
- Thread.start do
- begin
- irb = Irb.new(workspace, file)
- rescue
- print "Subirb can't start with context(self): ", workspace.main.inspect, "\n"
- print "return to main irb\n"
- Thread.pass
- Thread.main.wakeup
- Thread.exit
- end
- @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
- @JobManager.insert(irb)
- @JobManager.current_job = irb
- begin
- system_exit = false
- catch(:IRB_EXIT) do
- irb.eval_input
- end
- rescue SystemExit
- system_exit = true
- raise
- #fail
- ensure
- unless system_exit
- @JobManager.delete(irb)
- if @JobManager.current_job == irb
- if parent_thread.alive?
- @JobManager.current_job = @JobManager.irb(parent_thread)
- parent_thread.run
- else
- @JobManager.current_job = @JobManager.main_irb
- @JobManager.main_thread.run
- end
- end
- end
- end
- end
- Thread.stop
- @JobManager.current_job = @JobManager.irb(Thread.current)
- end
-
- @CONF[:SINGLE_IRB_MODE] = false
- @JobManager.insert(@CONF[:MAIN_CONTEXT].irb)
- @JobManager.current_job = @CONF[:MAIN_CONTEXT].irb
-
- class Irb
- def signal_handle
- unless @context.ignore_sigint?
- print "\nabort!!\n" if @context.verbose?
- exit
- end
-
- case @signal_status
- when :IN_INPUT
- print "^C\n"
- IRB.JobManager.thread(self).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
- end
-
- trap("SIGINT") do
- @JobManager.current_job.signal_handle
- Thread.stop
- end
-
-end
diff --git a/lib/irb/ext/save-history.rb b/lib/irb/ext/save-history.rb
deleted file mode 100644
index b1987ea646..0000000000
--- a/lib/irb/ext/save-history.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-# frozen_string_literal: false
-#
-# save-history.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- module HistorySavingAbility # :nodoc:
- end
-
- class Context
- 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
-
- remove_method(:save_history=) if method_defined?(:save_history=)
- # Sets <code>IRB.conf[:SAVE_HISTORY]</code> to the given +val+ and calls
- # #init_save_history with this context.
- #
- # Will store the number of +val+ entries of history in the #history_file
- #
- # Add the following to your +.irbrc+ to change the number of history
- # entries stored to 1000:
- #
- # IRB.conf[:SAVE_HISTORY] = 1000
- def save_history=(val)
- IRB.conf[:SAVE_HISTORY] = val
- if val
- main_context = IRB.conf[:MAIN_CONTEXT]
- main_context = self unless main_context
- main_context.init_save_history
- 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 # :nodoc:
- def HistorySavingAbility.extended(obj)
- IRB.conf[:AT_EXIT].push proc{obj.save_history}
- obj.load_history
- obj
- end
-
- def load_history
- return unless self.class.const_defined?(:HISTORY)
- history = self.class::HISTORY
- if history_file = IRB.conf[:HISTORY_FILE]
- history_file = File.expand_path(history_file)
- end
- history_file = IRB.rc_file("_history") unless history_file
- if File.exist?(history_file)
- File.open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
- f.each { |l|
- l = l.chomp
- if self.class == RelineInputMethod and history.last&.end_with?("\\")
- history.last.delete_suffix!("\\")
- history.last << "\n" << l
- else
- history << l
- end
- }
- end
- @loaded_history_lines = history.size
- @loaded_history_mtime = File.mtime(history_file)
- end
- end
-
- def save_history
- return unless self.class.const_defined?(:HISTORY)
- history = self.class::HISTORY
- if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) != 0
- if history_file = IRB.conf[:HISTORY_FILE]
- history_file = File.expand_path(history_file)
- end
- history_file = IRB.rc_file("_history") unless history_file
-
- # Change the permission of a file that already exists[BUG #7694]
- begin
- if File.stat(history_file).mode & 066 != 0
- File.chmod(0600, history_file)
- end
- rescue Errno::ENOENT
- rescue Errno::EPERM
- return
- rescue
- raise
- end
-
- if File.exist?(history_file) &&
- File.mtime(history_file) != @loaded_history_mtime
- history = history[@loaded_history_lines..-1] if @loaded_history_lines
- append_history = true
- end
-
- File.open(history_file, (append_history ? 'a' : 'w'), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f|
- hist = history.map{ |l| l.split("\n").join("\\\n") }
- unless append_history
- begin
- hist = hist.last(num) if hist.size > num and num > 0
- rescue RangeError # bignum too big to convert into `long'
- # Do nothing because the bignum should be treated as inifinity
- end
- end
- f.puts(hist)
- end
- end
- end
- end
-end
diff --git a/lib/irb/ext/tracer.rb b/lib/irb/ext/tracer.rb
deleted file mode 100644
index 56beb0a1dd..0000000000
--- a/lib/irb/ext/tracer.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/lib/tracer.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-begin
- require "tracer"
-rescue LoadError
- $stderr.puts "Tracer extension of IRB is enabled but tracer gem doesn't found."
- module IRB
- TracerLoadError = true
- class Context
- def use_tracer=(opt)
- # do nothing
- end
- end
- end
- return # This is about to disable loading below
-end
-
-module IRB
-
- # initialize tracing function
- def IRB.initialize_tracer
- Tracer.verbose = false
- Tracer.add_filter {
- |event, file, line, id, binding, *rests|
- /^#{Regexp.quote(@CONF[:IRB_LIB_PATH])}/ !~ file and
- File::basename(file) != "irb.rb"
- }
- 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) {
- |line_no, *rests|
- @io.line(line_no)
- }
- elsif !opt && @use_tracer
- Tracer.off
- end
- @use_tracer=opt
- end
- end
-
- 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
- begin
- __evaluate__(context, statements, file, line)
- ensure
- Tracer.off
- end
- else
- __evaluate__(context, statements, file || __FILE__, line || __LINE__)
- end
- end
- end
-
- IRB.initialize_tracer
-end
diff --git a/lib/irb/ext/use-loader.rb b/lib/irb/ext/use-loader.rb
deleted file mode 100644
index d0b8c2d4f4..0000000000
--- a/lib/irb/ext/use-loader.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# frozen_string_literal: false
-#
-# use-loader.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "../cmd/load"
-require_relative "loader"
-
-class Object
- alias __original__load__IRB_use_loader__ load
- alias __original__require__IRB_use_loader__ require
-end
-
-module IRB
- module ExtendCommandBundle
- remove_method :irb_load if method_defined?(:irb_load)
- # 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
- remove_method :irb_require if method_defined?(:irb_require)
- # Loads the given file similarly to Kernel#require
- def irb_require(*opts, &b)
- ExtendCommand::Require.execute(irb_context, *opts, &b)
- end
- end
-
- class Context
-
- IRB.conf[:USE_LOADER] = false
-
- # Returns whether +irb+'s own file reader method is used by
- # +load+/+require+ or not.
- #
- # This mode is globally affected (irb-wide).
- def use_loader
- IRB.conf[:USE_LOADER]
- end
-
- alias use_loader? use_loader
-
- remove_method :use_loader= if method_defined?(:use_loader=)
- # Sets <code>IRB.conf[:USE_LOADER]</code>
- #
- # See #use_loader for more information.
- def use_loader=(opt)
-
- if IRB.conf[:USE_LOADER] != opt
- IRB.conf[:USE_LOADER] = opt
- if opt
- if !$".include?("irb/cmd/load")
- end
- (class<<@workspace.main;self;end).instance_eval {
- alias_method :load, :irb_load
- alias_method :require, :irb_require
- }
- else
- (class<<@workspace.main;self;end).instance_eval {
- alias_method :load, :__original__load__IRB_use_loader__
- alias_method :require, :__original__require__IRB_use_loader__
- }
- end
- end
- print "Switch to load/require#{unless use_loader; ' non';end} trace mode.\n" if verbose?
- opt
- end
- end
-end
diff --git a/lib/irb/ext/workspaces.rb b/lib/irb/ext/workspaces.rb
deleted file mode 100644
index 9defc3e17b..0000000000
--- a/lib/irb/ext/workspaces.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: false
-#
-# push-ws.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
- class Context
-
- # Size of the current WorkSpace stack
- def irb_level
- workspace_stack.size
- end
-
- # WorkSpaces in the current stack
- def workspaces
- if defined? @workspaces
- @workspaces
- else
- @workspaces = []
- end
- end
-
- # Creates a new workspace with the given object or binding, and appends it
- # onto the current #workspaces stack.
- #
- # See IRB::Context#change_workspace and IRB::WorkSpace.new for more
- # information.
- def push_workspace(*_main)
- if _main.empty?
- if workspaces.empty?
- print "No other workspace\n"
- return nil
- end
- ws = workspaces.pop
- workspaces.push @workspace
- @workspace = ws
- return workspaces
- end
-
- workspaces.push @workspace
- @workspace = WorkSpace.new(@workspace.binding, _main[0])
- if !(class<<main;ancestors;end).include?(ExtendCommandBundle)
- main.extend ExtendCommandBundle
- end
- end
-
- # Removes the last element from the current #workspaces stack and returns
- # it, or +nil+ if the current workspace stack is empty.
- #
- # Also, see #push_workspace.
- def pop_workspace
- if workspaces.empty?
- print "workspace stack empty\n"
- return
- end
- @workspace = workspaces.pop
- end
- end
-end
diff --git a/lib/irb/extend-command.rb b/lib/irb/extend-command.rb
deleted file mode 100644
index 5020b1e5cd..0000000000
--- a/lib/irb/extend-command.rb
+++ /dev/null
@@ -1,428 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/extend-command.rb - irb extend command
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
- # Installs the default irb extensions command bundle.
- module 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
-
- # Displays current configuration.
- #
- # Modifying the configuration is achieved by sending a message to IRB.conf.
- def irb_context
- IRB.CurrentContext
- end
-
- @ALIASES = [
- [:context, :irb_context, NO_OVERRIDE],
- [:conf, :irb_context, NO_OVERRIDE],
- [:irb_quit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
- [:exit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
- [:quit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
- ]
-
-
- @EXTEND_COMMANDS = [
- [
- :irb_current_working_workspace, :CurrentWorkingWorkspace, "cmd/chws",
- [:cwws, NO_OVERRIDE],
- [:pwws, NO_OVERRIDE],
- [:irb_print_working_workspace, OVERRIDE_ALL],
- [:irb_cwws, OVERRIDE_ALL],
- [:irb_pwws, OVERRIDE_ALL],
- [:irb_current_working_binding, OVERRIDE_ALL],
- [:irb_print_working_binding, OVERRIDE_ALL],
- [:irb_cwb, OVERRIDE_ALL],
- [:irb_pwb, OVERRIDE_ALL],
- ],
- [
- :irb_change_workspace, :ChangeWorkspace, "cmd/chws",
- [:chws, NO_OVERRIDE],
- [:cws, NO_OVERRIDE],
- [:irb_chws, OVERRIDE_ALL],
- [:irb_cws, OVERRIDE_ALL],
- [:irb_change_binding, OVERRIDE_ALL],
- [:irb_cb, OVERRIDE_ALL],
- [:cb, NO_OVERRIDE],
- ],
-
- [
- :irb_workspaces, :Workspaces, "cmd/pushws",
- [:workspaces, NO_OVERRIDE],
- [:irb_bindings, OVERRIDE_ALL],
- [:bindings, NO_OVERRIDE],
- ],
- [
- :irb_push_workspace, :PushWorkspace, "cmd/pushws",
- [:pushws, NO_OVERRIDE],
- [:irb_pushws, OVERRIDE_ALL],
- [:irb_push_binding, OVERRIDE_ALL],
- [:irb_pushb, OVERRIDE_ALL],
- [:pushb, NO_OVERRIDE],
- ],
- [
- :irb_pop_workspace, :PopWorkspace, "cmd/pushws",
- [:popws, NO_OVERRIDE],
- [:irb_popws, OVERRIDE_ALL],
- [:irb_pop_binding, OVERRIDE_ALL],
- [:irb_popb, OVERRIDE_ALL],
- [:popb, NO_OVERRIDE],
- ],
-
- [
- :irb_load, :Load, "cmd/load"],
- [
- :irb_require, :Require, "cmd/load"],
- [
- :irb_source, :Source, "cmd/load",
- [:source, NO_OVERRIDE],
- ],
-
- [
- :irb, :IrbCommand, "cmd/subirb"],
- [
- :irb_jobs, :Jobs, "cmd/subirb",
- [:jobs, NO_OVERRIDE],
- ],
- [
- :irb_fg, :Foreground, "cmd/subirb",
- [:fg, NO_OVERRIDE],
- ],
- [
- :irb_kill, :Kill, "cmd/subirb",
- [:kill, OVERRIDE_PRIVATE_ONLY],
- ],
-
- [
- :irb_debug, :Debug, "cmd/debug",
- [:debug, NO_OVERRIDE],
- ],
- [
- :irb_edit, :Edit, "cmd/edit",
- [:edit, NO_OVERRIDE],
- ],
- [
- :irb_break, :Break, "cmd/break",
- ],
- [
- :irb_catch, :Catch, "cmd/catch",
- ],
- [
- :irb_next, :Next, "cmd/next"
- ],
- [
- :irb_delete, :Delete, "cmd/delete",
- [:delete, NO_OVERRIDE],
- ],
- [
- :irb_step, :Step, "cmd/step",
- [:step, NO_OVERRIDE],
- ],
- [
- :irb_continue, :Continue, "cmd/continue",
- [:continue, NO_OVERRIDE],
- ],
- [
- :irb_finish, :Finish, "cmd/finish",
- [:finish, NO_OVERRIDE],
- ],
- [
- :irb_backtrace, :Backtrace, "cmd/backtrace",
- [:backtrace, NO_OVERRIDE],
- [:bt, NO_OVERRIDE],
- ],
- [
- :irb_debug_info, :Info, "cmd/info",
- [:info, NO_OVERRIDE],
- ],
-
- [
- :irb_help, :Help, "cmd/help",
- [:show_doc, NO_OVERRIDE],
- [:help, NO_OVERRIDE],
- ],
-
- [
- :irb_info, :IrbInfo, "cmd/irb_info"
- ],
-
- [
- :irb_ls, :Ls, "cmd/ls",
- [:ls, NO_OVERRIDE],
- ],
-
- [
- :irb_measure, :Measure, "cmd/measure",
- [:measure, NO_OVERRIDE],
- ],
-
- [
- :irb_show_source, :ShowSource, "cmd/show_source",
- [:show_source, NO_OVERRIDE],
- ],
-
- [
- :irb_whereami, :Whereami, "cmd/whereami",
- [:whereami, NO_OVERRIDE],
- ],
- [
- :irb_show_cmds, :ShowCmds, "cmd/show_cmds",
- [:show_cmds, NO_OVERRIDE],
- ]
- ]
-
-
- @@commands = []
-
- def self.all_commands_info
- return @@commands unless @@commands.empty?
- user_aliases = IRB.CurrentContext.command_aliases.each_with_object({}) do |(alias_name, target), result|
- result[target] ||= []
- result[target] << alias_name
- end
-
- @EXTEND_COMMANDS.each do |cmd_name, cmd_class, load_file, *aliases|
- if !defined?(ExtendCommand) || !ExtendCommand.const_defined?(cmd_class, false)
- require_relative load_file
- end
-
- klass = ExtendCommand.const_get(cmd_class, false)
- aliases = aliases.map { |a| a.first }
-
- if additional_aliases = user_aliases[cmd_name]
- aliases += additional_aliases
- end
-
- display_name = aliases.shift || cmd_name
- @@commands << { display_name: display_name, description: klass.description, category: klass.category }
- end
-
- @@commands
- end
-
- # Convert a command name to its implementation class if such command exists
- def self.load_command(command)
- command = command.to_sym
- @EXTEND_COMMANDS.each do |cmd_name, cmd_class, load_file, *aliases|
- next if cmd_name != command && aliases.all? { |alias_name, _| alias_name != command }
-
- if !defined?(ExtendCommand) || !ExtendCommand.const_defined?(cmd_class, false)
- require_relative load_file
- end
- return ExtendCommand.const_get(cmd_class, false)
- end
- nil
- end
-
- # Installs the default irb commands.
- def self.install_extend_commands
- for args in @EXTEND_COMMANDS
- def_extend_command(*args)
- end
- end
-
- # 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
- cmd_class = cmd_class.id2name
- when String
- when Class
- cmd_class = cmd_class.name
- end
-
- if load_file
- kwargs = ", **kwargs" if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0"
- line = __LINE__; eval %[
- def #{cmd_name}(*opts#{kwargs}, &b)
- Kernel.require_relative "#{load_file}"
- arity = ::IRB::ExtendCommand::#{cmd_class}.instance_method(:execute).arity
- args = (1..(arity < 0 ? ~arity : arity)).map {|i| "arg" + i.to_s }
- args << "*opts#{kwargs}" if arity < 0
- args << "&block"
- args = args.join(", ")
- line = __LINE__; eval %[
- unless singleton_class.class_variable_defined?(:@@#{cmd_name}_)
- singleton_class.class_variable_set(:@@#{cmd_name}_, true)
- def self.#{cmd_name}_(\#{args})
- ::IRB::ExtendCommand::#{cmd_class}.execute(irb_context, \#{args})
- end
- end
- ], nil, __FILE__, line
- __send__ :#{cmd_name}_, *opts#{kwargs}, &b
- end
- ], nil, __FILE__, line
- else
- line = __LINE__; eval %[
- def #{cmd_name}(*opts, &b)
- ::IRB::ExtendCommand::#{cmd_class}.execute(irb_context, *opts, &b)
- end
- ], nil, __FILE__, line
- end
-
- for ali, flag in aliases
- @ALIASES.push [ali, cmd_name, flag]
- end
- end
-
- # 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)
-
- if override == OVERRIDE_ALL or
- (override == OVERRIDE_PRIVATE_ONLY) && !respond_to?(to) or
- (override == NO_OVERRIDE) && !respond_to?(to, true)
- target = self
- (class << self; self; end).instance_eval{
- if target.respond_to?(to, true) &&
- !target.respond_to?(EXCB.irb_original_method_name(to), true)
- alias_method(EXCB.irb_original_method_name(to), to)
- end
- alias_method to, from
- }
- else
- Kernel.print "irb: warn: can't alias #{to} from #{from}.\n"
- end
- end
-
- 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
- for ali, com, flg in @ALIASES
- obj.install_alias_method(ali, com, flg)
- end
- end
- end
-
- install_extend_commands
- end
-
- # Extends methods for the Context module
- module ContextExtender
- CE = ContextExtender # :nodoc:
-
- @EXTEND_COMMANDS = [
- [:eval_history=, "ext/history.rb"],
- [:use_tracer=, "ext/tracer.rb"],
- [:use_loader=, "ext/use-loader.rb"],
- [:save_history=, "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#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)
- Context.module_eval {remove_method(:#{cmd_name})}
- require_relative "#{load_file}"
- __send__ :#{cmd_name}, *opts, &b
- end
- for ali in aliases
- alias_method ali, cmd_name
- end
- ], __FILE__, line
- end
-
- 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
-
- alias_name = new_alias_name(base_method)
- module_eval %[
- alias_method alias_name, base_method
- def #{base_method}(*opts)
- __send__ :#{extend_method}, *opts
- __send__ :#{alias_name}, *opts
- end
- ]
- 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
-
- alias_name = new_alias_name(base_method)
- module_eval %[
- alias_method alias_name, base_method
- def #{base_method}(*opts)
- __send__ :#{alias_name}, *opts
- __send__ :#{extend_method}, *opts
- end
- ]
- end
-
- # 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)
- same_methods = all_methods.grep(/^#{Regexp.quote(base_name)}[0-9]*$/)
- return base_name if same_methods.empty?
- no = same_methods.size
- while !same_methods.include?(alias_name = base_name + no)
- no += 1
- end
- alias_name
- end
- end
-end
diff --git a/lib/irb/frame.rb b/lib/irb/frame.rb
deleted file mode 100644
index 14768bd8f6..0000000000
--- a/lib/irb/frame.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: false
-#
-# frame.rb -
-# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
-#
-
-module IRB
- class Frame
- class FrameOverflow < StandardError
- def initialize
- super("frame overflow")
- end
- end
- class FrameUnderflow < StandardError
- def initialize
- super("frame underflow")
- end
- end
-
- # 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'
- @frames.push binding
- when 'return', 'end'
- @frames.pop
- 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
-
- # 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
-
- @backtrace = Frame.new
- set_trace_func proc{|event, file, line, id, binding, klass|
- @backtrace.trace_func(event, file, line, id, binding)
- }
- end
-end
diff --git a/lib/irb/help.rb b/lib/irb/help.rb
deleted file mode 100644
index 7624d05dd4..0000000000
--- a/lib/irb/help.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/help.rb - print usage module
-# by Keiju ISHITSUKA(keiju@ishitsuka.com)
-#
-
-require_relative '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")
- space_line = false
- IRB::MagicFile.open(path){|f|
- f.each_line do |l|
- if /^\s*$/ =~ l
- lc.puts l unless space_line
- space_line = true
- next
- end
- space_line = false
-
- l.sub!(/#.*$/, "")
- next if /^\s*$/ =~ l
- lc.puts l
- end
- }
- end
-end
diff --git a/lib/irb/init.rb b/lib/irb/init.rb
deleted file mode 100644
index f790f7f41d..0000000000
--- a/lib/irb/init.rb
+++ /dev/null
@@ -1,444 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/init.rb - irb initialize module
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
-
- # initialize config
- def IRB.setup(ap_path, argv: ::ARGV)
- IRB.init_config(ap_path)
- IRB.init_error
- IRB.parse_opts(argv: argv)
- IRB.run_config
- IRB.load_modules
-
- unless @CONF[:PROMPT][@CONF[:PROMPT_MODE]]
- fail UndefinedPromptMode, @CONF[:PROMPT_MODE]
- end
- end
-
- # @CONF default setting
- def IRB.init_config(ap_path)
- # class instance variables
- @TRACER_INITIALIZED = false
-
- # default configurations
- unless ap_path and @CONF[:AP_NAME]
- ap_path = File.join(File.dirname(File.dirname(__FILE__)), "irb.rb")
- end
- @CONF[:AP_NAME] = File::basename(ap_path, ".rb")
-
- @CONF[:IRB_NAME] = "irb"
- @CONF[:IRB_LIB_PATH] = File.dirname(__FILE__)
-
- @CONF[:RC] = true
- @CONF[:LOAD_MODULES] = []
- @CONF[:IRB_RC] = nil
-
- @CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod)
- @CONF[:USE_COLORIZE] = (nc = ENV['NO_COLOR']).nil? || nc.empty?
- @CONF[:USE_AUTOCOMPLETE] = ENV.fetch("IRB_USE_AUTOCOMPLETE", "true") != "false"
- @CONF[:INSPECT_MODE] = true
- @CONF[:USE_TRACER] = false
- @CONF[:USE_LOADER] = false
- @CONF[:IGNORE_SIGINT] = true
- @CONF[:IGNORE_EOF] = false
- @CONF[:EXTRA_DOC_DIRS] = []
- @CONF[:ECHO] = nil
- @CONF[:ECHO_ON_ASSIGNMENT] = nil
- @CONF[:VERBOSE] = nil
-
- @CONF[:EVAL_HISTORY] = nil
- @CONF[:SAVE_HISTORY] = 1000
-
- @CONF[:BACK_TRACE_LIMIT] = 16
-
- @CONF[:PROMPT] = {
- :NULL => {
- :PROMPT_I => nil,
- :PROMPT_N => nil,
- :PROMPT_S => nil,
- :PROMPT_C => nil,
- :RETURN => "%s\n"
- },
- :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\n"
- },
- :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\n"
- },
- :SIMPLE => {
- :PROMPT_I => ">> ",
- :PROMPT_N => ">> ",
- :PROMPT_S => "%l> ",
- :PROMPT_C => "?> ",
- :RETURN => "=> %s\n"
- },
- :INF_RUBY => {
- :PROMPT_I => "%N(%m):%03n:%i> ",
- :PROMPT_N => nil,
- :PROMPT_S => nil,
- :PROMPT_C => nil,
- :RETURN => "%s\n",
- :AUTO_INDENT => true
- },
- :XMP => {
- :PROMPT_I => nil,
- :PROMPT_N => nil,
- :PROMPT_S => nil,
- :PROMPT_C => nil,
- :RETURN => " ==>%s\n"
- }
- }
-
- @CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL)
- @CONF[:AUTO_INDENT] = true
-
- @CONF[:CONTEXT_MODE] = 4 # use a copy of TOPLEVEL_BINDING
- @CONF[:SINGLE_IRB] = false
-
- @CONF[:MEASURE] = false
- @CONF[:MEASURE_PROC] = {}
- @CONF[:MEASURE_PROC][:TIME] = proc { |context, code, line_no, &block|
- time = Time.now
- result = block.()
- now = Time.now
- puts 'processing time: %fs' % (now - time) if IRB.conf[:MEASURE]
- result
- }
- # arg can be either a symbol for the mode (:cpu, :wall, ..) or a hash for
- # a more complete configuration.
- # See https://github.com/tmm1/stackprof#all-options.
- @CONF[:MEASURE_PROC][:STACKPROF] = proc { |context, code, line_no, arg, &block|
- return block.() unless IRB.conf[:MEASURE]
- success = false
- begin
- require 'stackprof'
- success = true
- rescue LoadError
- puts 'Please run "gem install stackprof" before measuring by StackProf.'
- end
- if success
- result = nil
- arg = { mode: arg || :cpu } unless arg.is_a?(Hash)
- stackprof_result = StackProf.run(**arg) do
- result = block.()
- end
- case stackprof_result
- when File
- puts "StackProf report saved to #{stackprof_result.path}"
- when Hash
- StackProf::Report.new(stackprof_result).print_text
- else
- puts "Stackprof ran with #{arg.inspect}"
- end
- result
- else
- block.()
- end
- }
- @CONF[:MEASURE_CALLBACKS] = []
-
- @CONF[:LC_MESSAGES] = Locale.new
-
- @CONF[:AT_EXIT] = []
-
- @CONF[:COMMAND_ALIASES] = {
- # Symbol aliases
- :'$' => :show_source,
- :'@' => :whereami,
- # Keyword aliases
- :break => :irb_break,
- :catch => :irb_catch,
- :next => :irb_next,
- }
- end
-
- def IRB.set_measure_callback(type = nil, arg = nil, &block)
- added = nil
- if type
- type_sym = type.upcase.to_sym
- if IRB.conf[:MEASURE_PROC][type_sym]
- added = [type_sym, IRB.conf[:MEASURE_PROC][type_sym], arg]
- end
- elsif IRB.conf[:MEASURE_PROC][:CUSTOM]
- added = [:CUSTOM, IRB.conf[:MEASURE_PROC][:CUSTOM], arg]
- elsif block_given?
- added = [:BLOCK, block, arg]
- found = IRB.conf[:MEASURE_CALLBACKS].find{ |m| m[0] == added[0] && m[2] == added[2] }
- if found
- found[1] = block
- return added
- else
- IRB.conf[:MEASURE_CALLBACKS] << added
- return added
- end
- else
- added = [:TIME, IRB.conf[:MEASURE_PROC][:TIME], arg]
- end
- if added
- found = IRB.conf[:MEASURE_CALLBACKS].find{ |m| m[0] == added[0] && m[2] == added[2] }
- if found
- # already added
- nil
- else
- IRB.conf[:MEASURE_CALLBACKS] << added if added
- added
- end
- else
- nil
- end
- end
-
- def IRB.unset_measure_callback(type = nil)
- if type.nil?
- IRB.conf[:MEASURE_CALLBACKS].clear
- else
- type_sym = type.upcase.to_sym
- IRB.conf[:MEASURE_CALLBACKS].reject!{ |t, | t == type_sym }
- end
- end
-
- def IRB.init_error
- @CONF[:LC_MESSAGES].load("irb/error.rb")
- end
-
- # option analyzing
- def IRB.parse_opts(argv: ::ARGV)
- load_path = []
- while opt = argv.shift
- case opt
- when "-f"
- @CONF[:RC] = false
- when "-d"
- $DEBUG = true
- $VERBOSE = true
- when "-w"
- Warning[:deprecated] = $VERBOSE = true
- when /^-W(.+)?/
- opt = $1 || argv.shift
- case opt
- when "0"
- $VERBOSE = nil
- when "1"
- $VERBOSE = false
- else
- Warning[:deprecated] = $VERBOSE = true
- end
- when /^-r(.+)?/
- opt = $1 || argv.shift
- @CONF[:LOAD_MODULES].push opt if opt
- when /^-I(.+)?/
- opt = $1 || argv.shift
- load_path.concat(opt.split(File::PATH_SEPARATOR)) if opt
- when '-U'
- set_encoding("UTF-8", "UTF-8")
- when /^-E(.+)?/, /^--encoding(?:=(.+))?/
- opt = $1 || argv.shift
- set_encoding(*opt.split(':', 2))
- when "--inspect"
- if /^-/ !~ argv.first
- @CONF[:INSPECT_MODE] = argv.shift
- else
- @CONF[:INSPECT_MODE] = true
- end
- when "--noinspect"
- @CONF[:INSPECT_MODE] = false
- when "--singleline", "--readline", "--legacy"
- @CONF[:USE_SINGLELINE] = true
- when "--nosingleline", "--noreadline"
- @CONF[:USE_SINGLELINE] = false
- when "--multiline", "--reidline"
- if opt == "--reidline"
- warn <<~MSG.strip
- --reidline is deprecated, please use --multiline instead.
- MSG
- end
-
- @CONF[:USE_MULTILINE] = true
- when "--nomultiline", "--noreidline"
- if opt == "--noreidline"
- warn <<~MSG.strip
- --noreidline is deprecated, please use --nomultiline instead.
- MSG
- end
-
- @CONF[:USE_MULTILINE] = false
- when /^--extra-doc-dir(?:=(.+))?/
- opt = $1 || argv.shift
- @CONF[:EXTRA_DOC_DIRS] << opt
- when "--echo"
- @CONF[:ECHO] = true
- when "--noecho"
- @CONF[:ECHO] = false
- when "--echo-on-assignment"
- @CONF[:ECHO_ON_ASSIGNMENT] = true
- when "--noecho-on-assignment"
- @CONF[:ECHO_ON_ASSIGNMENT] = false
- when "--truncate-echo-on-assignment"
- @CONF[:ECHO_ON_ASSIGNMENT] = :truncate
- when "--verbose"
- @CONF[:VERBOSE] = true
- when "--noverbose"
- @CONF[:VERBOSE] = false
- when "--colorize"
- @CONF[:USE_COLORIZE] = true
- when "--nocolorize"
- @CONF[:USE_COLORIZE] = false
- when "--autocomplete"
- @CONF[:USE_AUTOCOMPLETE] = true
- when "--noautocomplete"
- @CONF[:USE_AUTOCOMPLETE] = false
- when /^--prompt-mode(?:=(.+))?/, /^--prompt(?:=(.+))?/
- opt = $1 || argv.shift
- prompt_mode = opt.upcase.tr("-", "_").intern
- @CONF[:PROMPT_MODE] = prompt_mode
- when "--noprompt"
- @CONF[:PROMPT_MODE] = :NULL
- when "--script"
- noscript = false
- when "--noscript"
- noscript = true
- when "--inf-ruby-mode"
- @CONF[:PROMPT_MODE] = :INF_RUBY
- when "--sample-book-mode", "--simple-prompt"
- @CONF[:PROMPT_MODE] = :SIMPLE
- when "--tracer"
- @CONF[:USE_TRACER] = true
- when /^--back-trace-limit(?:=(.+))?/
- @CONF[:BACK_TRACE_LIMIT] = ($1 || argv.shift).to_i
- when /^--context-mode(?:=(.+))?/
- @CONF[:CONTEXT_MODE] = ($1 || argv.shift).to_i
- when "--single-irb"
- @CONF[:SINGLE_IRB] = true
- when "-v", "--version"
- print IRB.version, "\n"
- exit 0
- when "-h", "--help"
- require_relative "help"
- IRB.print_usage
- exit 0
- when "--"
- if !noscript && (opt = argv.shift)
- @CONF[:SCRIPT] = opt
- $0 = opt
- end
- break
- when /^-./
- fail UnrecognizedSwitch, opt
- else
- if noscript
- argv.unshift(opt)
- else
- @CONF[:SCRIPT] = opt
- $0 = opt
- end
- break
- end
- end
-
- load_path.collect! do |path|
- /\A\.\// =~ path ? path : File.expand_path(path)
- end
- $LOAD_PATH.unshift(*load_path)
- end
-
- # running config
- def IRB.run_config
- if @CONF[:RC]
- begin
- load rc_file
- rescue LoadError, Errno::ENOENT
- rescue # StandardError, ScriptError
- print "load error: #{rc_file}\n"
- print $!.class, ": ", $!, "\n"
- for err in $@[0, $@.size - 2]
- print "\t", err, "\n"
- end
- end
- end
- end
-
- IRBRC_EXT = "rc"
- def IRB.rc_file(ext = IRBRC_EXT)
- if !@CONF[:RC_NAME_GENERATOR]
- rc_file_generators do |rcgen|
- @CONF[:RC_NAME_GENERATOR] ||= rcgen
- if File.exist?(rcgen.call(IRBRC_EXT))
- @CONF[:RC_NAME_GENERATOR] = rcgen
- break
- end
- end
- end
- case rc_file = @CONF[:RC_NAME_GENERATOR].call(ext)
- when String
- return rc_file
- else
- fail IllegalRCNameGenerator
- end
- end
-
- # enumerate possible rc-file base name generators
- def IRB.rc_file_generators
- if irbrc = ENV["IRBRC"]
- yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc}
- end
- if xdg_config_home = ENV["XDG_CONFIG_HOME"]
- irb_home = File.join(xdg_config_home, "irb")
- if File.directory?(irb_home)
- yield proc{|rc| irb_home + "/irb#{rc}"}
- end
- end
- if home = ENV["HOME"]
- yield proc{|rc| home+"/.irb#{rc}"}
- yield proc{|rc| home+"/.config/irb/irb#{rc}"}
- end
- current_dir = Dir.pwd
- yield proc{|rc| current_dir+"/.irb#{rc}"}
- yield proc{|rc| current_dir+"/irb#{rc.sub(/\A_?/, '.')}"}
- yield proc{|rc| current_dir+"/_irb#{rc}"}
- yield proc{|rc| current_dir+"/$irb#{rc}"}
- end
-
- # loading modules
- def IRB.load_modules
- for m in @CONF[:LOAD_MODULES]
- begin
- require m
- rescue LoadError => err
- warn "#{err.class}: #{err}", uplevel: 0
- end
- end
- end
-
-
- DefaultEncodings = Struct.new(:external, :internal)
- class << IRB
- private
- def set_encoding(extern, intern = nil, override: true)
- verbose, $VERBOSE = $VERBOSE, nil
- Encoding.default_external = extern unless extern.nil? || extern.empty?
- Encoding.default_internal = intern unless intern.nil? || intern.empty?
- [$stdin, $stdout, $stderr].each do |io|
- io.set_encoding(extern, intern)
- end
- if override
- @CONF[:LC_MESSAGES].instance_variable_set(:@override_encoding, extern)
- else
- @CONF[:LC_MESSAGES].instance_variable_set(:@encoding, extern)
- end
- ensure
- $VERBOSE = verbose
- end
- end
-end
diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb
deleted file mode 100644
index bc61805ebb..0000000000
--- a/lib/irb/input-method.rb
+++ /dev/null
@@ -1,478 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/input-method.rb - input methods used irb
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative 'src_encoding'
-require_relative 'magic-file'
-require_relative 'completion'
-require 'io/console'
-require 'reline'
-
-module IRB
- STDIN_FILE_NAME = "(line)" # :nodoc:
- class InputMethod
-
- # 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
- fail NotImplementedError, "gets"
- end
- public :gets
-
- def winsize
- if instance_variable_defined?(:@stdout) && @stdout.tty?
- @stdout.winsize
- else
- [24, 80]
- end
- end
-
- # Whether this input method is still readable when there is no more data to
- # read.
- #
- # See IO#eof for more information.
- def readable_after_eof?
- false
- end
-
- # For debug message
- def inspect
- 'Abstract InputMethod'
- end
- end
-
- class StdioInputMethod < InputMethod
- # Creates a new input method object
- def initialize
- super
- @line_no = 0
- @line = []
- @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
- @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?
- if @stdin.wait_readable(0.00001)
- c = @stdin.getc
- result = c.nil? ? true : false
- @stdin.ungetc(c) unless c.nil?
- result
- else # buffer is empty
- false
- end
- end
-
- # Whether this input method is still readable when there is no more data to
- # read.
- #
- # See IO#eof for more information.
- def readable_after_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
-
- # For debug message
- def inspect
- 'StdioInputMethod'
- end
- end
-
- # Use a File for IO with irb, see InputMethod
- class FileInputMethod < InputMethod
- class << self
- def open(file, &block)
- begin
- io = new(file)
- block.call(io)
- ensure
- io&.close
- end
- end
- end
-
- # Creates a new input method object
- def initialize(file)
- super
- @io = file.is_a?(IO) ? file : IRB::MagicFile.open(file)
- @external_encoding = @io.external_encoding
- 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.closed? || @io.eof?
- end
-
- # Reads the next line from this input method.
- #
- # See IO#gets for more information.
- def gets
- print @prompt
- @io.gets
- end
-
- # The external encoding for standard input.
- def encoding
- @external_encoding
- end
-
- # For debug message
- def inspect
- 'FileInputMethod'
- end
-
- def close
- @io.close
- end
- end
-
- begin
- class ReadlineInputMethod < InputMethod
- def self.initialize_readline
- require "readline"
- rescue LoadError
- else
- include ::Readline
- end
-
- # Creates a new input method object using Readline
- def initialize
- self.class.initialize_readline
- if Readline.respond_to?(:encoding_system_needs)
- IRB.__send__(:set_encoding, Readline.encoding_system_needs.name, override: false)
- end
- super
-
- @line_no = 0
- @line = []
- @eof = false
-
- @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
- @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
-
- if Readline.respond_to?("basic_word_break_characters=")
- Readline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS
- end
- Readline.completion_append_character = nil
- Readline.completion_proc = IRB::InputCompletor::CompletionProc
- end
-
- # Reads the next line from this input method.
- #
- # See IO#gets for more information.
- def gets
- Readline.input = @stdin
- Readline.output = @stdout
- if l = readline(@prompt, false)
- HISTORY.push(l) if !l.empty?
- @line[@line_no += 1] = l + "\n"
- else
- @eof = true
- l
- 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_after_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
-
- # For debug message
- def inspect
- readline_impl = (defined?(Reline) && Readline == Reline) ? 'Reline' : 'ext/readline'
- str = "ReadlineInputMethod with #{readline_impl} #{Readline::VERSION}"
- inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc')
- str += " and #{inputrc_path}" if File.exist?(inputrc_path)
- str
- end
- end
- end
-
- class RelineInputMethod < InputMethod
- include Reline
-
- # Creates a new input method object using Reline
- def initialize
- IRB.__send__(:set_encoding, Reline.encoding_system_needs.name, override: false)
- super
-
- @line_no = 0
- @line = []
- @eof = false
-
- @stdin = ::IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
- @stdout = ::IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
-
- if Reline.respond_to?("basic_word_break_characters=")
- Reline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS
- end
- Reline.completion_append_character = nil
- Reline.completer_quote_characters = ''
- Reline.completion_proc = IRB::InputCompletor::CompletionProc
- Reline.output_modifier_proc =
- if IRB.conf[:USE_COLORIZE]
- proc do |output, complete: |
- next unless IRB::Color.colorable?
- lvars = IRB.CurrentContext&.local_variables || []
- IRB::Color.colorize_code(output, complete: complete, local_variables: lvars)
- end
- else
- proc do |output|
- Reline::Unicode.escape_for_print(output)
- end
- end
- Reline.dig_perfect_match_proc = IRB::InputCompletor::PerfectMatchedProc
- Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE]
-
- if IRB.conf[:USE_AUTOCOMPLETE]
- begin
- require 'rdoc'
- Reline.add_dialog_proc(:show_doc, SHOW_DOC_DIALOG, Reline::DEFAULT_DIALOG_CONTEXT)
- rescue LoadError
- end
- end
- end
-
- def check_termination(&block)
- @check_termination_proc = block
- end
-
- def dynamic_prompt(&block)
- @prompt_proc = block
- end
-
- def auto_indent(&block)
- @auto_indent_proc = block
- end
-
- SHOW_DOC_DIALOG = ->() {
- dialog.trap_key = nil
- alt_d = [
- [Reline::Key.new(nil, 0xE4, true)], # Normal Alt+d.
- [27, 100], # Normal Alt+d when convert-meta isn't used.
- [195, 164], # The "ä" that appears when Alt+d is pressed on xterm.
- [226, 136, 130] # The "∂" that appears when Alt+d in pressed on iTerm2.
- ]
-
- if just_cursor_moving and completion_journey_data.nil?
- return nil
- end
- cursor_pos_to_render, result, pointer, autocomplete_dialog = context.pop(4)
- return nil if result.nil? or pointer.nil? or pointer < 0
- name = result[pointer]
- name = IRB::InputCompletor.retrieve_completion_data(name, doc_namespace: true)
-
- options = {}
- options[:extra_doc_dirs] = IRB.conf[:EXTRA_DOC_DIRS] unless IRB.conf[:EXTRA_DOC_DIRS].empty?
- driver = RDoc::RI::Driver.new(options)
-
- if key.match?(dialog.name)
- begin
- driver.display_names([name])
- rescue RDoc::RI::Driver::NotFoundError
- end
- end
-
- begin
- name = driver.expand_name(name)
- rescue RDoc::RI::Driver::NotFoundError
- return nil
- rescue
- return nil # unknown error
- end
- doc = nil
- used_for_class = false
- if not name =~ /#|\./
- found, klasses, includes, extends = driver.classes_and_includes_and_extends_for(name)
- if not found.empty?
- doc = driver.class_document(name, found, klasses, includes, extends)
- used_for_class = true
- end
- end
- unless used_for_class
- doc = RDoc::Markup::Document.new
- begin
- driver.add_method(doc, name)
- rescue RDoc::RI::Driver::NotFoundError
- doc = nil
- rescue
- return nil # unknown error
- end
- end
- return nil if doc.nil?
- width = 40
-
- right_x = cursor_pos_to_render.x + autocomplete_dialog.width
- if right_x + width > screen_width
- right_width = screen_width - (right_x + 1)
- left_x = autocomplete_dialog.column - width
- left_x = 0 if left_x < 0
- left_width = width > autocomplete_dialog.column ? autocomplete_dialog.column : width
- if right_width.positive? and left_width.positive?
- if right_width >= left_width
- width = right_width
- x = right_x
- else
- width = left_width
- x = left_x
- end
- elsif right_width.positive? and left_width <= 0
- width = right_width
- x = right_x
- elsif right_width <= 0 and left_width.positive?
- width = left_width
- x = left_x
- else # Both are negative width.
- return nil
- end
- else
- x = right_x
- end
- formatter = RDoc::Markup::ToAnsi.new
- formatter.width = width
- dialog.trap_key = alt_d
- message = 'Press Alt+d to read the full document'
- contents = [message] + doc.accept(formatter).split("\n")
-
- y = cursor_pos_to_render.y
- DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49')
- }
-
- # Reads the next line from this input method.
- #
- # See IO#gets for more information.
- def gets
- Reline.input = @stdin
- Reline.output = @stdout
- Reline.prompt_proc = @prompt_proc
- Reline.auto_indent_proc = @auto_indent_proc if @auto_indent_proc
- if l = readmultiline(@prompt, false, &@check_termination_proc)
- HISTORY.push(l) if !l.empty?
- @line[@line_no += 1] = l + "\n"
- else
- @eof = true
- l
- 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_after_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
-
- # For debug message
- def inspect
- config = Reline::Config.new
- str = "RelineInputMethod with Reline #{Reline::VERSION}"
- if config.respond_to?(:inputrc_path)
- inputrc_path = File.expand_path(config.inputrc_path)
- else
- inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc')
- end
- str += " and #{inputrc_path}" if File.exist?(inputrc_path)
- str
- end
- end
-
- class ReidlineInputMethod < RelineInputMethod
- def initialize
- warn <<~MSG.strip
- IRB::ReidlineInputMethod is deprecated, please use IRB::RelineInputMethod instead.
- MSG
- super
- end
- end
-end
diff --git a/lib/irb/inspector.rb b/lib/irb/inspector.rb
deleted file mode 100644
index 50f6ebf383..0000000000
--- a/lib/irb/inspector.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/inspector.rb - inspect methods
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-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
- # 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 self.keys_with_inspector(inspector)
- INSPECTORS.select{|k,v| v == inspector}.collect{|k, v| k}
- end
-
- # Example
- #
- # Inspector.def_inspector(key, init_p=nil){|v| v.inspect}
- # Inspector.def_inspector([key1,..], init_p=nil){|v| v.inspect}
- # Inspector.def_inspector(key, inspector)
- # Inspector.def_inspector([key1,...], inspector)
- def self.def_inspector(key, arg=nil, &block)
- if block_given?
- inspector = IRB::Inspector(block, arg)
- else
- inspector = arg
- end
-
- case key
- when Array
- for k in key
- def_inspector(k, inspector)
- end
- when Symbol
- INSPECTORS[key] = inspector
- INSPECTORS[key.to_s] = inspector
- when String
- INSPECTORS[key] = inspector
- INSPECTORS[key.intern] = inspector
- else
- INSPECTORS[key] = inspector
- end
- end
-
- # 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
- # dependent 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)
- rescue
- puts "(Object doesn't support #inspect)"
- ''
- end
- end
-
- Inspector.def_inspector([false, :to_s, :raw]){|v| v.to_s}
- Inspector.def_inspector([:p, :inspect]){|v|
- Color.colorize_code(v.inspect, colorable: Color.colorable? && Color.inspect_colorable?(v))
- }
- Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require_relative "color_printer"}){|v|
- IRB::ColorPrinter.pp(v, '').chomp
- }
- Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v|
- begin
- YAML.dump(v)
- rescue
- puts "(can't dump yaml. use inspect)"
- v.inspect
- end
- }
-
- Inspector.def_inspector([:marshal, :Marshal, :MARSHAL, Marshal]){|v|
- Marshal.dump(v)
- }
-end
diff --git a/lib/irb/irb.gemspec b/lib/irb/irb.gemspec
deleted file mode 100644
index c3e8a4dc58..0000000000
--- a/lib/irb/irb.gemspec
+++ /dev/null
@@ -1,40 +0,0 @@
-begin
- require_relative "lib/irb/version"
-rescue LoadError
- # for Ruby core repository
- require_relative "version"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "irb"
- spec.version = IRB::VERSION
- spec.authors = ["aycabta", "Keiju ISHITSUKA"]
- spec.email = ["aycabta@gmail.com", "keiju@ruby-lang.org"]
-
- spec.summary = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
- spec.description = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
- spec.homepage = "https://github.com/ruby/irb"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.files = [
- ".document",
- "Gemfile",
- "LICENSE.txt",
- "README.md",
- "Rakefile",
- "bin/console",
- "bin/setup",
- "doc/irb/irb-tools.rd.ja",
- "doc/irb/irb.rd.ja",
- "exe/irb",
- "irb.gemspec",
- "man/irb.1",
- ] + Dir.glob("lib/**/*")
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-
- spec.required_ruby_version = Gem::Requirement.new(">= 2.6")
-
- spec.add_dependency "reline", ">= 0.3.0"
-end
diff --git a/lib/irb/lc/error.rb b/lib/irb/lc/error.rb
deleted file mode 100644
index a5ec150865..0000000000
--- a/lib/irb/lc/error.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/lc/error.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- # :stopdoc:
-
- class UnrecognizedSwitch < StandardError
- def initialize(val)
- super("Unrecognized switch: #{val}")
- end
- end
- class NotImplementedError < StandardError
- def initialize(val)
- super("Need to define `#{val}'")
- end
- end
- class CantReturnToNormalMode < StandardError
- def initialize
- super("Can't return to normal mode.")
- end
- end
- class IllegalParameter < StandardError
- def initialize(val)
- super("Invalid parameter(#{val}).")
- end
- end
- class IrbAlreadyDead < StandardError
- def initialize
- super("Irb is already dead.")
- end
- end
- class IrbSwitchedToCurrentThread < StandardError
- def initialize
- super("Switched to current thread.")
- end
- end
- class NoSuchJob < StandardError
- def initialize(val)
- super("No such job(#{val}).")
- end
- end
- class CantChangeBinding < StandardError
- def initialize(val)
- super("Can't change binding to (#{val}).")
- end
- end
- class UndefinedPromptMode < StandardError
- def initialize(val)
- super("Undefined prompt mode(#{val}).")
- end
- end
- class IllegalRCGenerator < StandardError
- def initialize
- super("Define illegal RC_NAME_GENERATOR.")
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/lc/help-message b/lib/irb/lc/help-message
deleted file mode 100644
index 5b23f4c41e..0000000000
--- a/lib/irb/lc/help-message
+++ /dev/null
@@ -1,51 +0,0 @@
-Usage: irb.rb [options] [programfile] [arguments]
- -f Don't initialize from configuration file.
- -d Set $DEBUG and $VERBOSE to true (same as 'ruby -d').
- -r load-module Require load-module (same as 'ruby -r').
- -I path Specify $LOAD_PATH directory (same as 'ruby -I').
- -U Set external and internal encodings to UTF-8.
- -E ex[:in] Set default external (ex) and internal (in) encodings
- (same as 'ruby -E').
- -w Suppress warnings (same as 'ruby -w').
- -W[level=2] Set warning level: 0=silence, 1=medium, 2=verbose
- (same as 'ruby -W').
- --context-mode n Set n[0-4] to method to create Binding Object,
- when new workspace was created.
- --extra-doc-dir Add an extra doc dir for the doc dialog.
- --echo Show result (default).
- --noecho Don't show result.
- --echo-on-assignment
- Show result on assignment.
- --noecho-on-assignment
- Don't show result on assignment.
- --truncate-echo-on-assignment
- Show truncated result on assignment (default).
- --inspect Use 'inspect' for output.
- --noinspect Don't use 'inspect' for output.
- --multiline Use multiline editor module.
- --nomultiline Don't use multiline editor module (default).
- --singleline Use single line editor module.
- --nosingleline Don't use single line editor module (default).
- --colorize Use color-highlighting (default).
- --nocolorize Don't use color-highlighting.
- --autocomplete Use auto-completion (default).
- --noautocomplete Don't use auto-completion.
- --prompt prompt-mode, --prompt-mode prompt-mode
- Set prompt mode. Pre-defined prompt modes are:
- 'default', 'classic', 'simple', 'inf-ruby', 'xmp', 'null'.
- --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
- Suppresses --multiline and --singleline.
- --sample-book-mode, --simple-prompt
- Set prompt mode to 'simple'.
- --noprompt Don't output prompt.
- --script Script mode (default, treat first argument as script)
- --noscript No script mode (leave arguments in argv)
- --single-irb Share self with sub-irb.
- --tracer Show stack trace for each command.
- --back-trace-limit n[=16]
- Display backtrace top n and bottom n.
- --verbose Show details.
- --noverbose Don't show details.
- -v, --version Print the version of irb.
- -h, --help Print help.
- -- Separate options of irb from the list of command-line args.
diff --git a/lib/irb/lc/ja/encoding_aliases.rb b/lib/irb/lc/ja/encoding_aliases.rb
deleted file mode 100644
index 08180c3ec2..0000000000
--- a/lib/irb/lc/ja/encoding_aliases.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: false
-module IRB
- # :stopdoc:
-
- class Locale
- @@legacy_encoding_alias_map = {
- 'ujis' => Encoding::EUC_JP,
- 'euc' => Encoding::EUC_JP
- }.freeze
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/lc/ja/error.rb b/lib/irb/lc/ja/error.rb
deleted file mode 100644
index 50d72c4a10..0000000000
--- a/lib/irb/lc/ja/error.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/lc/ja/error.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- # :stopdoc:
-
- class UnrecognizedSwitch < StandardError
- def initialize(val)
- super("スイッチ(#{val})が分りません")
- end
- end
- class NotImplementedError < StandardError
- def initialize(val)
- super("`#{val}'の定義が必要です")
- end
- end
- class CantReturnToNormalMode < StandardError
- def initialize
- super("Normalモードに戻れません.")
- end
- end
- class IllegalParameter < StandardError
- def initialize(val)
- super("パラメータ(#{val})が間違っています.")
- end
- end
- class IrbAlreadyDead < StandardError
- def initialize
- super("Irbは既に死んでいます.")
- end
- end
- class IrbSwitchedToCurrentThread < StandardError
- def initialize
- super("カレントスレッドに切り替わりました.")
- end
- end
- class NoSuchJob < StandardError
- def initialize(val)
- super("そのようなジョブ(#{val})はありません.")
- end
- end
- class CantChangeBinding < StandardError
- def initialize(val)
- super("バインディング(#{val})に変更できません.")
- end
- end
- class UndefinedPromptMode < StandardError
- def initialize(val)
- super("プロンプトモード(#{val})は定義されていません.")
- end
- end
- class IllegalRCGenerator < StandardError
- def initialize
- super("RC_NAME_GENERATORが正しく定義されていません.")
- end
- end
-
- # :startdoc:
-end
-# vim:fileencoding=utf-8
diff --git a/lib/irb/lc/ja/help-message b/lib/irb/lc/ja/help-message
deleted file mode 100644
index 1c15d331ea..0000000000
--- a/lib/irb/lc/ja/help-message
+++ /dev/null
@@ -1,45 +0,0 @@
-Usage: irb.rb [options] [programfile] [arguments]
- -f ~/.irbrc を読み込まない.
- -d $DEBUG をtrueにする(ruby -d と同じ)
- -r load-module ruby -r と同じ.
- -I path $LOAD_PATH に path を追加する.
- -U ruby -U と同じ.
- -E enc ruby -E と同じ.
- -w ruby -w と同じ.
- -W[level=2] ruby -W と同じ.
- --context-mode n 新しいワークスペースを作成した時に関連する Binding
- オブジェクトの作成方法を 0 から 3 のいずれかに設定する.
- --echo 実行結果を表示する(デフォルト).
- --noecho 実行結果を表示しない.
- --inspect 結果出力にinspectを用いる.
- --noinspect 結果出力にinspectを用いない.
- --multiline マルチラインエディタを利用する.
- --nomultiline マルチラインエディタを利用しない.
- --singleline シングルラインエディタを利用する.
- --nosingleline シングルラインエディタを利用しない.
- --colorize 色付けを利用する.
- --nocolorize 色付けを利用しない.
- --autocomplete オートコンプリートを利用する.
- --noautocomplete オートコンプリートを利用しない.
- --prompt prompt-mode/--prompt-mode prompt-mode
- プロンプトモードを切替えます. 現在定義されているプ
- ロンプトモードは, default, simple, xmp, inf-rubyが
- 用意されています.
- --inf-ruby-mode emacsのinf-ruby-mode用のプロンプト表示を行なう. 特
- に指定がない限り, シングルラインエディタとマルチラ
- インエディタは使わなくなる.
- --sample-book-mode/--simple-prompt
- 非常にシンプルなプロンプトを用いるモードです.
- --noprompt プロンプト表示を行なわない.
- --single-irb irb 中で self を実行して得られるオブジェクトをサ
- ブ irb と共有する.
- --tracer コマンド実行時にトレースを行なう.
- --back-trace-limit n
- バックトレース表示をバックトレースの頭から n, 後ろ
- からnだけ行なう. デフォルトは16
-
- --verbose 詳細なメッセージを出力する.
- --noverbose 詳細なメッセージを出力しない(デフォルト).
- -v, --version irbのバージョンを表示する.
- -h, --help irb のヘルプを表示する.
- -- 以降のコマンドライン引数をオプションとして扱わない.
diff --git a/lib/irb/locale.rb b/lib/irb/locale.rb
deleted file mode 100644
index eb3028616d..0000000000
--- a/lib/irb/locale.rb
+++ /dev/null
@@ -1,186 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/locale.rb - internationalization module
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
- class Locale
-
- LOCALE_NAME_RE = %r[
- (?<language>[[:alpha:]]{2,3})
- (?:_ (?<territory>[[:alpha:]]{2,3}) )?
- (?:\. (?<codeset>[^@]+) )?
- (?:@ (?<modifier>.*) )?
- ]x
- LOCALE_DIR = "/lc/"
-
- @@legacy_encoding_alias_map = {}.freeze
- @@loaded = []
-
- def initialize(locale = nil)
- @override_encoding = nil
- @lang = @territory = @encoding_name = @modifier = nil
- @locale = locale || ENV["IRB_LANG"] || ENV["LC_MESSAGES"] || ENV["LC_ALL"] || ENV["LANG"] || "C"
- if m = LOCALE_NAME_RE.match(@locale)
- @lang, @territory, @encoding_name, @modifier = m[:language], m[:territory], m[:codeset], m[:modifier]
-
- if @encoding_name
- begin load 'irb/encoding_aliases.rb'; rescue LoadError; end
- if @encoding = @@legacy_encoding_alias_map[@encoding_name]
- warn(("%s is obsolete. use %s" % ["#{@lang}_#{@territory}.#{@encoding_name}", "#{@lang}_#{@territory}.#{@encoding.name}"]), uplevel: 1)
- end
- @encoding = Encoding.find(@encoding_name) rescue nil
- end
- end
- @encoding ||= (Encoding.find('locale') rescue Encoding::ASCII_8BIT)
- end
-
- attr_reader :lang, :territory, :modifier
-
- def encoding
- @override_encoding || @encoding
- end
-
- def String(mes)
- mes = super(mes)
- if encoding
- mes.encode(encoding, undef: :replace)
- else
- mes
- end
- end
-
- def format(*opts)
- String(super(*opts))
- end
-
- def gets(*rs)
- String(super(*rs))
- end
-
- def readline(*rs)
- String(super(*rs))
- end
-
- def print(*opts)
- ary = opts.collect{|opt| String(opt)}
- super(*ary)
- end
-
- def printf(*opts)
- s = format(*opts)
- print s
- end
-
- def puts(*opts)
- ary = opts.collect{|opt| String(opt)}
- super(*ary)
- end
-
- def require(file, priv = nil)
- rex = Regexp.new("lc/#{Regexp.quote(file)}\.(so|o|sl|rb)?")
- return false if $".find{|f| f =~ rex}
-
- case file
- when /\.rb$/
- begin
- load(file, priv)
- $".push file
- return true
- rescue LoadError
- end
- when /\.(so|o|sl)$/
- return super
- end
-
- begin
- load(f = file + ".rb")
- $".push f #"
- return true
- rescue LoadError
- return ruby_require(file)
- end
- end
-
- alias toplevel_load load
-
- def load(file, priv=nil)
- found = find(file)
- if found
- unless @@loaded.include?(found)
- @@loaded << found # cache
- return real_load(found, priv)
- end
- else
- raise LoadError, "No such file to load -- #{file}"
- end
- end
-
- def find(file , paths = $:)
- dir = File.dirname(file)
- dir = "" if dir == "."
- base = File.basename(file)
-
- if dir.start_with?('/')
- return each_localized_path(dir, base).find{|full_path| File.readable? full_path}
- else
- return search_file(paths, dir, base)
- end
- end
-
- private
- def real_load(path, priv)
- src = MagicFile.open(path){|f| f.read}
- if priv
- eval("self", TOPLEVEL_BINDING).extend(Module.new {eval(src, nil, path)})
- else
- eval(src, TOPLEVEL_BINDING, path)
- end
- end
-
- # @param paths load paths in which IRB find a localized file.
- # @param dir directory
- # @param file basename to be localized
- #
- # typically, for the parameters and a <path> in paths, it searches
- # <path>/<dir>/<locale>/<file>
- def search_file(lib_paths, dir, file)
- each_localized_path(dir, file) do |lc_path|
- lib_paths.each do |libpath|
- full_path = File.join(libpath, lc_path)
- return full_path if File.readable?(full_path)
- end
- redo if defined?(Gem) and Gem.try_activate(lc_path)
- end
- nil
- end
-
- def each_localized_path(dir, file)
- return enum_for(:each_localized_path) unless block_given?
- each_sublocale do |lc|
- yield lc.nil? ? File.join(dir, LOCALE_DIR, file) : File.join(dir, LOCALE_DIR, lc, file)
- end
- end
-
- def each_sublocale
- if @lang
- if @territory
- if @encoding_name
- yield "#{@lang}_#{@territory}.#{@encoding_name}@#{@modifier}" if @modifier
- yield "#{@lang}_#{@territory}.#{@encoding_name}"
- end
- yield "#{@lang}_#{@territory}@#{@modifier}" if @modifier
- yield "#{@lang}_#{@territory}"
- end
- if @encoding_name
- yield "#{@lang}.#{@encoding_name}@#{@modifier}" if @modifier
- yield "#{@lang}.#{@encoding_name}"
- end
- yield "#{@lang}@#{@modifier}" if @modifier
- yield "#{@lang}"
- end
- yield nil
- end
- end
-end
diff --git a/lib/irb/magic-file.rb b/lib/irb/magic-file.rb
deleted file mode 100644
index 34e06d64b3..0000000000
--- a/lib/irb/magic-file.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: false
-module IRB
- class << (MagicFile = Object.new)
- # see parser_magic_comment in parse.y
- ENCODING_SPEC_RE = %r"coding\s*[=:]\s*([[:alnum:]\-_]+)"
-
- def open(path)
- io = File.open(path, 'rb')
- line = io.gets
- line = io.gets if line[0,2] == "#!"
- encoding = detect_encoding(line)
- internal_encoding = encoding
- encoding ||= IRB.default_src_encoding
- io.rewind
- io.set_encoding(encoding, internal_encoding)
-
- if block_given?
- begin
- return (yield io)
- ensure
- io.close
- end
- else
- return io
- end
- end
-
- private
- def detect_encoding(line)
- return unless line[0] == ?#
- line = line[1..-1]
- line = $1 if line[/-\*-\s*(.*?)\s*-*-$/]
- return nil unless ENCODING_SPEC_RE =~ line
- encoding = $1
- return encoding.sub(/-(?:mac|dos|unix)/i, '')
- end
- end
-end
diff --git a/lib/irb/notifier.rb b/lib/irb/notifier.rb
deleted file mode 100644
index 612de3df16..0000000000
--- a/lib/irb/notifier.rb
+++ /dev/null
@@ -1,230 +0,0 @@
-# frozen_string_literal: false
-#
-# notifier.rb - output methods used by irb
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "output-method"
-
-module IRB
- # An output formatter used internally by the lexer.
- module Notifier
- class ErrUndefinedNotifier < StandardError
- def initialize(val)
- super("undefined notifier level: #{val} is specified")
- end
- end
- class ErrUnrecognizedLevel < StandardError
- def initialize(val)
- super("unrecognized notifier level: #{val} is specified")
- end
- end
-
- # 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, StdioOutputMethod 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
-
- @notifiers = [D_NOMSG]
- @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
- @level_notifier = value
- when Integer
- l = @notifiers[value]
- raise ErrUndefinedNotifier, value unless l
- @level_notifier = l
- else
- raise ErrUnrecognizedLevel, value unless l
- end
- end
-
- 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 # :nodoc:
- end
-end
diff --git a/lib/irb/output-method.rb b/lib/irb/output-method.rb
deleted file mode 100644
index f5ea57111d..0000000000
--- a/lib/irb/output-method.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-# frozen_string_literal: false
-#
-# output-method.rb - output methods used by irb
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- # 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
- class NotImplementedError < StandardError
- def initialize(val)
- super("Need to define `#{val}'")
- end
- end
-
- # 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)
- raise NotImplementedError, "print"
- end
-
- # Prints the given +opts+, with a newline delimiter.
- def printn(*opts)
- print opts.join(" "), "\n"
- end
-
- # 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)
- end
- print sprintf(format, *opts)
- end
-
- # 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)
- print "\n"
- 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
- end
-end
diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb
deleted file mode 100644
index 9e4a7b28fa..0000000000
--- a/lib/irb/ruby-lex.rb
+++ /dev/null
@@ -1,851 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/ruby-lex.rb - ruby lexcal analyzer
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require "ripper"
-require "jruby" if RUBY_ENGINE == "jruby"
-
-# :stopdoc:
-class RubyLex
-
- class TerminateLineInput < StandardError
- def initialize
- super("Terminate Line Input")
- end
- end
-
- def initialize(context)
- @context = context
- @exp_line_no = @line_no = 1
- @indent = 0
- @continue = false
- @line = ""
- @prompt = nil
- end
-
- def self.compile_with_errors_suppressed(code, line_no: 1)
- begin
- result = yield code, line_no
- rescue ArgumentError
- # Ruby can issue an error for the code if there is an
- # incomplete magic comment for encoding in it. Force an
- # expression with a new line before the code in this
- # case to prevent magic comment handling. To make sure
- # line numbers in the lexed code remain the same,
- # decrease the line number by one.
- code = ";\n#{code}"
- line_no -= 1
- result = yield code, line_no
- end
- result
- end
-
- # io functions
- def set_input(io, &block)
- @io = io
- if @io.respond_to?(:check_termination)
- @io.check_termination do |code|
- if Reline::IOGate.in_pasting?
- lex = RubyLex.new(@context)
- rest = lex.check_termination_in_prev_line(code)
- if rest
- Reline.delete_text
- rest.bytes.reverse_each do |c|
- Reline.ungetc(c)
- end
- true
- else
- false
- end
- else
- # Accept any single-line input for symbol aliases or commands that transform args
- command = code.split(/\s/, 2).first
- if @context.symbol_alias?(command) || @context.transform_args?(command)
- next true
- end
-
- code.gsub!(/\s*\z/, '').concat("\n")
- tokens = self.class.ripper_lex_without_warning(code, context: @context)
- ltype, indent, continue, code_block_open = check_state(code, tokens)
- if ltype or indent > 0 or continue or code_block_open
- false
- else
- true
- end
- end
- end
- end
- if @io.respond_to?(:dynamic_prompt)
- @io.dynamic_prompt do |lines|
- lines << '' if lines.empty?
- result = []
- tokens = self.class.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: @context)
- code = String.new
- partial_tokens = []
- unprocessed_tokens = []
- line_num_offset = 0
- tokens.each do |t|
- partial_tokens << t
- unprocessed_tokens << t
- if t.tok.include?("\n")
- t_str = t.tok
- t_str.each_line("\n") do |s|
- code << s
- next unless s.include?("\n")
- ltype, indent, continue, code_block_open = check_state(code, partial_tokens)
- result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
- line_num_offset += 1
- end
- unprocessed_tokens = []
- else
- code << t.tok
- end
- end
-
- unless unprocessed_tokens.empty?
- ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens)
- result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
- end
- result
- end
- end
-
- if block_given?
- @input = block
- else
- @input = Proc.new{@io.gets}
- end
- end
-
- def set_prompt(&block)
- @prompt = block
- end
-
- ERROR_TOKENS = [
- :on_parse_error,
- :compile_error,
- :on_assign_error,
- :on_alias_error,
- :on_class_name_error,
- :on_param_error
- ]
-
- def self.generate_local_variables_assign_code(local_variables)
- "#{local_variables.join('=')}=nil;" unless local_variables.empty?
- end
-
- def self.ripper_lex_without_warning(code, context: nil)
- verbose, $VERBOSE = $VERBOSE, nil
- lvars_code = generate_local_variables_assign_code(context&.local_variables || [])
- if lvars_code
- code = "#{lvars_code}\n#{code}"
- line_no = 0
- else
- line_no = 1
- end
-
- compile_with_errors_suppressed(code, line_no: line_no) do |inner_code, line_no|
- lexer = Ripper::Lexer.new(inner_code, '-', line_no)
- if lexer.respond_to?(:scan) # Ruby 2.7+
- lexer.scan.each_with_object([]) do |t, tokens|
- next if t.pos.first == 0
- prev_tk = tokens.last
- position_overlapped = prev_tk && t.pos[0] == prev_tk.pos[0] && t.pos[1] < prev_tk.pos[1] + prev_tk.tok.bytesize
- if position_overlapped
- tokens[-1] = t if ERROR_TOKENS.include?(prev_tk.event) && !ERROR_TOKENS.include?(t.event)
- else
- tokens << t
- end
- end
- else
- lexer.parse.reject { |it| it.pos.first == 0 }.sort_by(&:pos)
- end
- end
- ensure
- $VERBOSE = verbose
- end
-
- def find_prev_spaces(line_index)
- return 0 if @tokens.size == 0
- md = @tokens[0].tok.match(/(\A +)/)
- prev_spaces = md.nil? ? 0 : md[1].count(' ')
- line_count = 0
- @tokens.each_with_index do |t, i|
- if t.tok.include?("\n")
- line_count += t.tok.count("\n")
- if line_count >= line_index
- return prev_spaces
- end
- next if t.event == :on_tstring_content || t.event == :on_words_sep
- if (@tokens.size - 1) > i
- md = @tokens[i + 1].tok.match(/(\A +)/)
- prev_spaces = md.nil? ? 0 : md[1].count(' ')
- end
- end
- end
- prev_spaces
- end
-
- def set_auto_indent
- if @io.respond_to?(:auto_indent) and @context.auto_indent_mode
- @io.auto_indent do |lines, line_index, byte_pointer, is_newline|
- if is_newline
- @tokens = self.class.ripper_lex_without_warning(lines[0..line_index].join("\n"), context: @context)
- prev_spaces = find_prev_spaces(line_index)
- depth_difference = check_newline_depth_difference
- depth_difference = 0 if depth_difference < 0
- prev_spaces + depth_difference * 2
- else
- code = line_index.zero? ? '' : lines[0..(line_index - 1)].map{ |l| l + "\n" }.join
- last_line = lines[line_index]&.byteslice(0, byte_pointer)
- code += last_line if last_line
- @tokens = self.class.ripper_lex_without_warning(code, context: @context)
- check_corresponding_token_depth(lines, line_index)
- end
- end
- end
- end
-
- def check_state(code, tokens)
- ltype = process_literal_type(tokens)
- indent = process_nesting_level(tokens)
- continue = process_continue(tokens)
- lvars_code = self.class.generate_local_variables_assign_code(@context.local_variables)
- code = "#{lvars_code}\n#{code}" if lvars_code
- code_block_open = check_code_block(code, tokens)
- [ltype, indent, continue, code_block_open]
- end
-
- def prompt
- if @prompt
- @prompt.call(@ltype, @indent, @continue, @line_no)
- end
- end
-
- def initialize_input
- @ltype = nil
- @indent = 0
- @continue = false
- @line = ""
- @exp_line_no = @line_no
- @code_block_open = false
- end
-
- def each_top_level_statement
- initialize_input
- catch(:TERM_INPUT) do
- loop do
- begin
- prompt
- unless l = lex
- throw :TERM_INPUT if @line == ''
- else
- @line_no += l.count("\n")
- if l == "\n"
- @exp_line_no += 1
- next
- end
- @line.concat l
- if @code_block_open or @ltype or @continue or @indent > 0
- next
- end
- end
- if @line != "\n"
- @line.force_encoding(@io.encoding)
- yield @line, @exp_line_no
- end
- raise TerminateLineInput if @io.eof?
- @line = ''
- @exp_line_no = @line_no
-
- @indent = 0
- rescue TerminateLineInput
- initialize_input
- prompt
- end
- end
- end
- end
-
- def lex
- line = @input.call
- if @io.respond_to?(:check_termination)
- return line # multiline
- end
- code = @line + (line.nil? ? '' : line)
- code.gsub!(/\s*\z/, '').concat("\n")
- @tokens = self.class.ripper_lex_without_warning(code, context: @context)
- @ltype, @indent, @continue, @code_block_open = check_state(code, @tokens)
- line
- end
-
- def process_continue(tokens)
- # last token is always newline
- if tokens.size >= 2 and tokens[-2].event == :on_regexp_end
- # end of regexp literal
- return false
- elsif tokens.size >= 2 and tokens[-2].event == :on_semicolon
- return false
- elsif tokens.size >= 2 and tokens[-2].event == :on_kw and ['begin', 'else', 'ensure'].include?(tokens[-2].tok)
- return false
- elsif !tokens.empty? and tokens.last.tok == "\\\n"
- return true
- elsif tokens.size >= 1 and tokens[-1].event == :on_heredoc_end # "EOH\n"
- return false
- elsif tokens.size >= 2 and tokens[-2].state.anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME) and tokens[-2].tok !~ /\A\.\.\.?\z/
- # end of literal except for regexp
- # endless range at end of line is not a continue
- return true
- end
- false
- end
-
- def check_code_block(code, tokens)
- return true if tokens.empty?
- if tokens.last.event == :on_heredoc_beg
- return true
- end
-
- begin # check if parser error are available
- verbose, $VERBOSE = $VERBOSE, nil
- case RUBY_ENGINE
- when 'ruby'
- self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
- RubyVM::InstructionSequence.compile(inner_code, nil, nil, line_no)
- end
- when 'jruby'
- JRuby.compile_ir(code)
- else
- catch(:valid) do
- eval("BEGIN { throw :valid, true }\n#{code}")
- false
- end
- end
- rescue EncodingError
- # This is for a hash with invalid encoding symbol, {"\xAE": 1}
- rescue SyntaxError => e
- case e.message
- when /unterminated (?:string|regexp) meets end of file/
- # "unterminated regexp meets end of file"
- #
- # example:
- # /
- #
- # "unterminated string meets end of file"
- #
- # example:
- # '
- return true
- when /syntax error, unexpected end-of-input/
- # "syntax error, unexpected end-of-input, expecting keyword_end"
- #
- # example:
- # if true
- # hoge
- # if false
- # fuga
- # end
- return true
- when /syntax error, unexpected keyword_end/
- # "syntax error, unexpected keyword_end"
- #
- # example:
- # if (
- # end
- #
- # example:
- # end
- return false
- when /syntax error, unexpected '\.'/
- # "syntax error, unexpected '.'"
- #
- # example:
- # .
- return false
- when /unexpected tREGEXP_BEG/
- # "syntax error, unexpected tREGEXP_BEG, expecting keyword_do or '{' or '('"
- #
- # example:
- # method / f /
- return false
- end
- ensure
- $VERBOSE = verbose
- end
-
- last_lex_state = tokens.last.state
-
- if last_lex_state.allbits?(Ripper::EXPR_BEG)
- return false
- elsif last_lex_state.allbits?(Ripper::EXPR_DOT)
- return true
- elsif last_lex_state.allbits?(Ripper::EXPR_CLASS)
- return true
- elsif last_lex_state.allbits?(Ripper::EXPR_FNAME)
- return true
- elsif last_lex_state.allbits?(Ripper::EXPR_VALUE)
- return true
- elsif last_lex_state.allbits?(Ripper::EXPR_ARG)
- return false
- end
-
- false
- end
-
- def process_nesting_level(tokens)
- indent = 0
- in_oneliner_def = nil
- tokens.each_with_index { |t, index|
- # detecting one-liner method definition
- if in_oneliner_def.nil?
- if t.state.allbits?(Ripper::EXPR_ENDFN)
- in_oneliner_def = :ENDFN
- end
- else
- if t.state.allbits?(Ripper::EXPR_ENDFN)
- # continuing
- elsif t.state.allbits?(Ripper::EXPR_BEG)
- if t.tok == '='
- in_oneliner_def = :BODY
- end
- else
- if in_oneliner_def == :BODY
- # one-liner method definition
- indent -= 1
- end
- in_oneliner_def = nil
- end
- end
-
- case t.event
- when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
- indent += 1
- when :on_rbracket, :on_rbrace, :on_rparen
- indent -= 1
- when :on_kw
- next if index > 0 and tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
- case t.tok
- when 'do'
- syntax_of_do = take_corresponding_syntax_to_kw_do(tokens, index)
- indent += 1 if syntax_of_do == :method_calling
- when 'def', 'case', 'for', 'begin', 'class', 'module'
- indent += 1
- when 'if', 'unless', 'while', 'until'
- # postfix if/unless/while/until must be Ripper::EXPR_LABEL
- indent += 1 unless t.state.allbits?(Ripper::EXPR_LABEL)
- when 'end'
- indent -= 1
- end
- end
- # percent literals are not indented
- }
- indent
- end
-
- def is_method_calling?(tokens, index)
- tk = tokens[index]
- if tk.state.anybits?(Ripper::EXPR_CMDARG) and tk.event == :on_ident
- # The target method call to pass the block with "do".
- return true
- elsif tk.state.anybits?(Ripper::EXPR_ARG) and tk.event == :on_ident
- non_sp_index = tokens[0..(index - 1)].rindex{ |t| t.event != :on_sp }
- if non_sp_index
- prev_tk = tokens[non_sp_index]
- if prev_tk.state.anybits?(Ripper::EXPR_DOT) and prev_tk.event == :on_period
- # The target method call with receiver to pass the block with "do".
- return true
- end
- end
- end
- false
- end
-
- def take_corresponding_syntax_to_kw_do(tokens, index)
- syntax_of_do = nil
- # Finding a syntax corresponding to "do".
- index.downto(0) do |i|
- tk = tokens[i]
- # In "continue", the token isn't the corresponding syntax to "do".
- non_sp_index = tokens[0..(i - 1)].rindex{ |t| t.event != :on_sp }
- first_in_fomula = false
- if non_sp_index.nil?
- first_in_fomula = true
- elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index].event)
- first_in_fomula = true
- end
- if is_method_calling?(tokens, i)
- syntax_of_do = :method_calling
- break if first_in_fomula
- elsif tk.event == :on_kw && %w{while until for}.include?(tk.tok)
- # A loop syntax in front of "do" found.
- #
- # while cond do # also "until" or "for"
- # end
- #
- # This "do" doesn't increment indent because the loop syntax already
- # incremented.
- syntax_of_do = :loop_syntax
- break if first_in_fomula
- end
- end
- syntax_of_do
- end
-
- def is_the_in_correspond_to_a_for(tokens, index)
- syntax_of_in = nil
- # Finding a syntax corresponding to "do".
- index.downto(0) do |i|
- tk = tokens[i]
- # In "continue", the token isn't the corresponding syntax to "do".
- non_sp_index = tokens[0..(i - 1)].rindex{ |t| t.event != :on_sp }
- first_in_fomula = false
- if non_sp_index.nil?
- first_in_fomula = true
- elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index].event)
- first_in_fomula = true
- end
- if tk.event == :on_kw && tk.tok == 'for'
- # A loop syntax in front of "do" found.
- #
- # while cond do # also "until" or "for"
- # end
- #
- # This "do" doesn't increment indent because the loop syntax already
- # incremented.
- syntax_of_in = :for
- end
- break if first_in_fomula
- end
- syntax_of_in
- end
-
- def check_newline_depth_difference
- depth_difference = 0
- open_brace_on_line = 0
- in_oneliner_def = nil
- @tokens.each_with_index do |t, index|
- # detecting one-liner method definition
- if in_oneliner_def.nil?
- if t.state.allbits?(Ripper::EXPR_ENDFN)
- in_oneliner_def = :ENDFN
- end
- else
- if t.state.allbits?(Ripper::EXPR_ENDFN)
- # continuing
- elsif t.state.allbits?(Ripper::EXPR_BEG)
- if t.tok == '='
- in_oneliner_def = :BODY
- end
- else
- if in_oneliner_def == :BODY
- # one-liner method definition
- depth_difference -= 1
- end
- in_oneliner_def = nil
- end
- end
-
- case t.event
- when :on_ignored_nl, :on_nl, :on_comment
- if index != (@tokens.size - 1) and in_oneliner_def != :BODY
- depth_difference = 0
- open_brace_on_line = 0
- end
- next
- when :on_sp
- next
- end
-
- case t.event
- when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
- depth_difference += 1
- open_brace_on_line += 1
- when :on_rbracket, :on_rbrace, :on_rparen
- depth_difference -= 1 if open_brace_on_line > 0
- when :on_kw
- next if index > 0 and @tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
- case t.tok
- when 'do'
- syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
- depth_difference += 1 if syntax_of_do == :method_calling
- when 'def', 'case', 'for', 'begin', 'class', 'module'
- depth_difference += 1
- when 'if', 'unless', 'while', 'until', 'rescue'
- # postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
- unless t.state.allbits?(Ripper::EXPR_LABEL)
- depth_difference += 1
- end
- when 'else', 'elsif', 'ensure', 'when'
- depth_difference += 1
- when 'in'
- unless is_the_in_correspond_to_a_for(@tokens, index)
- depth_difference += 1
- end
- when 'end'
- depth_difference -= 1
- end
- end
- end
- depth_difference
- end
-
- def check_corresponding_token_depth(lines, line_index)
- corresponding_token_depth = nil
- is_first_spaces_of_line = true
- is_first_printable_of_line = true
- spaces_of_nest = []
- spaces_at_line_head = 0
- open_brace_on_line = 0
- in_oneliner_def = nil
-
- if heredoc_scope?
- return lines[line_index][/^ */].length
- end
-
- @tokens.each_with_index do |t, index|
- # detecting one-liner method definition
- if in_oneliner_def.nil?
- if t.state.allbits?(Ripper::EXPR_ENDFN)
- in_oneliner_def = :ENDFN
- end
- else
- if t.state.allbits?(Ripper::EXPR_ENDFN)
- # continuing
- elsif t.state.allbits?(Ripper::EXPR_BEG)
- if t.tok == '='
- in_oneliner_def = :BODY
- end
- else
- if in_oneliner_def == :BODY
- # one-liner method definition
- if is_first_printable_of_line
- corresponding_token_depth = spaces_of_nest.pop
- else
- spaces_of_nest.pop
- corresponding_token_depth = nil
- end
- end
- in_oneliner_def = nil
- end
- end
-
- case t.event
- when :on_ignored_nl, :on_nl, :on_comment, :on_heredoc_end, :on_embdoc_end
- if in_oneliner_def != :BODY
- corresponding_token_depth = nil
- spaces_at_line_head = 0
- is_first_spaces_of_line = true
- is_first_printable_of_line = true
- open_brace_on_line = 0
- end
- next
- when :on_sp
- spaces_at_line_head = t.tok.count(' ') if is_first_spaces_of_line
- is_first_spaces_of_line = false
- next
- end
-
- case t.event
- when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
- spaces_of_nest.push(spaces_at_line_head + open_brace_on_line * 2)
- open_brace_on_line += 1
- when :on_rbracket, :on_rbrace, :on_rparen
- if is_first_printable_of_line
- corresponding_token_depth = spaces_of_nest.pop
- else
- spaces_of_nest.pop
- corresponding_token_depth = nil
- end
- open_brace_on_line -= 1
- when :on_kw
- next if index > 0 and @tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
- case t.tok
- when 'do'
- syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
- if syntax_of_do == :method_calling
- spaces_of_nest.push(spaces_at_line_head)
- end
- when 'def', 'case', 'for', 'begin', 'class', 'module'
- spaces_of_nest.push(spaces_at_line_head)
- when 'rescue'
- unless t.state.allbits?(Ripper::EXPR_LABEL)
- corresponding_token_depth = spaces_of_nest.last
- end
- when 'if', 'unless', 'while', 'until'
- # postfix if/unless/while/until must be Ripper::EXPR_LABEL
- unless t.state.allbits?(Ripper::EXPR_LABEL)
- spaces_of_nest.push(spaces_at_line_head)
- end
- when 'else', 'elsif', 'ensure', 'when'
- corresponding_token_depth = spaces_of_nest.last
- when 'in'
- if in_keyword_case_scope?
- corresponding_token_depth = spaces_of_nest.last
- end
- when 'end'
- if is_first_printable_of_line
- corresponding_token_depth = spaces_of_nest.pop
- else
- spaces_of_nest.pop
- corresponding_token_depth = nil
- end
- end
- end
- is_first_spaces_of_line = false
- is_first_printable_of_line = false
- end
- corresponding_token_depth
- end
-
- def check_string_literal(tokens)
- i = 0
- start_token = []
- end_type = []
- pending_heredocs = []
- while i < tokens.size
- t = tokens[i]
- case t.event
- when *end_type.last
- start_token.pop
- end_type.pop
- when :on_tstring_beg
- start_token << t
- end_type << [:on_tstring_end, :on_label_end]
- when :on_regexp_beg
- start_token << t
- end_type << :on_regexp_end
- when :on_symbeg
- acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw on_int on_backtick}
- if (i + 1) < tokens.size
- if acceptable_single_tokens.all?{ |st| tokens[i + 1].event != st }
- start_token << t
- end_type << :on_tstring_end
- else
- i += 1
- end
- end
- when :on_backtick
- if t.state.allbits?(Ripper::EXPR_BEG)
- start_token << t
- end_type << :on_tstring_end
- end
- when :on_qwords_beg, :on_words_beg, :on_qsymbols_beg, :on_symbols_beg
- start_token << t
- end_type << :on_tstring_end
- when :on_heredoc_beg
- pending_heredocs << t
- end
-
- if pending_heredocs.any? && t.tok.include?("\n")
- pending_heredocs.reverse_each do |t|
- start_token << t
- end_type << :on_heredoc_end
- end
- pending_heredocs = []
- end
- i += 1
- end
- pending_heredocs.first || start_token.last
- end
-
- def process_literal_type(tokens)
- start_token = check_string_literal(tokens)
- return nil if start_token == ""
-
- case start_token&.event
- when :on_tstring_beg
- case start_token&.tok
- when ?" then ?"
- when /^%.$/ then ?"
- when /^%Q.$/ then ?"
- when ?' then ?'
- when /^%q.$/ then ?'
- end
- when :on_regexp_beg then ?/
- when :on_symbeg then ?:
- when :on_backtick then ?`
- when :on_qwords_beg then ?]
- when :on_words_beg then ?]
- when :on_qsymbols_beg then ?]
- when :on_symbols_beg then ?]
- when :on_heredoc_beg
- start_token&.tok =~ /<<[-~]?(['"`])\w+\1/
- $1 || ?"
- else
- nil
- end
- end
-
- def check_termination_in_prev_line(code)
- tokens = self.class.ripper_lex_without_warning(code, context: @context)
- past_first_newline = false
- index = tokens.rindex do |t|
- # traverse first token before last line
- if past_first_newline
- if t.tok.include?("\n")
- true
- end
- elsif t.tok.include?("\n")
- past_first_newline = true
- false
- else
- false
- end
- end
-
- if index
- first_token = nil
- last_line_tokens = tokens[(index + 1)..(tokens.size - 1)]
- last_line_tokens.each do |t|
- unless [:on_sp, :on_ignored_sp, :on_comment].include?(t.event)
- first_token = t
- break
- end
- end
-
- if first_token.nil?
- return false
- elsif first_token && first_token.state == Ripper::EXPR_DOT
- return false
- else
- tokens_without_last_line = tokens[0..index]
- ltype = process_literal_type(tokens_without_last_line)
- indent = process_nesting_level(tokens_without_last_line)
- continue = process_continue(tokens_without_last_line)
- code_block_open = check_code_block(tokens_without_last_line.map(&:tok).join(''), tokens_without_last_line)
- if ltype or indent > 0 or continue or code_block_open
- return false
- else
- return last_line_tokens.map(&:tok).join('')
- end
- end
- end
- false
- end
-
- private
-
- def heredoc_scope?
- heredoc_tokens = @tokens.select { |t| [:on_heredoc_beg, :on_heredoc_end].include?(t.event) }
- heredoc_tokens[-1]&.event == :on_heredoc_beg
- end
-
- def in_keyword_case_scope?
- kw_tokens = @tokens.select { |t| t.event == :on_kw && ['case', 'for', 'end'].include?(t.tok) }
- counter = 0
- kw_tokens.reverse.each do |t|
- if t.tok == 'case'
- return true if counter.zero?
- counter += 1
- elsif t.tok == 'for'
- counter += 1
- elsif t.tok == 'end'
- counter -= 1
- end
- end
- false
- end
-end
-# :startdoc:
diff --git a/lib/irb/ruby_logo.aa b/lib/irb/ruby_logo.aa
deleted file mode 100644
index a34a3e2f28..0000000000
--- a/lib/irb/ruby_logo.aa
+++ /dev/null
@@ -1,37 +0,0 @@
-
- -+smJYYN?mm-
- HB"BBYT TQg NggT
- 9Q+g Nm,T 8g NJW
- YS+ N2NJ"Sg N?
- BQg #( gT Nggggk J
- 5j NJ NJ NNge
- #Q #JJ NgT N(
- @j bj mT J
- Bj @/d NJ (
- #q #(( NgT #J
- 5d #(t mT $d
- #q @(@J NJB;
- @( 5d ? HHH H HQmgggggggmN qD
- 5d #uN 2QdH E O
- 5 5JSd Nd NJH @d j
- Fd @J4d s NQH #d (
- #( #o6d Nd NgH #d #d
- 4 B&Od v NgT #d F
- #( 9JGd NH NgUd F
- #d #GJQ d NP $
- #J #U+#Q N Q # j
- j /W BQ+ BQ d NJ NJ
- - NjJH HBIjTQggPJQgW N W k #J
- #J b HYWgggN j s Nag d NN b #d
- #J 5- D s Ngg N d Nd F
- Fd BKH2 #+ s NNgg J Q J ]
- F H @ J N y K(d P I
- F4 E N? #d y #Q NJ E j
- F W Nd q m Bg NxW N(H-
- F d b @ m Hd gW vKJ
- NJ d K d s Bg aT FDd
- b # d N m BQ mV N>
- e5 Nd #d NggggggQWH HHHH NJ -
- m7 NW H N HSVO1z=?11-
- NgTH bB kH WBHWWHBHWmQgg&gggggNNN
- NNggggggNN
diff --git a/lib/irb/src_encoding.rb b/lib/irb/src_encoding.rb
deleted file mode 100644
index 99aea2b43e..0000000000
--- a/lib/irb/src_encoding.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: false
-# DO NOT WRITE ANY MAGIC COMMENT HERE.
-module IRB
- def self.default_src_encoding
- return __ENCODING__
- end
-end
diff --git a/lib/irb/version.rb b/lib/irb/version.rb
deleted file mode 100644
index 33b423ea18..0000000000
--- a/lib/irb/version.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/version.rb - irb version definition file
-# by Keiju ISHITSUKA(keiju@ishitsuka.com)
-#
-
-module IRB # :nodoc:
- VERSION = "1.6.2"
- @RELEASE_VERSION = VERSION
- @LAST_UPDATE_DATE = "2022-12-13"
-end
diff --git a/lib/irb/workspace.rb b/lib/irb/workspace.rb
deleted file mode 100644
index 5f990940e8..0000000000
--- a/lib/irb/workspace.rb
+++ /dev/null
@@ -1,167 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/workspace-binding.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require "delegate"
-
-IRB::TOPLEVEL_BINDING = binding
-module IRB # :nodoc:
- class WorkSpace
- # Creates a new workspace.
- #
- # set self to main if specified, otherwise
- # inherit main from TOPLEVEL_BINDING.
- def initialize(*main)
- if main[0].kind_of?(Binding)
- @binding = main.shift
- elsif IRB.conf[:SINGLE_IRB]
- @binding = TOPLEVEL_BINDING
- else
- case IRB.conf[:CONTEXT_MODE]
- when 0 # binding in proc on TOPLEVEL_BINDING
- @binding = eval("proc{binding}.call",
- TOPLEVEL_BINDING,
- __FILE__,
- __LINE__)
- when 1 # binding in loaded file
- require "tempfile"
- f = Tempfile.open("irb-binding")
- f.print <<EOF
- $binding = binding
-EOF
- f.close
- load f.path
- @binding = $binding
-
- when 2 # binding in loaded file(thread use)
- unless defined? BINDING_QUEUE
- IRB.const_set(:BINDING_QUEUE, Thread::SizedQueue.new(1))
- Thread.abort_on_exception = true
- Thread.start do
- eval "require \"irb/ws-for-case-2\"", TOPLEVEL_BINDING, __FILE__, __LINE__
- end
- Thread.pass
- end
- @binding = BINDING_QUEUE.pop
-
- when 3 # binding in function on TOPLEVEL_BINDING
- @binding = eval("self.class.remove_method(:irb_binding) if defined?(irb_binding); private; def irb_binding; binding; end; irb_binding",
- TOPLEVEL_BINDING,
- __FILE__,
- __LINE__ - 3)
- when 4 # binding is a copy of TOPLEVEL_BINDING (default)
- # Note that this will typically be IRB::TOPLEVEL_BINDING
- # This is to avoid RubyGems' local variables (see issue #17623)
- @binding = TOPLEVEL_BINDING.dup
- end
- end
-
- if main.empty?
- @main = eval("self", @binding)
- else
- @main = main[0]
- end
- IRB.conf[:__MAIN__] = @main
-
- unless main.empty?
- case @main
- when Module
- @binding = eval("IRB.conf[:__MAIN__].module_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
- else
- begin
- @binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
- rescue TypeError
- fail CantChangeBinding, @main.inspect
- end
- end
- end
-
- case @main
- when Object
- use_delegator = @main.frozen?
- else
- use_delegator = true
- end
-
- if use_delegator
- @main = SimpleDelegator.new(@main)
- IRB.conf[:__MAIN__] = @main
- @main.singleton_class.class_eval do
- private
- define_method(:exit) do |*a, &b|
- # Do nothing, will be overridden
- end
- define_method(:binding, Kernel.instance_method(:binding))
- define_method(:local_variables, Kernel.instance_method(:local_variables))
- end
- @binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, *@binding.source_location)
- end
-
- @binding.local_variable_set(:_, nil)
- 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
-
- def local_variable_set(name, value)
- @binding.local_variable_set(name, value)
- end
-
- def local_variable_get(name)
- @binding.local_variable_get(name)
- end
-
- # error message manipulator
- def filter_backtrace(bt)
- return nil if bt =~ /\/irb\/.*\.rb/
- return nil if bt =~ /\/irb\.rb/
- return nil if bt =~ /tool\/lib\/.*\.rb|runner\.rb/ # for tests in Ruby repository
- case IRB.conf[:CONTEXT_MODE]
- when 1
- return nil if bt =~ %r!/tmp/irb-binding!
- when 3
- bt = bt.sub(/:\s*in `irb_binding'/, '')
- end
- bt
- end
-
- def code_around_binding
- file, pos = @binding.source_location
-
- if defined?(::SCRIPT_LINES__[file]) && lines = ::SCRIPT_LINES__[file]
- code = ::SCRIPT_LINES__[file].join('')
- else
- begin
- code = File.read(file)
- rescue SystemCallError
- return
- end
- end
-
- lines = Color.colorize_code(code).lines
- pos -= 1
-
- start_pos = [pos - 5, 0].max
- end_pos = [pos + 5, lines.size - 1].min
-
- line_number_fmt = Color.colorize("%#{end_pos.to_s.length}d", [:BLUE, :BOLD])
- fmt = " %2s #{line_number_fmt}: %s"
-
- body = (start_pos..end_pos).map do |current_pos|
- sprintf(fmt, pos == current_pos ? '=>' : '', current_pos + 1, lines[current_pos])
- end.join("")
-
- "\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear}\n"
- end
- end
-end
diff --git a/lib/irb/ws-for-case-2.rb b/lib/irb/ws-for-case-2.rb
deleted file mode 100644
index a0f617e4ed..0000000000
--- a/lib/irb/ws-for-case-2.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/ws-for-case-2.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-while true
- IRB::BINDING_QUEUE.push _ = binding
-end
diff --git a/lib/irb/xmp.rb b/lib/irb/xmp.rb
deleted file mode 100644
index 94c700b484..0000000000
--- a/lib/irb/xmp.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-# frozen_string_literal: false
-#
-# xmp.rb - irb version of gotoken xmp
-# by Keiju ISHITSUKA(Nippon Rational Inc.)
-#
-
-require_relative "../irb"
-require_relative "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
-
- # 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.conf[:PROMPT_MODE] = :XMP
-
- bind = IRB::Frame.top(1) unless bind
- ws = IRB::WorkSpace.new(bind)
- @io = StringInputMethod.new
- @irb = IRB::Irb.new(ws, @io)
- @irb.context.ignore_sigint = false
-
- 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
-
- if @irb.context.ignore_sigint
- begin
- trap_proc_b = trap("SIGINT"){@irb.signal_handle}
- catch(:IRB_EXIT) do
- @irb.eval_input
- end
- ensure
- trap("SIGINT", trap_proc_b)
- end
- else
- catch(:IRB_EXIT) do
- @irb.eval_input
- end
- 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
- l.concat "\n"
- print @prompt, l
- break
- end
- 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)
- if enc.nil?
- raise Encoding::CompatibilityError, "Encoding in which the passed expression is encoded is not compatible to the preceding's one"
- else
- @encoding = enc
- end
- else
- @encoding = exps.encoding
- end
- @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)
- xmp.puts exps
- xmp
-end