mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Merge IRB 1.2.6
This commit is contained in:
parent
3bb503e0e8
commit
2159798f4c
29 changed files with 912 additions and 105 deletions
58
lib/irb.rb
58
lib/irb.rb
|
|
@ -10,18 +10,19 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
require "ripper"
|
require "ripper"
|
||||||
|
require "reline"
|
||||||
|
|
||||||
require "irb/init"
|
require_relative "irb/init"
|
||||||
require "irb/context"
|
require_relative "irb/context"
|
||||||
require "irb/extend-command"
|
require_relative "irb/extend-command"
|
||||||
|
|
||||||
require "irb/ruby-lex"
|
require_relative "irb/ruby-lex"
|
||||||
require "irb/input-method"
|
require_relative "irb/input-method"
|
||||||
require "irb/locale"
|
require_relative "irb/locale"
|
||||||
require "irb/color"
|
require_relative "irb/color"
|
||||||
|
|
||||||
require "irb/version"
|
require_relative "irb/version"
|
||||||
require "irb/easter-egg"
|
require_relative "irb/easter-egg"
|
||||||
|
|
||||||
# IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby
|
# IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby
|
||||||
# expressions read from the standard input.
|
# expressions read from the standard input.
|
||||||
|
|
@ -271,7 +272,7 @@ require "irb/easter-egg"
|
||||||
# On the other hand, each conf in IRB@Command+line+options is used to
|
# On the other hand, each conf in IRB@Command+line+options is used to
|
||||||
# individually configure IRB.irb.
|
# individually configure IRB.irb.
|
||||||
#
|
#
|
||||||
# If a proc is set for IRB.conf[:IRB_RC], its will be invoked after execution
|
# If a proc is set for <code>IRB.conf[:IRB_RC]</code>, its will be invoked after execution
|
||||||
# of that proc with the context of the current session as its argument. Each
|
# of that proc with the context of the current session as its argument. Each
|
||||||
# session can be configured using this mechanism.
|
# session can be configured using this mechanism.
|
||||||
#
|
#
|
||||||
|
|
@ -399,7 +400,7 @@ module IRB
|
||||||
irb.run(@CONF)
|
irb.run(@CONF)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Calls each event hook of IRB.conf[:AT_EXIT] when the current session quits.
|
# Calls each event hook of <code>IRB.conf[:TA_EXIT]</code> when the current session quits.
|
||||||
def IRB.irb_at_exit
|
def IRB.irb_at_exit
|
||||||
@CONF[:AT_EXIT].each{|hook| hook.call}
|
@CONF[:AT_EXIT].each{|hook| hook.call}
|
||||||
end
|
end
|
||||||
|
|
@ -538,7 +539,15 @@ module IRB
|
||||||
begin
|
begin
|
||||||
line.untaint if RUBY_VERSION < '2.7'
|
line.untaint if RUBY_VERSION < '2.7'
|
||||||
@context.evaluate(line, line_no, exception: exc)
|
@context.evaluate(line, line_no, exception: exc)
|
||||||
output_value if @context.echo? && (@context.echo_on_assignment? || !assignment_expression?(line))
|
if @context.echo?
|
||||||
|
if assignment_expression?(line)
|
||||||
|
if @context.echo_on_assignment?
|
||||||
|
output_value(@context.omit_on_assignment?)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
output_value
|
||||||
|
end
|
||||||
|
end
|
||||||
rescue Interrupt => exc
|
rescue Interrupt => exc
|
||||||
rescue SystemExit, SignalException
|
rescue SystemExit, SignalException
|
||||||
raise
|
raise
|
||||||
|
|
@ -737,9 +746,32 @@ module IRB
|
||||||
p
|
p
|
||||||
end
|
end
|
||||||
|
|
||||||
def output_value # :nodoc:
|
def output_value(omit = false) # :nodoc:
|
||||||
str = @context.inspect_last_value
|
str = @context.inspect_last_value
|
||||||
multiline_p = str.include?("\n")
|
multiline_p = str.include?("\n")
|
||||||
|
if omit
|
||||||
|
winwidth = @context.io.winsize.last
|
||||||
|
if multiline_p
|
||||||
|
first_line = str.split("\n").first
|
||||||
|
result = @context.newline_before_multiline_output? ? (@context.return_format % first_line) : first_line
|
||||||
|
output_width = Reline::Unicode.calculate_width(result, true)
|
||||||
|
diff_size = output_width - Reline::Unicode.calculate_width(first_line, true)
|
||||||
|
if diff_size.positive? and output_width > winwidth
|
||||||
|
lines, _ = Reline::Unicode.split_by_width(first_line, winwidth - diff_size - 3)
|
||||||
|
str = "%s...\e[0m" % lines.first
|
||||||
|
multiline_p = false
|
||||||
|
else
|
||||||
|
str.gsub!(/(\A.*?\n).*/m, "\\1...")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
output_width = Reline::Unicode.calculate_width(@context.return_format % str, true)
|
||||||
|
diff_size = output_width - Reline::Unicode.calculate_width(str, true)
|
||||||
|
if diff_size.positive? and output_width > winwidth
|
||||||
|
lines, _ = Reline::Unicode.split_by_width(str, winwidth - diff_size - 3)
|
||||||
|
str = "%s...\e[0m" % lines.first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
if multiline_p && @context.newline_before_multiline_output?
|
if multiline_p && @context.newline_before_multiline_output?
|
||||||
printf @context.return_format, "\n#{str}"
|
printf @context.return_format, "\n#{str}"
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -35,5 +35,3 @@ module IRB
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# :startdoc:
|
# :startdoc:
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
24
lib/irb/cmd/info.rb
Normal file
24
lib/irb/cmd/info.rb
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
# frozen_string_literal: false
|
||||||
|
|
||||||
|
require_relative "nop"
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
|
module IRB
|
||||||
|
module ExtendCommand
|
||||||
|
class Info < Nop
|
||||||
|
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
|
||||||
|
end
|
||||||
|
alias_method :to_s, :inspect
|
||||||
|
}.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# :startdoc:
|
||||||
|
|
@ -38,4 +38,3 @@ module IRB
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# :startdoc:
|
# :startdoc:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
require 'reline'
|
require 'reline'
|
||||||
require 'ripper'
|
require 'ripper'
|
||||||
|
require 'irb/ruby-lex'
|
||||||
|
|
||||||
module IRB # :nodoc:
|
module IRB # :nodoc:
|
||||||
module Color
|
module Color
|
||||||
|
|
@ -145,37 +146,38 @@ module IRB # :nodoc:
|
||||||
seen.delete(obj)
|
seen.delete(obj)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Ripper::Lexer::Elem#state is supported on Ruby 2.5+
|
|
||||||
def supported?
|
def supported?
|
||||||
return @supported if defined?(@supported)
|
return @supported if defined?(@supported)
|
||||||
@supported = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
|
@supported = Ripper::Lexer::Elem.method_defined?(:state)
|
||||||
end
|
end
|
||||||
|
|
||||||
def scan(code, allow_last_error:)
|
def scan(code, allow_last_error:)
|
||||||
pos = [1, 0]
|
pos = [1, 0]
|
||||||
|
|
||||||
verbose, $VERBOSE = $VERBOSE, nil
|
verbose, $VERBOSE = $VERBOSE, nil
|
||||||
lexer = Ripper::Lexer.new(code)
|
RubyLex.compile_with_errors_suppressed(code) do |inner_code, line_no|
|
||||||
if lexer.respond_to?(:scan) # Ruby 2.7+
|
lexer = Ripper::Lexer.new(inner_code, '(ripper)', line_no)
|
||||||
lexer.scan.each do |elem|
|
if lexer.respond_to?(:scan) # Ruby 2.7+
|
||||||
str = elem.tok
|
lexer.scan.each do |elem|
|
||||||
next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message
|
str = elem.tok
|
||||||
next if ([elem.pos[0], elem.pos[1] + str.bytesize] <=> pos) <= 0
|
next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message
|
||||||
|
next if ([elem.pos[0], elem.pos[1] + str.bytesize] <=> pos) <= 0
|
||||||
|
|
||||||
str.each_line do |line|
|
str.each_line do |line|
|
||||||
if line.end_with?("\n")
|
if line.end_with?("\n")
|
||||||
pos[0] += 1
|
pos[0] += 1
|
||||||
pos[1] = 0
|
pos[1] = 0
|
||||||
else
|
else
|
||||||
pos[1] += line.bytesize
|
pos[1] += line.bytesize
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
yield(elem.event, str, elem.state)
|
yield(elem.event, str, elem.state)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
lexer.parse.each do |elem|
|
lexer.parse.each do |elem|
|
||||||
yield(elem.event, elem.tok, elem.state)
|
yield(elem.event, elem.tok, elem.state)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
$VERBOSE = verbose
|
$VERBOSE = verbose
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
# From Original Idea of shugo@ruby-lang.org
|
# From Original Idea of shugo@ruby-lang.org
|
||||||
#
|
#
|
||||||
|
|
||||||
require "readline"
|
|
||||||
autoload :RDoc, "rdoc"
|
autoload :RDoc, "rdoc"
|
||||||
|
|
||||||
module IRB
|
module IRB
|
||||||
|
|
@ -97,17 +96,13 @@ module IRB
|
||||||
when /^(:[^:.]*)$/
|
when /^(:[^:.]*)$/
|
||||||
# Symbol
|
# Symbol
|
||||||
return nil if doc_namespace
|
return nil if doc_namespace
|
||||||
if Symbol.respond_to?(:all_symbols)
|
sym = $1
|
||||||
sym = $1
|
candidates = Symbol.all_symbols.collect do |s|
|
||||||
candidates = Symbol.all_symbols.collect do |s|
|
":" + s.id2name.encode(Encoding.default_external)
|
||||||
":" + s.id2name.encode(Encoding.default_external)
|
rescue Encoding::UndefinedConversionError
|
||||||
rescue Encoding::UndefinedConversionError
|
# ignore
|
||||||
# ignore
|
|
||||||
end
|
|
||||||
candidates.grep(/^#{Regexp.quote(sym)}/)
|
|
||||||
else
|
|
||||||
[]
|
|
||||||
end
|
end
|
||||||
|
candidates.grep(/^#{Regexp.quote(sym)}/)
|
||||||
|
|
||||||
when /^::([A-Z][^:\.\(]*)$/
|
when /^::([A-Z][^:\.\(]*)$/
|
||||||
# Absolute Constant or class methods
|
# Absolute Constant or class methods
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,12 @@ module IRB
|
||||||
|
|
||||||
@echo_on_assignment = IRB.conf[:ECHO_ON_ASSIGNMENT]
|
@echo_on_assignment = IRB.conf[:ECHO_ON_ASSIGNMENT]
|
||||||
if @echo_on_assignment.nil?
|
if @echo_on_assignment.nil?
|
||||||
@echo_on_assignment = false
|
@echo_on_assignment = true
|
||||||
|
end
|
||||||
|
|
||||||
|
@omit_on_assignment = IRB.conf[:OMIT_ON_ASSIGNMENT]
|
||||||
|
if @omit_on_assignment.nil?
|
||||||
|
@omit_on_assignment = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@newline_before_multiline_output = IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]
|
@newline_before_multiline_output = IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]
|
||||||
|
|
@ -240,7 +245,7 @@ module IRB
|
||||||
attr_accessor :ignore_eof
|
attr_accessor :ignore_eof
|
||||||
# Whether to echo the return value to output or not.
|
# Whether to echo the return value to output or not.
|
||||||
#
|
#
|
||||||
# Uses IRB.conf[:ECHO] if available, or defaults to +true+.
|
# Uses <code>IRB.conf[:ECHO]</code> if available, or defaults to +true+.
|
||||||
#
|
#
|
||||||
# puts "hello"
|
# puts "hello"
|
||||||
# # hello
|
# # hello
|
||||||
|
|
@ -251,16 +256,30 @@ module IRB
|
||||||
attr_accessor :echo
|
attr_accessor :echo
|
||||||
# Whether to echo for assignment expressions
|
# Whether to echo for assignment expressions
|
||||||
#
|
#
|
||||||
# Uses IRB.conf[:ECHO_ON_ASSIGNMENT] if available, or defaults to +false+.
|
# Uses <code>IRB.conf[:ECHO_ON_ASSIGNMENT]</code> if available, or defaults to +true+.
|
||||||
#
|
#
|
||||||
# a = "omg"
|
# a = "omg"
|
||||||
# IRB.CurrentContext.echo_on_assignment = true
|
|
||||||
# a = "omg"
|
|
||||||
# #=> omg
|
# #=> omg
|
||||||
|
# IRB.CurrentContext.echo_on_assignment = false
|
||||||
|
# a = "omg"
|
||||||
attr_accessor :echo_on_assignment
|
attr_accessor :echo_on_assignment
|
||||||
|
# Whether to omit echo for assignment expressions
|
||||||
|
#
|
||||||
|
# Uses <code>IRB.conf[:OMIT_ON_ASSIGNMENT]</code> if available, or defaults to +true+.
|
||||||
|
#
|
||||||
|
# a = [1] * 10
|
||||||
|
# #=> [1, 1, 1, 1, 1, 1, 1, 1, ...
|
||||||
|
# [1] * 10
|
||||||
|
# #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||||
|
# IRB.CurrentContext.omit_on_assignment = false
|
||||||
|
# a = [1] * 10
|
||||||
|
# #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||||
|
# [1] * 10
|
||||||
|
# #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||||
|
attr_accessor :omit_on_assignment
|
||||||
# Whether a newline is put before multiline output.
|
# Whether a newline is put before multiline output.
|
||||||
#
|
#
|
||||||
# Uses IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT] if available,
|
# Uses <code>IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]</code> if available,
|
||||||
# or defaults to +true+.
|
# or defaults to +true+.
|
||||||
#
|
#
|
||||||
# "abc\ndef"
|
# "abc\ndef"
|
||||||
|
|
@ -306,6 +325,7 @@ module IRB
|
||||||
alias ignore_eof? ignore_eof
|
alias ignore_eof? ignore_eof
|
||||||
alias echo? echo
|
alias echo? echo
|
||||||
alias echo_on_assignment? echo_on_assignment
|
alias echo_on_assignment? echo_on_assignment
|
||||||
|
alias omit_on_assignment? omit_on_assignment
|
||||||
alias newline_before_multiline_output? newline_before_multiline_output
|
alias newline_before_multiline_output? newline_before_multiline_output
|
||||||
|
|
||||||
# Returns whether messages are displayed or not.
|
# Returns whether messages are displayed or not.
|
||||||
|
|
|
||||||
|
|
@ -43,4 +43,3 @@ module IRB # :nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -153,5 +153,3 @@ module IRB # :nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -126,4 +126,3 @@ module IRB # :nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
require "readline"
|
|
||||||
|
|
||||||
module IRB
|
module IRB
|
||||||
module HistorySavingAbility # :nodoc:
|
module HistorySavingAbility # :nodoc:
|
||||||
end
|
end
|
||||||
|
|
@ -27,7 +25,7 @@ module IRB
|
||||||
IRB.conf[:SAVE_HISTORY]
|
IRB.conf[:SAVE_HISTORY]
|
||||||
end
|
end
|
||||||
|
|
||||||
remove_method :save_history= if method_defined?(:save_history=)
|
remove_method(:save_history=) if method_defined?(:save_history=)
|
||||||
# Sets <code>IRB.conf[:SAVE_HISTORY]</code> to the given +val+ and calls
|
# Sets <code>IRB.conf[:SAVE_HISTORY]</code> to the given +val+ and calls
|
||||||
# #init_save_history with this context.
|
# #init_save_history with this context.
|
||||||
#
|
#
|
||||||
|
|
@ -89,7 +87,7 @@ module IRB
|
||||||
def save_history
|
def save_history
|
||||||
return unless self.class.const_defined?(:HISTORY)
|
return unless self.class.const_defined?(:HISTORY)
|
||||||
history = self.class::HISTORY
|
history = self.class::HISTORY
|
||||||
if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) > 0
|
if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) != 0
|
||||||
if history_file = IRB.conf[:HISTORY_FILE]
|
if history_file = IRB.conf[:HISTORY_FILE]
|
||||||
history_file = File.expand_path(history_file)
|
history_file = File.expand_path(history_file)
|
||||||
end
|
end
|
||||||
|
|
@ -109,7 +107,12 @@ module IRB
|
||||||
|
|
||||||
open(history_file, "w:#{IRB.conf[:LC_MESSAGES].encoding}", 0600) do |f|
|
open(history_file, "w:#{IRB.conf[:LC_MESSAGES].encoding}", 0600) do |f|
|
||||||
hist = history.map{ |l| l.split("\n").join("\\\n") }
|
hist = history.map{ |l| l.split("\n").join("\\\n") }
|
||||||
f.puts(hist[-num..-1] || hist)
|
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
|
||||||
|
f.puts(hist)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -82,4 +82,3 @@ module IRB
|
||||||
|
|
||||||
IRB.initialize_tracer
|
IRB.initialize_tracer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ module IRB
|
||||||
alias use_loader? use_loader
|
alias use_loader? use_loader
|
||||||
|
|
||||||
remove_method :use_loader= if method_defined?(:use_loader=)
|
remove_method :use_loader= if method_defined?(:use_loader=)
|
||||||
# Sets IRB.conf[:USE_LOADER]
|
# Sets <code>IRB.conf[:USE_LOADER]</code>
|
||||||
#
|
#
|
||||||
# See #use_loader for more information.
|
# See #use_loader for more information.
|
||||||
def use_loader=(opt)
|
def use_loader=(opt)
|
||||||
|
|
@ -73,5 +73,3 @@ module IRB
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,4 +64,3 @@ module IRB # :nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,10 @@ module IRB # :nodoc:
|
||||||
[:help, NO_OVERRIDE],
|
[:help, NO_OVERRIDE],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
[
|
||||||
|
:irb_info, :Info, "irb/cmd/info"
|
||||||
|
],
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Installs the default irb commands:
|
# Installs the default irb commands:
|
||||||
|
|
@ -169,11 +173,14 @@ module IRB # :nodoc:
|
||||||
args << "&block"
|
args << "&block"
|
||||||
args = args.join(", ")
|
args = args.join(", ")
|
||||||
line = __LINE__; eval %[
|
line = __LINE__; eval %[
|
||||||
def #{cmd_name}(\#{args})
|
unless self.class.class_variable_defined?(:@@#{cmd_name}_)
|
||||||
ExtendCommand::#{cmd_class}.execute(irb_context, \#{args})
|
self.class.class_variable_set(:@@#{cmd_name}_, true)
|
||||||
|
def #{cmd_name}_(\#{args})
|
||||||
|
ExtendCommand::#{cmd_class}.execute(irb_context, \#{args})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
], nil, __FILE__, line
|
], nil, __FILE__, line
|
||||||
send :#{cmd_name}, *opts, &b
|
send :#{cmd_name}_, *opts, &b
|
||||||
end
|
end
|
||||||
], nil, __FILE__, line
|
], nil, __FILE__, line
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -34,4 +34,3 @@ module IRB
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ module IRB # :nodoc:
|
||||||
@CONF[:IGNORE_EOF] = false
|
@CONF[:IGNORE_EOF] = false
|
||||||
@CONF[:ECHO] = nil
|
@CONF[:ECHO] = nil
|
||||||
@CONF[:ECHO_ON_ASSIGNMENT] = nil
|
@CONF[:ECHO_ON_ASSIGNMENT] = nil
|
||||||
|
@CONF[:OMIT_ON_ASSIGNMENT] = nil
|
||||||
@CONF[:VERBOSE] = nil
|
@CONF[:VERBOSE] = nil
|
||||||
|
|
||||||
@CONF[:EVAL_HISTORY] = nil
|
@CONF[:EVAL_HISTORY] = nil
|
||||||
|
|
@ -177,6 +178,10 @@ module IRB # :nodoc:
|
||||||
@CONF[:ECHO_ON_ASSIGNMENT] = true
|
@CONF[:ECHO_ON_ASSIGNMENT] = true
|
||||||
when "--noecho-on-assignment"
|
when "--noecho-on-assignment"
|
||||||
@CONF[:ECHO_ON_ASSIGNMENT] = false
|
@CONF[:ECHO_ON_ASSIGNMENT] = false
|
||||||
|
when "--omit-on-assignment"
|
||||||
|
@CONF[:OMIT_ON_ASSIGNMENT] = true
|
||||||
|
when "--noomit-on-assignment"
|
||||||
|
@CONF[:OMIT_ON_ASSIGNMENT] = false
|
||||||
when "--verbose"
|
when "--verbose"
|
||||||
@CONF[:VERBOSE] = true
|
@CONF[:VERBOSE] = true
|
||||||
when "--noverbose"
|
when "--noverbose"
|
||||||
|
|
@ -271,10 +276,19 @@ module IRB # :nodoc:
|
||||||
if irbrc = ENV["IRBRC"]
|
if irbrc = ENV["IRBRC"]
|
||||||
yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc}
|
yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc}
|
||||||
end
|
end
|
||||||
|
if xdg_config_home = ENV["XDG_CONFIG_HOME"]
|
||||||
|
irb_home = File.join(xdg_config_home, "irb")
|
||||||
|
unless File.exist? irb_home
|
||||||
|
require 'fileutils'
|
||||||
|
FileUtils.mkdir_p irb_home
|
||||||
|
end
|
||||||
|
yield proc{|rc| irb_home + "/irb#{rc}"}
|
||||||
|
end
|
||||||
if home = ENV["HOME"]
|
if home = ENV["HOME"]
|
||||||
yield proc{|rc| home+"/.irb#{rc}"}
|
yield proc{|rc| home+"/.irb#{rc}"}
|
||||||
end
|
end
|
||||||
current_dir = Dir.pwd
|
current_dir = Dir.pwd
|
||||||
|
yield proc{|rc| current_dir+"/.config/irb/irb#{rc}"}
|
||||||
yield proc{|rc| current_dir+"/.irb#{rc}"}
|
yield proc{|rc| current_dir+"/.irb#{rc}"}
|
||||||
yield proc{|rc| current_dir+"/irb#{rc.sub(/\A_?/, '.')}"}
|
yield proc{|rc| current_dir+"/irb#{rc.sub(/\A_?/, '.')}"}
|
||||||
yield proc{|rc| current_dir+"/_irb#{rc}"}
|
yield proc{|rc| current_dir+"/_irb#{rc}"}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
require_relative 'src_encoding'
|
require_relative 'src_encoding'
|
||||||
require_relative 'magic-file'
|
require_relative 'magic-file'
|
||||||
require_relative 'completion'
|
require_relative 'completion'
|
||||||
|
require 'io/console'
|
||||||
require 'reline'
|
require 'reline'
|
||||||
|
|
||||||
module IRB
|
module IRB
|
||||||
|
|
@ -36,6 +37,14 @@ module IRB
|
||||||
end
|
end
|
||||||
public :gets
|
public :gets
|
||||||
|
|
||||||
|
def winsize
|
||||||
|
if instance_variable_defined?(:@stdout)
|
||||||
|
@stdout.winsize
|
||||||
|
else
|
||||||
|
[24, 80]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Whether this input method is still readable when there is no more data to
|
# Whether this input method is still readable when there is no more data to
|
||||||
# read.
|
# read.
|
||||||
#
|
#
|
||||||
|
|
@ -43,6 +52,11 @@ module IRB
|
||||||
def readable_after_eof?
|
def readable_after_eof?
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# For debug message
|
||||||
|
def inspect
|
||||||
|
'Abstract InputMethod'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class StdioInputMethod < InputMethod
|
class StdioInputMethod < InputMethod
|
||||||
|
|
@ -93,6 +107,11 @@ module IRB
|
||||||
def encoding
|
def encoding
|
||||||
@stdin.external_encoding
|
@stdin.external_encoding
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# For debug message
|
||||||
|
def inspect
|
||||||
|
'StdioInputMethod'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Use a File for IO with irb, see InputMethod
|
# Use a File for IO with irb, see InputMethod
|
||||||
|
|
@ -125,14 +144,25 @@ module IRB
|
||||||
def encoding
|
def encoding
|
||||||
@io.external_encoding
|
@io.external_encoding
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# For debug message
|
||||||
|
def inspect
|
||||||
|
'FileInputMethod'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
require "readline"
|
|
||||||
class ReadlineInputMethod < InputMethod
|
class ReadlineInputMethod < InputMethod
|
||||||
include Readline
|
def self.initialize_readline
|
||||||
|
require "readline"
|
||||||
|
rescue LoadError
|
||||||
|
else
|
||||||
|
include ::Readline
|
||||||
|
end
|
||||||
|
|
||||||
# Creates a new input method object using Readline
|
# Creates a new input method object using Readline
|
||||||
def initialize
|
def initialize
|
||||||
|
self.class.initialize_readline
|
||||||
if Readline.respond_to?(:encoding_system_needs)
|
if Readline.respond_to?(:encoding_system_needs)
|
||||||
IRB.__send__(:set_encoding, Readline.encoding_system_needs.name, override: false)
|
IRB.__send__(:set_encoding, Readline.encoding_system_needs.name, override: false)
|
||||||
end
|
end
|
||||||
|
|
@ -197,13 +227,15 @@ module IRB
|
||||||
@stdin.external_encoding
|
@stdin.external_encoding
|
||||||
end
|
end
|
||||||
|
|
||||||
if Readline.respond_to?("basic_word_break_characters=")
|
# For debug message
|
||||||
Readline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS
|
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
|
||||||
Readline.completion_append_character = nil
|
|
||||||
Readline.completion_proc = IRB::InputCompletor::CompletionProc
|
|
||||||
end
|
end
|
||||||
rescue LoadError
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class ReidlineInputMethod < InputMethod
|
class ReidlineInputMethod < InputMethod
|
||||||
|
|
@ -227,7 +259,7 @@ module IRB
|
||||||
Reline.completion_proc = IRB::InputCompletor::CompletionProc
|
Reline.completion_proc = IRB::InputCompletor::CompletionProc
|
||||||
Reline.output_modifier_proc =
|
Reline.output_modifier_proc =
|
||||||
if IRB.conf[:USE_COLORIZE]
|
if IRB.conf[:USE_COLORIZE]
|
||||||
proc do |output, complete:|
|
proc do |output, complete: |
|
||||||
next unless IRB::Color.colorable?
|
next unless IRB::Color.colorable?
|
||||||
IRB::Color.colorize_code(output, complete: complete)
|
IRB::Color.colorize_code(output, complete: complete)
|
||||||
end
|
end
|
||||||
|
|
@ -297,5 +329,18 @@ module IRB
|
||||||
def encoding
|
def encoding
|
||||||
@stdin.external_encoding
|
@stdin.external_encoding
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# For debug message
|
||||||
|
def inspect
|
||||||
|
config = Reline::Config.new
|
||||||
|
str = "ReidlineInputMethod 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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ module IRB # :nodoc:
|
||||||
result
|
result
|
||||||
rescue NoMethodError
|
rescue NoMethodError
|
||||||
puts "(Object doesn't support #inspect)"
|
puts "(Object doesn't support #inspect)"
|
||||||
|
''
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
Inspector.def_inspector([:pp, :pretty_inspect], proc{require "pp"}){|v|
|
Inspector.def_inspector([:pp, :pretty_inspect], proc{require "pp"}){|v|
|
||||||
|
|
@ -135,8 +136,3 @@ module IRB # :nodoc:
|
||||||
Marshal.dump(v)
|
Marshal.dump(v)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
|
||||||
spec.summary = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
|
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.description = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
|
||||||
spec.homepage = "https://github.com/ruby/irb"
|
spec.homepage = "https://github.com/ruby/irb"
|
||||||
spec.license = "BSD-2-Clause"
|
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
||||||
|
|
||||||
spec.files = [
|
spec.files = [
|
||||||
".document",
|
".document",
|
||||||
|
|
@ -78,7 +78,7 @@ Gem::Specification.new do |spec|
|
||||||
|
|
||||||
spec.required_ruby_version = Gem::Requirement.new(">= 2.5")
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.5")
|
||||||
|
|
||||||
spec.add_dependency "reline", ">= 0.0.1"
|
spec.add_dependency "reline", ">= 0.1.5"
|
||||||
spec.add_development_dependency "bundler"
|
spec.add_development_dependency "bundler"
|
||||||
spec.add_development_dependency "rake"
|
spec.add_development_dependency "rake"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
require "ripper"
|
require "ripper"
|
||||||
|
require "jruby" if RUBY_ENGINE == "jruby"
|
||||||
|
|
||||||
# :stopdoc:
|
# :stopdoc:
|
||||||
class RubyLex
|
class RubyLex
|
||||||
|
|
@ -29,6 +30,18 @@ class RubyLex
|
||||||
@prompt = nil
|
@prompt = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.compile_with_errors_suppressed(code)
|
||||||
|
line_no = 1
|
||||||
|
begin
|
||||||
|
result = yield code, line_no
|
||||||
|
rescue ArgumentError
|
||||||
|
code = ";\n#{code}"
|
||||||
|
line_no = 0
|
||||||
|
result = yield code, line_no
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
# io functions
|
# io functions
|
||||||
def set_input(io, p = nil, &block)
|
def set_input(io, p = nil, &block)
|
||||||
@io = io
|
@io = io
|
||||||
|
|
@ -75,7 +88,10 @@ class RubyLex
|
||||||
|
|
||||||
def ripper_lex_without_warning(code)
|
def ripper_lex_without_warning(code)
|
||||||
verbose, $VERBOSE = $VERBOSE, nil
|
verbose, $VERBOSE = $VERBOSE, nil
|
||||||
tokens = Ripper.lex(code)
|
tokens = nil
|
||||||
|
self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
|
||||||
|
tokens = Ripper.lex(inner_code, '-', line_no)
|
||||||
|
end
|
||||||
$VERBOSE = verbose
|
$VERBOSE = verbose
|
||||||
tokens
|
tokens
|
||||||
end
|
end
|
||||||
|
|
@ -209,7 +225,9 @@ class RubyLex
|
||||||
when 'jruby'
|
when 'jruby'
|
||||||
JRuby.compile_ir(code)
|
JRuby.compile_ir(code)
|
||||||
else
|
else
|
||||||
RubyVM::InstructionSequence.compile(code)
|
self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
|
||||||
|
RubyVM::InstructionSequence.compile(inner_code, nil, nil, line_no)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
rescue EncodingError
|
rescue EncodingError
|
||||||
# This is for a hash with invalid encoding symbol, {"\xAE": 1}
|
# This is for a hash with invalid encoding symbol, {"\xAE": 1}
|
||||||
|
|
@ -285,9 +303,33 @@ class RubyLex
|
||||||
|
|
||||||
def process_nesting_level
|
def process_nesting_level
|
||||||
indent = 0
|
indent = 0
|
||||||
|
in_oneliner_def = nil
|
||||||
@tokens.each_with_index { |t, index|
|
@tokens.each_with_index { |t, index|
|
||||||
|
# detecting one-liner method definition
|
||||||
|
if in_oneliner_def.nil?
|
||||||
|
if t[3].allbits?(Ripper::EXPR_ENDFN)
|
||||||
|
in_oneliner_def = :ENDFN
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if t[3].allbits?(Ripper::EXPR_ENDFN)
|
||||||
|
# continuing
|
||||||
|
elsif t[3].allbits?(Ripper::EXPR_BEG)
|
||||||
|
if t[2] == '='
|
||||||
|
in_oneliner_def = :BODY
|
||||||
|
end
|
||||||
|
elsif t[3].allbits?(Ripper::EXPR_END)
|
||||||
|
if in_oneliner_def == :BODY
|
||||||
|
# one-liner method definition
|
||||||
|
indent -= 1
|
||||||
|
end
|
||||||
|
in_oneliner_def = nil
|
||||||
|
else
|
||||||
|
in_oneliner_def = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
case t[1]
|
case t[1]
|
||||||
when :on_lbracket, :on_lbrace, :on_lparen
|
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
|
||||||
indent += 1
|
indent += 1
|
||||||
when :on_rbracket, :on_rbrace, :on_rparen
|
when :on_rbracket, :on_rbrace, :on_rparen
|
||||||
indent -= 1
|
indent -= 1
|
||||||
|
|
@ -306,7 +348,7 @@ class RubyLex
|
||||||
when 'def', 'case', 'for', 'begin', 'class', 'module'
|
when 'def', 'case', 'for', 'begin', 'class', 'module'
|
||||||
indent += 1
|
indent += 1
|
||||||
when 'if', 'unless', 'while', 'until'
|
when 'if', 'unless', 'while', 'until'
|
||||||
# postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
|
# postfix if/unless/while/until must be Ripper::EXPR_LABEL
|
||||||
indent += 1 unless t[3].allbits?(Ripper::EXPR_LABEL)
|
indent += 1 unless t[3].allbits?(Ripper::EXPR_LABEL)
|
||||||
when 'end'
|
when 'end'
|
||||||
indent -= 1
|
indent -= 1
|
||||||
|
|
@ -320,7 +362,31 @@ class RubyLex
|
||||||
def check_newline_depth_difference
|
def check_newline_depth_difference
|
||||||
depth_difference = 0
|
depth_difference = 0
|
||||||
open_brace_on_line = 0
|
open_brace_on_line = 0
|
||||||
|
in_oneliner_def = nil
|
||||||
@tokens.each_with_index do |t, index|
|
@tokens.each_with_index do |t, index|
|
||||||
|
# detecting one-liner method definition
|
||||||
|
if in_oneliner_def.nil?
|
||||||
|
if t[3].allbits?(Ripper::EXPR_ENDFN)
|
||||||
|
in_oneliner_def = :ENDFN
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if t[3].allbits?(Ripper::EXPR_ENDFN)
|
||||||
|
# continuing
|
||||||
|
elsif t[3].allbits?(Ripper::EXPR_BEG)
|
||||||
|
if t[2] == '='
|
||||||
|
in_oneliner_def = :BODY
|
||||||
|
end
|
||||||
|
elsif t[3].allbits?(Ripper::EXPR_END)
|
||||||
|
if in_oneliner_def == :BODY
|
||||||
|
# one[-liner method definition
|
||||||
|
depth_difference -= 1
|
||||||
|
end
|
||||||
|
in_oneliner_def = nil
|
||||||
|
else
|
||||||
|
in_oneliner_def = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
case t[1]
|
case t[1]
|
||||||
when :on_ignored_nl, :on_nl, :on_comment
|
when :on_ignored_nl, :on_nl, :on_comment
|
||||||
if index != (@tokens.size - 1)
|
if index != (@tokens.size - 1)
|
||||||
|
|
@ -332,7 +398,7 @@ class RubyLex
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
case t[1]
|
case t[1]
|
||||||
when :on_lbracket, :on_lbrace, :on_lparen
|
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
|
||||||
depth_difference += 1
|
depth_difference += 1
|
||||||
open_brace_on_line += 1
|
open_brace_on_line += 1
|
||||||
when :on_rbracket, :on_rbrace, :on_rparen
|
when :on_rbracket, :on_rbrace, :on_rparen
|
||||||
|
|
@ -351,12 +417,12 @@ class RubyLex
|
||||||
end
|
end
|
||||||
when 'def', 'case', 'for', 'begin', 'class', 'module'
|
when 'def', 'case', 'for', 'begin', 'class', 'module'
|
||||||
depth_difference += 1
|
depth_difference += 1
|
||||||
when 'if', 'unless', 'while', 'until'
|
when 'if', 'unless', 'while', 'until', 'rescue'
|
||||||
# postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
|
# postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
|
||||||
unless t[3].allbits?(Ripper::EXPR_LABEL)
|
unless t[3].allbits?(Ripper::EXPR_LABEL)
|
||||||
depth_difference += 1
|
depth_difference += 1
|
||||||
end
|
end
|
||||||
when 'else', 'elsif', 'rescue', 'ensure', 'when', 'in'
|
when 'else', 'elsif', 'ensure', 'when', 'in'
|
||||||
depth_difference += 1
|
depth_difference += 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -371,7 +437,36 @@ class RubyLex
|
||||||
spaces_of_nest = []
|
spaces_of_nest = []
|
||||||
spaces_at_line_head = 0
|
spaces_at_line_head = 0
|
||||||
open_brace_on_line = 0
|
open_brace_on_line = 0
|
||||||
|
in_oneliner_def = nil
|
||||||
@tokens.each_with_index do |t, index|
|
@tokens.each_with_index do |t, index|
|
||||||
|
# detecting one-liner method definition
|
||||||
|
if in_oneliner_def.nil?
|
||||||
|
if t[3].allbits?(Ripper::EXPR_ENDFN)
|
||||||
|
in_oneliner_def = :ENDFN
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if t[3].allbits?(Ripper::EXPR_ENDFN)
|
||||||
|
# continuing
|
||||||
|
elsif t[3].allbits?(Ripper::EXPR_BEG)
|
||||||
|
if t[2] == '='
|
||||||
|
in_oneliner_def = :BODY
|
||||||
|
end
|
||||||
|
elsif t[3].allbits?(Ripper::EXPR_END)
|
||||||
|
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
|
||||||
|
else
|
||||||
|
in_oneliner_def = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
case t[1]
|
case t[1]
|
||||||
when :on_ignored_nl, :on_nl, :on_comment
|
when :on_ignored_nl, :on_nl, :on_comment
|
||||||
corresponding_token_depth = nil
|
corresponding_token_depth = nil
|
||||||
|
|
@ -386,7 +481,7 @@ class RubyLex
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
case t[1]
|
case t[1]
|
||||||
when :on_lbracket, :on_lbrace, :on_lparen
|
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
|
||||||
spaces_of_nest.push(spaces_at_line_head + open_brace_on_line * 2)
|
spaces_of_nest.push(spaces_at_line_head + open_brace_on_line * 2)
|
||||||
open_brace_on_line += 1
|
open_brace_on_line += 1
|
||||||
when :on_rbracket, :on_rbrace, :on_rparen
|
when :on_rbracket, :on_rbrace, :on_rparen
|
||||||
|
|
@ -402,12 +497,16 @@ class RubyLex
|
||||||
case t[2]
|
case t[2]
|
||||||
when 'def', 'do', 'case', 'for', 'begin', 'class', 'module'
|
when 'def', 'do', 'case', 'for', 'begin', 'class', 'module'
|
||||||
spaces_of_nest.push(spaces_at_line_head)
|
spaces_of_nest.push(spaces_at_line_head)
|
||||||
|
when 'rescue'
|
||||||
|
unless t[3].allbits?(Ripper::EXPR_LABEL)
|
||||||
|
corresponding_token_depth = spaces_of_nest.last
|
||||||
|
end
|
||||||
when 'if', 'unless', 'while', 'until'
|
when 'if', 'unless', 'while', 'until'
|
||||||
# postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
|
# postfix if/unless/while/until must be Ripper::EXPR_LABEL
|
||||||
unless t[3].allbits?(Ripper::EXPR_LABEL)
|
unless t[3].allbits?(Ripper::EXPR_LABEL)
|
||||||
spaces_of_nest.push(spaces_at_line_head)
|
spaces_of_nest.push(spaces_at_line_head)
|
||||||
end
|
end
|
||||||
when 'else', 'elsif', 'rescue', 'ensure', 'when', 'in'
|
when 'else', 'elsif', 'ensure', 'when', 'in'
|
||||||
corresponding_token_depth = spaces_of_nest.last
|
corresponding_token_depth = spaces_of_nest.last
|
||||||
when 'end'
|
when 'end'
|
||||||
if is_first_printable_of_line
|
if is_first_printable_of_line
|
||||||
|
|
|
||||||
|
|
@ -35,4 +35,3 @@
|
||||||
m7 NW H N HSVO1z=?11-
|
m7 NW H N HSVO1z=?11-
|
||||||
NgTH bB kH WBHWWHBHWmQgg&gggggNNN
|
NgTH bB kH WBHWWHBHWmQgg&gggggNNN
|
||||||
NNggggggNN
|
NNggggggNN
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
module IRB # :nodoc:
|
module IRB # :nodoc:
|
||||||
VERSION = "1.2.3"
|
VERSION = "1.2.6"
|
||||||
@RELEASE_VERSION = VERSION
|
@RELEASE_VERSION = VERSION
|
||||||
@LAST_UPDATE_DATE = "2020-02-15"
|
@LAST_UPDATE_DATE = "2020-09-14"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
require "irb"
|
require_relative "../irb"
|
||||||
require_relative "frame"
|
require_relative "frame"
|
||||||
|
|
||||||
# An example printer for irb.
|
# An example printer for irb.
|
||||||
|
|
|
||||||
127
test/irb/test_cmd.rb
Normal file
127
test/irb/test_cmd.rb
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
# frozen_string_literal: false
|
||||||
|
require "test/unit"
|
||||||
|
require "irb"
|
||||||
|
require "irb/extend-command"
|
||||||
|
|
||||||
|
module TestIRB
|
||||||
|
class ExtendCommand < Test::Unit::TestCase
|
||||||
|
def setup
|
||||||
|
@pwd = Dir.pwd
|
||||||
|
@tmpdir = File.join(Dir.tmpdir, "test_reline_config_#{$$}")
|
||||||
|
begin
|
||||||
|
Dir.mkdir(@tmpdir)
|
||||||
|
rescue Errno::EEXIST
|
||||||
|
FileUtils.rm_rf(@tmpdir)
|
||||||
|
Dir.mkdir(@tmpdir)
|
||||||
|
end
|
||||||
|
Dir.chdir(@tmpdir)
|
||||||
|
@home_backup = ENV["HOME"]
|
||||||
|
ENV["HOME"] = @tmpdir
|
||||||
|
@default_encoding = [Encoding.default_external, Encoding.default_internal]
|
||||||
|
@stdio_encodings = [STDIN, STDOUT, STDERR].map {|io| [io.external_encoding, io.internal_encoding] }
|
||||||
|
IRB.instance_variable_get(:@CONF).clear
|
||||||
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
ENV["HOME"] = @home_backup
|
||||||
|
Dir.chdir(@pwd)
|
||||||
|
FileUtils.rm_rf(@tmpdir)
|
||||||
|
EnvUtil.suppress_warning {
|
||||||
|
Encoding.default_external, Encoding.default_internal = *@default_encoding
|
||||||
|
[STDIN, STDOUT, STDERR].zip(@stdio_encodings) do |io, encs|
|
||||||
|
io.set_encoding(*encs)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_irb_info_multiline
|
||||||
|
FileUtils.touch("#{@tmpdir}/.inputrc")
|
||||||
|
FileUtils.touch("#{@tmpdir}/.irbrc")
|
||||||
|
IRB.setup(__FILE__, argv: [])
|
||||||
|
IRB.conf[:USE_MULTILINE] = true
|
||||||
|
IRB.conf[:USE_SINGLELINE] = false
|
||||||
|
IRB.conf[:VERBOSE] = false
|
||||||
|
workspace = IRB::WorkSpace.new(self)
|
||||||
|
irb = IRB::Irb.new(workspace)
|
||||||
|
IRB.conf[:MAIN_CONTEXT] = irb.context
|
||||||
|
expected = %r{
|
||||||
|
Ruby\sversion: .+\n
|
||||||
|
IRB\sversion:\sirb .+\n
|
||||||
|
InputMethod:\sReidlineInputMethod\swith\sReline .+ and .+\n
|
||||||
|
\.irbrc\spath: .+
|
||||||
|
}x
|
||||||
|
assert_match expected, irb.context.main.irb_info.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_irb_info_singleline
|
||||||
|
FileUtils.touch("#{@tmpdir}/.inputrc")
|
||||||
|
FileUtils.touch("#{@tmpdir}/.irbrc")
|
||||||
|
IRB.setup(__FILE__, argv: [])
|
||||||
|
IRB.conf[:USE_MULTILINE] = false
|
||||||
|
IRB.conf[:USE_SINGLELINE] = true
|
||||||
|
IRB.conf[:VERBOSE] = false
|
||||||
|
workspace = IRB::WorkSpace.new(self)
|
||||||
|
irb = IRB::Irb.new(workspace)
|
||||||
|
IRB.conf[:MAIN_CONTEXT] = irb.context
|
||||||
|
expected = %r{
|
||||||
|
Ruby\sversion: .+\n
|
||||||
|
IRB\sversion:\sirb .+\n
|
||||||
|
InputMethod:\sReadlineInputMethod\swith .+ and .+\n
|
||||||
|
\.irbrc\spath: .+
|
||||||
|
}x
|
||||||
|
assert_match expected, irb.context.main.irb_info.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_irb_info_multiline_without_rc_files
|
||||||
|
inputrc_backup = ENV["INPUTRC"]
|
||||||
|
ENV["INPUTRC"] = "unknown_inpurc"
|
||||||
|
ext_backup = IRB::IRBRC_EXT
|
||||||
|
IRB.__send__(:remove_const, :IRBRC_EXT)
|
||||||
|
IRB.const_set(:IRBRC_EXT, "unknown_ext")
|
||||||
|
IRB.setup(__FILE__, argv: [])
|
||||||
|
IRB.conf[:USE_MULTILINE] = true
|
||||||
|
IRB.conf[:USE_SINGLELINE] = false
|
||||||
|
IRB.conf[:VERBOSE] = false
|
||||||
|
workspace = IRB::WorkSpace.new(self)
|
||||||
|
irb = IRB::Irb.new(workspace)
|
||||||
|
IRB.conf[:MAIN_CONTEXT] = irb.context
|
||||||
|
expected = %r{
|
||||||
|
Ruby\sversion: .+\n
|
||||||
|
IRB\sversion:\sirb .+\n
|
||||||
|
InputMethod:\sReidlineInputMethod\swith\sReline\s[^ ]+(?!\sand\s.+)\n
|
||||||
|
\z
|
||||||
|
}x
|
||||||
|
assert_match expected, irb.context.main.irb_info.to_s
|
||||||
|
ensure
|
||||||
|
ENV["INPUTRC"] = inputrc_backup
|
||||||
|
IRB.__send__(:remove_const, :IRBRC_EXT)
|
||||||
|
IRB.const_set(:IRBRC_EXT, ext_backup)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_irb_info_singleline_without_rc_files
|
||||||
|
inputrc_backup = ENV["INPUTRC"]
|
||||||
|
ENV["INPUTRC"] = "unknown_inpurc"
|
||||||
|
ext_backup = IRB::IRBRC_EXT
|
||||||
|
IRB.__send__(:remove_const, :IRBRC_EXT)
|
||||||
|
IRB.const_set(:IRBRC_EXT, "unknown_ext")
|
||||||
|
IRB.setup(__FILE__, argv: [])
|
||||||
|
IRB.conf[:USE_MULTILINE] = false
|
||||||
|
IRB.conf[:USE_SINGLELINE] = true
|
||||||
|
IRB.conf[:VERBOSE] = false
|
||||||
|
workspace = IRB::WorkSpace.new(self)
|
||||||
|
irb = IRB::Irb.new(workspace)
|
||||||
|
IRB.conf[:MAIN_CONTEXT] = irb.context
|
||||||
|
expected = %r{
|
||||||
|
Ruby\sversion: .+\n
|
||||||
|
IRB\sversion:\sirb .+\n
|
||||||
|
InputMethod:\sReadlineInputMethod\swith\s(?~.*\sand\s.+)\n
|
||||||
|
\z
|
||||||
|
}x
|
||||||
|
assert_match expected, irb.context.main.irb_info.to_s
|
||||||
|
ensure
|
||||||
|
ENV["INPUTRC"] = inputrc_backup
|
||||||
|
IRB.__send__(:remove_const, :IRBRC_EXT)
|
||||||
|
IRB.const_set(:IRBRC_EXT, ext_backup)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -30,6 +30,10 @@ module TestIRB
|
||||||
def reset
|
def reset
|
||||||
@line_no = 0
|
@line_no = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def winsize
|
||||||
|
[10, 20]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
|
|
@ -98,6 +102,21 @@ module TestIRB
|
||||||
$VERBOSE = verbose
|
$VERBOSE = verbose
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_eval_object_without_inspect_method
|
||||||
|
verbose, $VERBOSE = $VERBOSE, nil
|
||||||
|
input = TestInputMethod.new([
|
||||||
|
"BasicObject.new\n",
|
||||||
|
])
|
||||||
|
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
|
||||||
|
out, err = capture_output do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert(/\(Object doesn't support #inspect\)\n(=> )?\n/, out)
|
||||||
|
ensure
|
||||||
|
$VERBOSE = verbose
|
||||||
|
end
|
||||||
|
|
||||||
def test_default_config
|
def test_default_config
|
||||||
assert_equal(true, @context.use_colorize?)
|
assert_equal(true, @context.use_colorize?)
|
||||||
end
|
end
|
||||||
|
|
@ -198,6 +217,151 @@ module TestIRB
|
||||||
assert_equal("", out)
|
assert_equal("", out)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_omit_on_assignment
|
||||||
|
input = TestInputMethod.new([
|
||||||
|
"a = [1] * 100\n",
|
||||||
|
"a\n",
|
||||||
|
])
|
||||||
|
value = [1] * 100
|
||||||
|
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
|
||||||
|
irb.context.return_format = "=> %s\n"
|
||||||
|
|
||||||
|
irb.context.echo = true
|
||||||
|
irb.context.echo_on_assignment = false
|
||||||
|
irb.context.omit_on_assignment = true
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("=> #{value.inspect}\n", out)
|
||||||
|
|
||||||
|
input.reset
|
||||||
|
irb.context.echo = true
|
||||||
|
irb.context.echo_on_assignment = true
|
||||||
|
irb.context.omit_on_assignment = true
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("=> #{value.inspect[0..(input.winsize.last - 9)]}...\e[0m\n=> #{value.inspect}\n", out)
|
||||||
|
|
||||||
|
input.reset
|
||||||
|
irb.context.echo = true
|
||||||
|
irb.context.echo_on_assignment = true
|
||||||
|
irb.context.omit_on_assignment = false
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("=> #{value.inspect}\n=> #{value.inspect}\n", out)
|
||||||
|
|
||||||
|
input.reset
|
||||||
|
irb.context.echo = false
|
||||||
|
irb.context.echo_on_assignment = false
|
||||||
|
irb.context.omit_on_assignment = true
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("", out)
|
||||||
|
|
||||||
|
input.reset
|
||||||
|
irb.context.echo = false
|
||||||
|
irb.context.echo_on_assignment = true
|
||||||
|
irb.context.omit_on_assignment = true
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("", out)
|
||||||
|
|
||||||
|
input.reset
|
||||||
|
irb.context.echo = false
|
||||||
|
irb.context.echo_on_assignment = true
|
||||||
|
irb.context.omit_on_assignment = false
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("", out)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_omit_multiline_on_assignment
|
||||||
|
input = TestInputMethod.new([
|
||||||
|
"class A; def inspect; ([?* * 1000] * 3).join(%{\\n}); end; end; a = A.new\n",
|
||||||
|
"a\n"
|
||||||
|
])
|
||||||
|
value = ([?* * 1000] * 3).join(%{\n})
|
||||||
|
value_first_line = (?* * 1000).to_s
|
||||||
|
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
|
||||||
|
irb.context.return_format = "=> %s\n"
|
||||||
|
|
||||||
|
irb.context.echo = true
|
||||||
|
irb.context.echo_on_assignment = false
|
||||||
|
irb.context.omit_on_assignment = true
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("=> \n#{value}\n", out)
|
||||||
|
irb.context.evaluate('A.remove_method(:inspect)', 0)
|
||||||
|
|
||||||
|
input.reset
|
||||||
|
irb.context.echo = true
|
||||||
|
irb.context.echo_on_assignment = true
|
||||||
|
irb.context.omit_on_assignment = true
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("=> #{value_first_line[0..(input.winsize.last - 9)]}...\e[0m\n=> \n#{value}\n", out)
|
||||||
|
irb.context.evaluate('A.remove_method(:inspect)', 0)
|
||||||
|
|
||||||
|
input.reset
|
||||||
|
irb.context.echo = true
|
||||||
|
irb.context.echo_on_assignment = true
|
||||||
|
irb.context.omit_on_assignment = false
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("=> \n#{value}\n=> \n#{value}\n", out)
|
||||||
|
irb.context.evaluate('A.remove_method(:inspect)', 0)
|
||||||
|
|
||||||
|
input.reset
|
||||||
|
irb.context.echo = false
|
||||||
|
irb.context.echo_on_assignment = false
|
||||||
|
irb.context.omit_on_assignment = true
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("", out)
|
||||||
|
irb.context.evaluate('A.remove_method(:inspect)', 0)
|
||||||
|
|
||||||
|
input.reset
|
||||||
|
irb.context.echo = false
|
||||||
|
irb.context.echo_on_assignment = true
|
||||||
|
irb.context.omit_on_assignment = true
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("", out)
|
||||||
|
irb.context.evaluate('A.remove_method(:inspect)', 0)
|
||||||
|
|
||||||
|
input.reset
|
||||||
|
irb.context.echo = false
|
||||||
|
irb.context.echo_on_assignment = true
|
||||||
|
irb.context.omit_on_assignment = false
|
||||||
|
out, err = capture_io do
|
||||||
|
irb.eval_input
|
||||||
|
end
|
||||||
|
assert_empty err
|
||||||
|
assert_equal("", out)
|
||||||
|
irb.context.evaluate('A.remove_method(:inspect)', 0)
|
||||||
|
end
|
||||||
|
|
||||||
def test_echo_on_assignment_conf
|
def test_echo_on_assignment_conf
|
||||||
# Default
|
# Default
|
||||||
IRB.conf[:ECHO] = nil
|
IRB.conf[:ECHO] = nil
|
||||||
|
|
@ -206,22 +370,26 @@ module TestIRB
|
||||||
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
|
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
|
||||||
|
|
||||||
assert(irb.context.echo?, "echo? should be true by default")
|
assert(irb.context.echo?, "echo? should be true by default")
|
||||||
refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false by default")
|
assert(irb.context.echo_on_assignment?, "echo_on_assignment? should be true by default")
|
||||||
|
assert(irb.context.omit_on_assignment?, "omit_on_assignment? should be true by default")
|
||||||
|
|
||||||
# Explicitly set :ECHO to false
|
# Explicitly set :ECHO to false
|
||||||
IRB.conf[:ECHO] = false
|
IRB.conf[:ECHO] = false
|
||||||
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
|
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
|
||||||
|
|
||||||
refute(irb.context.echo?, "echo? should be false when IRB.conf[:ECHO] is set to false")
|
refute(irb.context.echo?, "echo? should be false when IRB.conf[:ECHO] is set to false")
|
||||||
refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false by default")
|
assert(irb.context.echo_on_assignment?, "echo_on_assignment? should be true by default")
|
||||||
|
assert(irb.context.omit_on_assignment?, "omit_on_assignment? should be true by default")
|
||||||
|
|
||||||
# Explicitly set :ECHO_ON_ASSIGNMENT to true
|
# Explicitly set :ECHO_ON_ASSIGNMENT to true
|
||||||
IRB.conf[:ECHO] = nil
|
IRB.conf[:ECHO] = nil
|
||||||
IRB.conf[:ECHO_ON_ASSIGNMENT] = true
|
IRB.conf[:ECHO_ON_ASSIGNMENT] = false
|
||||||
|
IRB.conf[:OMIT_ON_ASSIGNMENT] = false
|
||||||
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
|
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
|
||||||
|
|
||||||
assert(irb.context.echo?, "echo? should be true by default")
|
assert(irb.context.echo?, "echo? should be true by default")
|
||||||
assert(irb.context.echo_on_assignment?, "echo_on_assignment? should be true when IRB.conf[:ECHO_ON_ASSIGNMENT] is set to true")
|
refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false when IRB.conf[:ECHO_ON_ASSIGNMENT] is set to false")
|
||||||
|
refute(irb.context.omit_on_assignment?, "omit_on_assignment? should be false when IRB.conf[:OMIT_ON_ASSIGNMENT] is set to false")
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_multiline_output_on_default_inspector
|
def test_multiline_output_on_default_inspector
|
||||||
|
|
|
||||||
153
test/irb/test_history.rb
Normal file
153
test/irb/test_history.rb
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
# frozen_string_literal: false
|
||||||
|
require 'test/unit'
|
||||||
|
require 'irb'
|
||||||
|
require 'readline'
|
||||||
|
|
||||||
|
module TestIRB
|
||||||
|
class TestHistory < Test::Unit::TestCase
|
||||||
|
def setup
|
||||||
|
IRB.conf[:RC_NAME_GENERATOR] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
IRB.conf[:RC_NAME_GENERATOR] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_history_save_1
|
||||||
|
omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
|
||||||
|
_result_output, result_history_file = launch_irb_with_irbrc_and_irb_history(<<~IRBRC, <<~IRB_HISTORY) do |stdin|
|
||||||
|
IRB.conf[:USE_READLINE] = true
|
||||||
|
IRB.conf[:SAVE_HISTORY] = 1
|
||||||
|
IRB.conf[:USE_READLINE] = true
|
||||||
|
IRBRC
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
IRB_HISTORY
|
||||||
|
stdin.write("5\nexit\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal(<<~HISTORY_FILE, result_history_file)
|
||||||
|
exit
|
||||||
|
HISTORY_FILE
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_history_save_100
|
||||||
|
omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
|
||||||
|
_result_output, result_history_file = launch_irb_with_irbrc_and_irb_history(<<~IRBRC, <<~IRB_HISTORY) do |stdin|
|
||||||
|
IRB.conf[:USE_READLINE] = true
|
||||||
|
IRB.conf[:SAVE_HISTORY] = 100
|
||||||
|
IRB.conf[:USE_READLINE] = true
|
||||||
|
IRBRC
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
IRB_HISTORY
|
||||||
|
stdin.write("5\nexit\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal(<<~HISTORY_FILE, result_history_file)
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
exit
|
||||||
|
HISTORY_FILE
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_history_save_bignum
|
||||||
|
omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
|
||||||
|
_result_output, result_history_file = launch_irb_with_irbrc_and_irb_history(<<~IRBRC, <<~IRB_HISTORY) do |stdin|
|
||||||
|
IRB.conf[:USE_READLINE] = true
|
||||||
|
IRB.conf[:SAVE_HISTORY] = 10 ** 19
|
||||||
|
IRB.conf[:USE_READLINE] = true
|
||||||
|
IRBRC
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
IRB_HISTORY
|
||||||
|
stdin.write("5\nexit\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal(<<~HISTORY_FILE, result_history_file)
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
exit
|
||||||
|
HISTORY_FILE
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_history_save_minus_as_infinity
|
||||||
|
omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
|
||||||
|
_result_output, result_history_file = launch_irb_with_irbrc_and_irb_history(<<~IRBRC, <<~IRB_HISTORY) do |stdin|
|
||||||
|
IRB.conf[:USE_READLINE] = true
|
||||||
|
IRB.conf[:SAVE_HISTORY] = -1 # infinity
|
||||||
|
IRB.conf[:USE_READLINE] = true
|
||||||
|
IRBRC
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
IRB_HISTORY
|
||||||
|
stdin.write("5\nexit\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal(<<~HISTORY_FILE, result_history_file)
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
exit
|
||||||
|
HISTORY_FILE
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def launch_irb_with_irbrc_and_irb_history(irbrc, irb_history)
|
||||||
|
result = nil
|
||||||
|
result_history = nil
|
||||||
|
backup_irbrc = ENV.delete("IRBRC")
|
||||||
|
backup_home = ENV["HOME"]
|
||||||
|
Dir.mktmpdir("test_irb_history_#{$$}") do |tmpdir|
|
||||||
|
ENV["HOME"] = tmpdir
|
||||||
|
open(IRB.rc_file, "w") do |f|
|
||||||
|
f.write(irbrc)
|
||||||
|
end
|
||||||
|
open(IRB.rc_file("_history"), "w") do |f|
|
||||||
|
f.write(irb_history)
|
||||||
|
end
|
||||||
|
|
||||||
|
with_temp_stdio do |stdin, stdout|
|
||||||
|
yield(stdin, stdout)
|
||||||
|
stdin.close
|
||||||
|
stdout.flush
|
||||||
|
system('ruby', '-Ilib', '-Itest', '-W0', '-rirb', '-e', 'IRB.start(__FILE__)', in: stdin.path, out: stdout.path)
|
||||||
|
result = stdout.read
|
||||||
|
stdout.close
|
||||||
|
end
|
||||||
|
open(IRB.rc_file("_history"), "r") do |f|
|
||||||
|
result_history = f.read
|
||||||
|
end
|
||||||
|
end
|
||||||
|
[result, result_history]
|
||||||
|
ensure
|
||||||
|
ENV["HOME"] = backup_home
|
||||||
|
ENV["IRBRC"] = backup_irbrc
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_temp_stdio
|
||||||
|
Tempfile.create("test_readline_stdin") do |stdin|
|
||||||
|
Tempfile.create("test_readline_stdout") do |stdout|
|
||||||
|
yield stdin, stdout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end if not RUBY_PLATFORM.match?(/solaris|mswin|mingw/i)
|
||||||
|
|
@ -5,7 +5,7 @@ require 'ostruct'
|
||||||
|
|
||||||
module TestIRB
|
module TestIRB
|
||||||
class TestRubyLex < Test::Unit::TestCase
|
class TestRubyLex < Test::Unit::TestCase
|
||||||
Row = Struct.new(:content, :current_line_spaces, :new_line_spaces)
|
Row = Struct.new(:content, :current_line_spaces, :new_line_spaces, :nesting_level)
|
||||||
|
|
||||||
class MockIO
|
class MockIO
|
||||||
def initialize(params, &assertion)
|
def initialize(params, &assertion)
|
||||||
|
|
@ -34,6 +34,15 @@ module TestIRB
|
||||||
ruby_lex.set_auto_indent(context)
|
ruby_lex.set_auto_indent(context)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def assert_nesting_level(lines, expected)
|
||||||
|
ruby_lex = RubyLex.new()
|
||||||
|
io = proc{ lines.join("\n") }
|
||||||
|
ruby_lex.set_input(io, io)
|
||||||
|
ruby_lex.lex
|
||||||
|
error_message = "Calculated the wrong number of nesting level for:\n #{lines.join("\n")}"
|
||||||
|
assert_equal(expected, ruby_lex.instance_variable_get(:@indent), error_message)
|
||||||
|
end
|
||||||
|
|
||||||
def test_auto_indent
|
def test_auto_indent
|
||||||
input_with_correct_indents = [
|
input_with_correct_indents = [
|
||||||
Row.new(%q(def each_top_level_statement), nil, 2),
|
Row.new(%q(def each_top_level_statement), nil, 2),
|
||||||
|
|
@ -126,5 +135,130 @@ module TestIRB
|
||||||
assert_indenting(lines, row.new_line_spaces, true)
|
assert_indenting(lines, row.new_line_spaces, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_incomplete_coding_magic_comment
|
||||||
|
input_with_correct_indents = [
|
||||||
|
Row.new(%q(#coding:u), nil, 0),
|
||||||
|
]
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
input_with_correct_indents.each do |row|
|
||||||
|
lines << row.content
|
||||||
|
assert_indenting(lines, row.current_line_spaces, false)
|
||||||
|
assert_indenting(lines, row.new_line_spaces, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_incomplete_encoding_magic_comment
|
||||||
|
input_with_correct_indents = [
|
||||||
|
Row.new(%q(#encoding:u), nil, 0),
|
||||||
|
]
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
input_with_correct_indents.each do |row|
|
||||||
|
lines << row.content
|
||||||
|
assert_indenting(lines, row.current_line_spaces, false)
|
||||||
|
assert_indenting(lines, row.new_line_spaces, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_incomplete_emacs_coding_magic_comment
|
||||||
|
input_with_correct_indents = [
|
||||||
|
Row.new(%q(# -*- coding: u), nil, 0),
|
||||||
|
]
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
input_with_correct_indents.each do |row|
|
||||||
|
lines << row.content
|
||||||
|
assert_indenting(lines, row.current_line_spaces, false)
|
||||||
|
assert_indenting(lines, row.new_line_spaces, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_incomplete_vim_coding_magic_comment
|
||||||
|
input_with_correct_indents = [
|
||||||
|
Row.new(%q(# vim:set fileencoding=u), nil, 0),
|
||||||
|
]
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
input_with_correct_indents.each do |row|
|
||||||
|
lines << row.content
|
||||||
|
assert_indenting(lines, row.current_line_spaces, false)
|
||||||
|
assert_indenting(lines, row.new_line_spaces, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_mixed_rescue
|
||||||
|
input_with_correct_indents = [
|
||||||
|
Row.new(%q(def m), nil, 2),
|
||||||
|
Row.new(%q( begin), nil, 4),
|
||||||
|
Row.new(%q( begin), nil, 6),
|
||||||
|
Row.new(%q( x = a rescue 4), nil, 6),
|
||||||
|
Row.new(%q( y = [(a rescue 5)]), nil, 6),
|
||||||
|
Row.new(%q( [x, y]), nil, 6),
|
||||||
|
Row.new(%q( rescue => e), 4, 6),
|
||||||
|
Row.new(%q( raise e rescue 8), nil, 6),
|
||||||
|
Row.new(%q( end), 4, 4),
|
||||||
|
Row.new(%q( rescue), 2, 4),
|
||||||
|
Row.new(%q( raise rescue 11), nil, 4),
|
||||||
|
Row.new(%q( end), 2, 2),
|
||||||
|
Row.new(%q(rescue => e), 0, 2),
|
||||||
|
Row.new(%q( raise e rescue 14), nil, 2),
|
||||||
|
Row.new(%q(end), 0, 0),
|
||||||
|
]
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
input_with_correct_indents.each do |row|
|
||||||
|
lines << row.content
|
||||||
|
assert_indenting(lines, row.current_line_spaces, false)
|
||||||
|
assert_indenting(lines, row.new_line_spaces, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_oneliner_method_definition
|
||||||
|
input_with_correct_indents = [
|
||||||
|
Row.new(%q(class A), nil, 2),
|
||||||
|
Row.new(%q( def foo0), nil, 4),
|
||||||
|
Row.new(%q( 3), nil, 4),
|
||||||
|
Row.new(%q( end), 2, 2),
|
||||||
|
Row.new(%q( def foo1()), nil, 4),
|
||||||
|
Row.new(%q( 3), nil, 4),
|
||||||
|
Row.new(%q( end), 2, 2),
|
||||||
|
Row.new(%q( def foo2(a, b)), nil, 4),
|
||||||
|
Row.new(%q( a + b), nil, 4),
|
||||||
|
Row.new(%q( end), 2, 2),
|
||||||
|
Row.new(%q( def foo3 a, b), nil, 4),
|
||||||
|
Row.new(%q( a + b), nil, 4),
|
||||||
|
Row.new(%q( end), 2, 2),
|
||||||
|
Row.new(%q( def bar0() = 3), nil, 2),
|
||||||
|
Row.new(%q( def bar1(a) = a), nil, 2),
|
||||||
|
Row.new(%q( def bar2(a, b) = a + b), nil, 2),
|
||||||
|
Row.new(%q(end), 0, 0),
|
||||||
|
]
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
input_with_correct_indents.each do |row|
|
||||||
|
lines << row.content
|
||||||
|
assert_indenting(lines, row.current_line_spaces, false)
|
||||||
|
assert_indenting(lines, row.new_line_spaces, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_tlambda
|
||||||
|
input_with_correct_indents = [
|
||||||
|
Row.new(%q(if true), nil, 2, 1),
|
||||||
|
Row.new(%q( -> {), nil, 4, 2),
|
||||||
|
Row.new(%q( }), 2, 2, 1),
|
||||||
|
Row.new(%q(end), 0, 0, 0),
|
||||||
|
]
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
input_with_correct_indents.each do |row|
|
||||||
|
lines << row.content
|
||||||
|
assert_indenting(lines, row.current_line_spaces, false)
|
||||||
|
assert_indenting(lines, row.new_line_spaces, true)
|
||||||
|
assert_nesting_level(lines, row.nesting_level)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
# frozen_string_literal: false
|
# frozen_string_literal: false
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
require 'tempfile'
|
require 'tempfile'
|
||||||
|
require 'rubygems'
|
||||||
require 'irb'
|
require 'irb'
|
||||||
require 'irb/workspace'
|
require 'irb/workspace'
|
||||||
require 'irb/color'
|
require 'irb/color'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue