mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Backport lib/reline, and lib/irb for 3.0.1 2nd (#4157)
* [ruby/irb] Stub a screen size for tests6663057083
* [ruby/irb] Support GitHub Actions8e9e6c4037
* [ruby/irb] Stub a screen size for test_context http://ci.rvm.jp/logfiles/brlog.trunk-random1.20210119-074232ea87592d4a
* [ruby/irb] Use a real screen size for pp by default9b9300dec2
* [ruby/irb] Rescue Errno::EINVAL on IRB pp20210119
T070008Z.log.html.gz is caused by: /export/home/chkbuild/chkbuild-gcc/tmp/build/20210119T150010Z/ruby/lib/reline/ansi.rb:157:in `winsize': Invalid argument - <STDIN> (Errno::EINVAL) from /export/home/chkbuild/chkbuild-gcc/tmp/build/20210119T150010Z/ruby/lib/reline/ansi.rb:157:in `get_screen_size' from /export/home/chkbuild/chkbuild-gcc/tmp/build/20210119T150010Z/ruby/lib/reline.rb:168:in `get_screen_size' from /export/home/chkbuild/chkbuild-gcc/tmp/build/20210119T150010Z/ruby/lib/forwardable.rb:238:in `get_screen_size' from /export/home/chkbuild/chkbuild-gcc/tmp/build/20210119T150010Z/ruby/lib/irb/color_printer.rb:7:in `pp' from -e:1:in `<main>'1719514598
* [ruby/irb] Split test files for IRB::Color and IRB::ColorPrinterd95e8daab3
* [ruby/irb] Undefine unused constantseea9c16804
* [ruby/irb] Remove pp-specific stub from TestColor because it was for TestColorPrinter7569206fd4
* [ruby/irb] Delete a doodle-level memo comment...fc3e1d9e0c
* [ruby/irb] Indent correctly with keyword "for" and "in"47c83ea724
* [ruby/irb] Indent correctly with method calling with receivere7c68e74a0
* [ruby/irb] add `IRB::FileInputMethod.open` to ensure closing associated File * tweak some methods not to raise exception after `#close` * use it in `IRB::IrbLoader#{source_file,load_file}ec2947acbd
* [ruby/irb] use `RubyLex::TerminateLineInput` appropriately [Bug #17564] * using the appropriciate exception instead of `break` so that the session can be continue after the `irb_source` and `irb_load` commands * suppress extra new line due to one more `#prompt` callbdefaa7cfd
* [ruby/irb] specify the `VERBOSE` to `false` and fix tests to fit502c590925
* In test, need to pass a context to IRB::WorkSpace.new explicitly * Fix absolute path predicate on Windows A path starts with '/' is not an absolute path on Windows, because of drive letter or UNC. * [ruby/irb] follow up the actual line number7aed8fe3b1
* [ruby/irb] Add info.rb to gemspecadbba19adf
* [ruby/irb] Allow "measure" command to take block20f1ca23e9
* [ruby/irb] Enable to reassign a new block with "measure" commandb444573aa2
* [ruby/reline] Cache pasting state in processing a key Because it's too slow. The rendering time in IRB has been reduced as follows: start = Time.now 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") next if l == "\n" @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 break if @io.eof? @line = '' @exp_line_no = @line_no @indent = 0 rescue TerminateLineInput initialize_input prompt end end end end puts "Duration: #{Time.now - start} seconds" 0.22sec -> 0.14secb8b3dd52c0
* [ruby/reline] Initialize uninitialized variables in tests25af4bb64b
* [ruby/reline] Remove an unused variable123ea51166
* [ruby/reline] Scroll down when ^C is pressed6877a7e3f5
* [ruby/reline] Show all lines higher than the screen when finished On Unix-like OSes, logs prior to the screen are not editable. When the code is higher than the screen, the code is only shown on the screen until input is finished, but when it is finished, all lines are outputted.8cd9132a39
* [ruby/reline] Handle past logs correctly when the code is higher than the screenf197139b4a
* [ruby/reline] Update cursor info by inserting newline even if not in pasting92d314f514
* [ruby/reline] Move cursor just after the last line when finishedba06e4c480
* [ruby/reline] The vi_histedit supports multiline This closes ruby/reline#253.f131f86d71
* [ruby/reline] Autowrap correctly when inserting chars in the middle of a lineebaf37255f
* [ruby/reline] Terminate correctly in the middle of lines higher than the screene1d9240ada
* [ruby/irb] Version 1.3.34c87035b7c
* [ruby/reline] Version 0.2.3b26c7d60c8
Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Co-authored-by: Nobuhiro IMAI <nov@yo.rim.or.jp> Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org> Co-authored-by: ima1zumi <mariimaizumi5@gmail.com>
This commit is contained in:
parent
0c6361ff28
commit
77700bf023
19 changed files with 568 additions and 88 deletions
|
@ -525,7 +525,7 @@ module IRB
|
|||
printf "Use \"exit\" to leave %s\n", @context.ap_name
|
||||
end
|
||||
else
|
||||
print "\n"
|
||||
print "\n" if @context.prompting?
|
||||
end
|
||||
end
|
||||
l
|
||||
|
|
|
@ -8,7 +8,7 @@ module IRB
|
|||
super(*args)
|
||||
end
|
||||
|
||||
def execute(type = nil, arg = nil)
|
||||
def execute(type = nil, arg = nil, &block)
|
||||
case type
|
||||
when :off
|
||||
IRB.conf[:MEASURE] = nil
|
||||
|
@ -22,9 +22,15 @@ module IRB
|
|||
added = IRB.set_measure_callback(type, arg)
|
||||
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
|
||||
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
|
||||
|
|
|
@ -15,9 +15,9 @@ module IRB
|
|||
class Nop
|
||||
|
||||
|
||||
def self.execute(conf, *opts)
|
||||
def self.execute(conf, *opts, &block)
|
||||
command = new(conf)
|
||||
command.execute(*opts)
|
||||
command.execute(*opts, &block)
|
||||
end
|
||||
|
||||
def initialize(conf)
|
||||
|
|
|
@ -4,11 +4,21 @@ require 'irb/color'
|
|||
|
||||
module IRB
|
||||
class ColorPrinter < ::PP
|
||||
def self.pp(obj, out = $>, width = 79)
|
||||
q = ColorPrinter.new(out, width)
|
||||
q.guard_inspect_key {q.pp obj}
|
||||
q.flush
|
||||
out << "\n"
|
||||
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 text(str, width = nil)
|
||||
|
|
|
@ -31,8 +31,31 @@ module IRB # :nodoc:
|
|||
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
|
||||
File::SEPARATOR
|
||||
else
|
||||
"[#{Regexp.quote(File::SEPARATOR + File::ALT_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 /^#{Regexp.quote(File::Separator)}/ =~ fn
|
||||
if absolute_path?(fn)
|
||||
return fn if File.exist?(fn)
|
||||
return nil
|
||||
end
|
||||
|
@ -50,16 +73,18 @@ module IRB # :nodoc:
|
|||
# See Irb#suspend_input_method for more information.
|
||||
def source_file(path)
|
||||
irb.suspend_name(path, File.basename(path)) do
|
||||
irb.suspend_input_method(FileInputMethod.new(path)) do
|
||||
|back_io|
|
||||
irb.signal_status(:IN_LOAD) do
|
||||
if back_io.kind_of?(FileInputMethod)
|
||||
irb.eval_input
|
||||
else
|
||||
begin
|
||||
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
|
||||
rescue LoadAbort
|
||||
print "load abort!!\n"
|
||||
else
|
||||
begin
|
||||
irb.eval_input
|
||||
rescue LoadAbort
|
||||
print "load abort!!\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -79,16 +104,18 @@ module IRB # :nodoc:
|
|||
ws = WorkSpace.new
|
||||
end
|
||||
irb.suspend_workspace(ws) do
|
||||
irb.suspend_input_method(FileInputMethod.new(path)) do
|
||||
|back_io|
|
||||
irb.signal_status(:IN_LOAD) do
|
||||
if back_io.kind_of?(FileInputMethod)
|
||||
irb.eval_input
|
||||
else
|
||||
begin
|
||||
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
|
||||
rescue LoadAbort
|
||||
print "load abort!!\n"
|
||||
else
|
||||
begin
|
||||
irb.eval_input
|
||||
rescue LoadAbort
|
||||
print "load abort!!\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -146,7 +146,7 @@ module IRB # :nodoc:
|
|||
@CONF[:AT_EXIT] = []
|
||||
end
|
||||
|
||||
def IRB.set_measure_callback(type = nil, arg = nil)
|
||||
def IRB.set_measure_callback(type = nil, arg = nil, &block)
|
||||
added = nil
|
||||
if type
|
||||
type_sym = type.upcase.to_sym
|
||||
|
@ -155,6 +155,16 @@ module IRB # :nodoc:
|
|||
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
|
||||
|
|
|
@ -124,10 +124,22 @@ module IRB
|
|||
|
||||
# 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 = 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
|
||||
|
@ -137,7 +149,7 @@ module IRB
|
|||
#
|
||||
# See IO#eof? for more information.
|
||||
def eof?
|
||||
@io.eof?
|
||||
@io.closed? || @io.eof?
|
||||
end
|
||||
|
||||
# Reads the next line from this input method.
|
||||
|
@ -150,13 +162,17 @@ module IRB
|
|||
|
||||
# The external encoding for standard input.
|
||||
def encoding
|
||||
@io.external_encoding
|
||||
@external_encoding
|
||||
end
|
||||
|
||||
# For debug message
|
||||
def inspect
|
||||
'FileInputMethod'
|
||||
end
|
||||
|
||||
def close
|
||||
@io.close
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
|
|
|
@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
|
|||
"lib/irb/cmd/chws.rb",
|
||||
"lib/irb/cmd/fork.rb",
|
||||
"lib/irb/cmd/help.rb",
|
||||
"lib/irb/cmd/info.rb",
|
||||
"lib/irb/cmd/load.rb",
|
||||
"lib/irb/cmd/measure.rb",
|
||||
"lib/irb/cmd/nop.rb",
|
||||
|
|
|
@ -223,7 +223,10 @@ class RubyLex
|
|||
throw :TERM_INPUT if @line == ''
|
||||
else
|
||||
@line_no += l.count("\n")
|
||||
next if l == "\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
|
||||
|
@ -233,7 +236,7 @@ class RubyLex
|
|||
@line.force_encoding(@io.encoding)
|
||||
yield @line, @exp_line_no
|
||||
end
|
||||
break if @io.eof?
|
||||
raise TerminateLineInput if @io.eof?
|
||||
@line = ''
|
||||
@exp_line_no = @line_no
|
||||
|
||||
|
@ -424,14 +427,30 @@ class RubyLex
|
|||
indent
|
||||
end
|
||||
|
||||
def is_method_calling?(tokens, index)
|
||||
tk = tokens[index]
|
||||
if tk[3].anybits?(Ripper::EXPR_CMDARG) and tk[1] == :on_ident
|
||||
# The target method call to pass the block with "do".
|
||||
return true
|
||||
elsif tk[3].anybits?(Ripper::EXPR_ARG) and tk[1] == :on_ident
|
||||
non_sp_index = tokens[0..(index - 1)].rindex{ |t| t[1] != :on_sp }
|
||||
if non_sp_index
|
||||
prev_tk = tokens[non_sp_index]
|
||||
if prev_tk[3].anybits?(Ripper::EXPR_DOT) and prev_tk[1] == :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 correnponding to "do".
|
||||
index.downto(0) do |i|
|
||||
tk = tokens[i]
|
||||
# In "continue", the token isn't the corresponding syntax to "do".
|
||||
#is_continue = process_continue(@tokens[0..(i - 1)])
|
||||
# continue ではなく、直前に (:on_ignored_nl|:on_nl|:on_comment):on_sp* みたいなのがあるかどうかを調べる
|
||||
non_sp_index = tokens[0..(i - 1)].rindex{ |t| t[1] != :on_sp }
|
||||
first_in_fomula = false
|
||||
if non_sp_index.nil?
|
||||
|
@ -439,8 +458,7 @@ class RubyLex
|
|||
elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index][1])
|
||||
first_in_fomula = true
|
||||
end
|
||||
if tk[3].anybits?(Ripper::EXPR_CMDARG) and tk[1] == :on_ident
|
||||
# The target method call to pass the block with "do".
|
||||
if is_method_calling?(tokens, i)
|
||||
syntax_of_do = :method_calling
|
||||
break if first_in_fomula
|
||||
elsif tk[1] == :on_kw && %w{while until for}.include?(tk[2])
|
||||
|
@ -458,6 +476,34 @@ class RubyLex
|
|||
syntax_of_do
|
||||
end
|
||||
|
||||
def is_the_in_correspond_to_a_for(tokens, index)
|
||||
syntax_of_in = nil
|
||||
# Finding a syntax correnponding 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[1] != :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][1])
|
||||
first_in_fomula = true
|
||||
end
|
||||
if tk[1] == :on_kw && tk[2] == '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
|
||||
|
@ -513,8 +559,12 @@ class RubyLex
|
|||
unless t[3].allbits?(Ripper::EXPR_LABEL)
|
||||
depth_difference += 1
|
||||
end
|
||||
when 'else', 'elsif', 'ensure', 'when', 'in'
|
||||
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
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
|
||||
module IRB # :nodoc:
|
||||
VERSION = "1.3.2"
|
||||
VERSION = "1.3.3"
|
||||
@RELEASE_VERSION = VERSION
|
||||
@LAST_UPDATE_DATE = "2021-01-18"
|
||||
@LAST_UPDATE_DATE = "2021-02-07"
|
||||
end
|
||||
|
|
|
@ -243,6 +243,7 @@ module Reline
|
|||
loop do
|
||||
prev_pasting_state = Reline::IOGate.in_pasting?
|
||||
read_io(config.keyseq_timeout) { |inputs|
|
||||
line_editor.set_pasting_state(Reline::IOGate.in_pasting?)
|
||||
inputs.each { |c|
|
||||
line_editor.input_key(c)
|
||||
line_editor.rerender
|
||||
|
@ -253,6 +254,7 @@ module Reline
|
|||
end
|
||||
}
|
||||
if prev_pasting_state == true and not Reline::IOGate.in_pasting? and not line_editor.finished?
|
||||
line_editor.set_pasting_state(false)
|
||||
prev_pasting_state = false
|
||||
line_editor.rerender_all
|
||||
end
|
||||
|
|
|
@ -58,13 +58,17 @@ class Reline::LineEditor
|
|||
reset_variables(encoding: encoding)
|
||||
end
|
||||
|
||||
def set_pasting_state(in_pasting)
|
||||
@in_pasting = in_pasting
|
||||
end
|
||||
|
||||
def simplified_rendering?
|
||||
if finished?
|
||||
false
|
||||
elsif @just_cursor_moving and not @rerender_all
|
||||
true
|
||||
else
|
||||
not @rerender_all and not finished? and Reline::IOGate.in_pasting?
|
||||
not @rerender_all and not finished? and @in_pasting
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -146,6 +150,13 @@ class Reline::LineEditor
|
|||
@screen_height = @screen_size.first
|
||||
reset_variables(prompt, encoding: encoding)
|
||||
@old_trap = Signal.trap('SIGINT') {
|
||||
if @scroll_partial_screen
|
||||
move_cursor_down(@screen_height - (@line_index - @scroll_partial_screen) - 1)
|
||||
else
|
||||
move_cursor_down(@highest_in_all - @line_index - 1)
|
||||
end
|
||||
Reline::IOGate.move_cursor_column(0)
|
||||
scroll_down(1)
|
||||
@old_trap.call if @old_trap.respond_to?(:call) # can also be string, ex: "DEFAULT"
|
||||
raise Interrupt
|
||||
}
|
||||
|
@ -227,6 +238,8 @@ class Reline::LineEditor
|
|||
@scroll_partial_screen = nil
|
||||
@prev_mode_string = nil
|
||||
@drop_terminate_spaces = false
|
||||
@in_pasting = false
|
||||
@auto_indent_proc = nil
|
||||
reset_line
|
||||
end
|
||||
|
||||
|
@ -375,11 +388,29 @@ class Reline::LineEditor
|
|||
@cleared = false
|
||||
return
|
||||
end
|
||||
if @is_multiline and finished? and @scroll_partial_screen
|
||||
# Re-output all code higher than the screen when finished.
|
||||
Reline::IOGate.move_cursor_up(@first_line_started_from + @started_from - @scroll_partial_screen)
|
||||
Reline::IOGate.move_cursor_column(0)
|
||||
@scroll_partial_screen = nil
|
||||
prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt)
|
||||
if @previous_line_index
|
||||
new_lines = whole_lines(index: @previous_line_index, line: @line)
|
||||
else
|
||||
new_lines = whole_lines
|
||||
end
|
||||
modify_lines(new_lines).each_with_index do |line, index|
|
||||
@output.write "#{prompt_list ? prompt_list[index] : prompt}#{line}\n"
|
||||
Reline::IOGate.erase_after_cursor
|
||||
end
|
||||
@output.flush
|
||||
return
|
||||
end
|
||||
new_highest_in_this = calculate_height_by_width(prompt_width + calculate_width(@line.nil? ? '' : @line))
|
||||
# FIXME: end of logical line sometimes breaks
|
||||
rendered = false
|
||||
if @add_newline_to_end_of_buffer
|
||||
rerender_added_newline
|
||||
rerender_added_newline(prompt, prompt_width)
|
||||
@add_newline_to_end_of_buffer = false
|
||||
else
|
||||
if @just_cursor_moving and not @rerender_all
|
||||
|
@ -397,20 +428,32 @@ class Reline::LineEditor
|
|||
else
|
||||
end
|
||||
end
|
||||
line = modify_lines(whole_lines)[@line_index]
|
||||
if @is_multiline
|
||||
prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt)
|
||||
if finished?
|
||||
# Always rerender on finish because output_modifier_proc may return a different output.
|
||||
if @previous_line_index
|
||||
new_lines = whole_lines(index: @previous_line_index, line: @line)
|
||||
else
|
||||
new_lines = whole_lines
|
||||
end
|
||||
line = modify_lines(new_lines)[@line_index]
|
||||
prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines, prompt)
|
||||
render_partial(prompt, prompt_width, line, @first_line_started_from)
|
||||
move_cursor_down(@highest_in_all - (@first_line_started_from + @highest_in_this - 1) - 1)
|
||||
scroll_down(1)
|
||||
Reline::IOGate.move_cursor_column(0)
|
||||
Reline::IOGate.erase_after_cursor
|
||||
elsif not rendered
|
||||
render_partial(prompt, prompt_width, line, @first_line_started_from)
|
||||
unless @in_pasting
|
||||
line = modify_lines(whole_lines)[@line_index]
|
||||
prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt)
|
||||
render_partial(prompt, prompt_width, line, @first_line_started_from)
|
||||
end
|
||||
end
|
||||
@buffer_of_lines[@line_index] = @line
|
||||
@rest_height = 0 if @scroll_partial_screen
|
||||
else
|
||||
line = modify_lines(whole_lines)[@line_index]
|
||||
render_partial(prompt, prompt_width, line, 0)
|
||||
if finished?
|
||||
scroll_down(1)
|
||||
|
@ -453,13 +496,13 @@ class Reline::LineEditor
|
|||
end
|
||||
end
|
||||
|
||||
private def rerender_added_newline
|
||||
private def rerender_added_newline(prompt, prompt_width)
|
||||
scroll_down(1)
|
||||
new_lines = whole_lines(index: @previous_line_index, line: @line)
|
||||
prompt, prompt_width, = check_multiline_prompt(new_lines, prompt)
|
||||
@buffer_of_lines[@previous_line_index] = @line
|
||||
@line = @buffer_of_lines[@line_index]
|
||||
render_partial(prompt, prompt_width, @line, @first_line_started_from + @started_from + 1, with_control: false)
|
||||
unless @in_pasting
|
||||
render_partial(prompt, prompt_width, @line, @first_line_started_from + @started_from + 1, with_control: false)
|
||||
end
|
||||
@cursor = @cursor_max = calculate_width(@line)
|
||||
@byte_pointer = @line.bytesize
|
||||
@highest_in_all += @highest_in_this
|
||||
|
@ -568,7 +611,13 @@ class Reline::LineEditor
|
|||
new_first_line_started_from = calculate_height_by_lines(new_buffer[0..(@line_index - 1)], prompt_list || prompt)
|
||||
end
|
||||
new_started_from = calculate_height_by_width(prompt_width + @cursor) - 1
|
||||
if back > old_highest_in_all
|
||||
calculate_scroll_partial_screen(back, new_first_line_started_from + new_started_from)
|
||||
if @scroll_partial_screen
|
||||
move_cursor_up(@first_line_started_from + @started_from)
|
||||
scroll_down(@screen_height - 1)
|
||||
move_cursor_up(@screen_height)
|
||||
Reline::IOGate.move_cursor_column(0)
|
||||
elsif back > old_highest_in_all
|
||||
scroll_down(back - 1)
|
||||
move_cursor_up(back - 1)
|
||||
elsif back < old_highest_in_all
|
||||
|
@ -580,7 +629,6 @@ class Reline::LineEditor
|
|||
end
|
||||
move_cursor_up(old_highest_in_all - 1)
|
||||
end
|
||||
calculate_scroll_partial_screen(back, new_first_line_started_from + new_started_from)
|
||||
render_whole_lines(new_buffer, prompt_list || prompt, prompt_width)
|
||||
if @prompt_proc
|
||||
prompt = prompt_list[@line_index]
|
||||
|
@ -666,8 +714,8 @@ class Reline::LineEditor
|
|||
@highest_in_this = height
|
||||
end
|
||||
move_cursor_up(@started_from)
|
||||
cursor_up_from_last_line = height - 1 - @started_from
|
||||
@started_from = calculate_height_by_width(prompt_width + @cursor) - 1
|
||||
cursor_up_from_last_line = height - 1 - @started_from
|
||||
end
|
||||
if Reline::Unicode::CSI_REGEXP.match?(prompt + line_to_render)
|
||||
@output.write "\e[0m" # clear character decorations
|
||||
|
@ -1082,7 +1130,7 @@ class Reline::LineEditor
|
|||
unless completion_occurs
|
||||
@completion_state = CompletionState::NORMAL
|
||||
end
|
||||
if not Reline::IOGate.in_pasting? and @just_cursor_moving.nil?
|
||||
if not @in_pasting and @just_cursor_moving.nil?
|
||||
if @previous_line_index and @buffer_of_lines[@previous_line_index] == @line
|
||||
@just_cursor_moving = true
|
||||
elsif @previous_line_index.nil? and @buffer_of_lines[@line_index] == @line and old_line == @line
|
||||
|
@ -1286,7 +1334,11 @@ class Reline::LineEditor
|
|||
if @buffer_of_lines.size == 1 and @line.nil?
|
||||
nil
|
||||
else
|
||||
whole_lines.join("\n")
|
||||
if @previous_line_index
|
||||
whole_lines(index: @previous_line_index, line: @line).join("\n")
|
||||
else
|
||||
whole_lines.join("\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1332,14 +1384,14 @@ class Reline::LineEditor
|
|||
cursor_line = @line.byteslice(0, @byte_pointer)
|
||||
insert_new_line(cursor_line, next_line)
|
||||
@cursor = 0
|
||||
@check_new_auto_indent = true unless Reline::IOGate.in_pasting?
|
||||
@check_new_auto_indent = true unless @in_pasting
|
||||
end
|
||||
end
|
||||
|
||||
private def ed_unassigned(key) end # do nothing
|
||||
|
||||
private def process_insert(force: false)
|
||||
return if @continuous_insertion_buffer.empty? or (Reline::IOGate.in_pasting? and not force)
|
||||
return if @continuous_insertion_buffer.empty? or (@in_pasting and not force)
|
||||
width = Reline::Unicode.calculate_width(@continuous_insertion_buffer)
|
||||
bytesize = @continuous_insertion_buffer.bytesize
|
||||
if @cursor == @cursor_max
|
||||
|
@ -1374,7 +1426,7 @@ class Reline::LineEditor
|
|||
str = key.chr
|
||||
bytesize = 1
|
||||
end
|
||||
if Reline::IOGate.in_pasting?
|
||||
if @in_pasting
|
||||
@continuous_insertion_buffer << str
|
||||
return
|
||||
elsif not @continuous_insertion_buffer.empty?
|
||||
|
@ -2424,11 +2476,23 @@ class Reline::LineEditor
|
|||
|
||||
private def vi_histedit(key)
|
||||
path = Tempfile.open { |fp|
|
||||
fp.write @line
|
||||
if @is_multiline
|
||||
fp.write whole_lines.join("\n")
|
||||
else
|
||||
fp.write @line
|
||||
end
|
||||
fp.path
|
||||
}
|
||||
system("#{ENV['EDITOR']} #{path}")
|
||||
@line = File.read(path)
|
||||
if @is_multiline
|
||||
@buffer_of_lines = File.read(path).split("\n")
|
||||
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
||||
@line_index = 0
|
||||
@line = @buffer_of_lines[@line_index]
|
||||
@rerender_all = true
|
||||
else
|
||||
@line = File.read(path)
|
||||
end
|
||||
finish
|
||||
end
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module Reline
|
||||
VERSION = '0.2.2'
|
||||
VERSION = '0.2.3'
|
||||
end
|
||||
|
|
|
@ -275,5 +275,98 @@ module TestIRB
|
|||
assert_empty err
|
||||
assert_match(/\A=> 3\nCUSTOM is added\.\n=> nil\ncustom processing time: .+\n=> 3\n=> nil\n=> 3\n/, out)
|
||||
end
|
||||
|
||||
def test_measure_with_proc
|
||||
IRB.init_config(nil)
|
||||
IRB.conf[:PROMPT] = {
|
||||
DEFAULT: {
|
||||
PROMPT_I: '> ',
|
||||
PROMPT_S: '> ',
|
||||
PROMPT_C: '> ',
|
||||
PROMPT_N: '> '
|
||||
}
|
||||
}
|
||||
IRB.conf[:VERBOSE] = false
|
||||
IRB.conf[:PROMPT_MODE] = :DEFAULT
|
||||
IRB.conf[:MEASURE] = false
|
||||
input = TestInputMethod.new([
|
||||
"3\n",
|
||||
"measure { |context, code, line_no, &block|\n",
|
||||
" result = block.()\n",
|
||||
" puts 'aaa' if IRB.conf[:MEASURE]\n",
|
||||
" result\n",
|
||||
"}\n",
|
||||
"3\n",
|
||||
"measure { |context, code, line_no, &block|\n",
|
||||
" result = block.()\n",
|
||||
" puts 'bbb' if IRB.conf[:MEASURE]\n",
|
||||
" result\n",
|
||||
"}\n",
|
||||
"3\n",
|
||||
"measure :off\n",
|
||||
"3\n",
|
||||
])
|
||||
c = Class.new(Object)
|
||||
irb = IRB::Irb.new(IRB::WorkSpace.new(c.new), input)
|
||||
irb.context.return_format = "=> %s\n"
|
||||
out, err = capture_output do
|
||||
irb.eval_input
|
||||
end
|
||||
assert_empty err
|
||||
assert_match(/\A=> 3\nBLOCK is added\.\n=> nil\naaa\n=> 3\nBLOCK is added.\naaa\n=> nil\nbbb\n=> 3\n=> nil\n=> 3\n/, out)
|
||||
assert_empty(c.class_variables)
|
||||
end
|
||||
|
||||
def test_irb_source
|
||||
IRB.init_config(nil)
|
||||
File.write("#{@tmpdir}/a.rb", "a = 'hi'\n")
|
||||
input = TestInputMethod.new([
|
||||
"a = 'bug17564'\n",
|
||||
"a\n",
|
||||
"irb_source '#{@tmpdir}/a.rb'\n",
|
||||
"a\n",
|
||||
])
|
||||
IRB.conf[:VERBOSE] = false
|
||||
IRB.conf[:PROMPT_MODE] = :SIMPLE
|
||||
irb = IRB::Irb.new(IRB::WorkSpace.new(self), input)
|
||||
IRB.conf[:MAIN_CONTEXT] = irb.context
|
||||
out, err = capture_output do
|
||||
irb.eval_input
|
||||
end
|
||||
assert_empty err
|
||||
assert_pattern_list([
|
||||
/=> "bug17564"\n/,
|
||||
/=> "bug17564"\n/,
|
||||
/ => "hi"\n/,
|
||||
/ => nil\n/,
|
||||
/=> "hi"\n/,
|
||||
], out)
|
||||
end
|
||||
|
||||
def test_irb_load
|
||||
IRB.init_config(nil)
|
||||
File.write("#{@tmpdir}/a.rb", "a = 'hi'\n")
|
||||
input = TestInputMethod.new([
|
||||
"a = 'bug17564'\n",
|
||||
"a\n",
|
||||
"irb_load '#{@tmpdir}/a.rb'\n",
|
||||
"a\n",
|
||||
])
|
||||
IRB.conf[:VERBOSE] = false
|
||||
IRB.conf[:PROMPT_MODE] = :SIMPLE
|
||||
irb = IRB::Irb.new(IRB::WorkSpace.new(self), input)
|
||||
IRB.conf[:MAIN_CONTEXT] = irb.context
|
||||
out, err = capture_output do
|
||||
irb.eval_input
|
||||
end
|
||||
assert_empty err
|
||||
assert_pattern_list([
|
||||
/=> "bug17564"\n/,
|
||||
/=> "bug17564"\n/,
|
||||
/ => "hi"\n/,
|
||||
/ => nil\n/,
|
||||
/=> "bug17564"\n/,
|
||||
], out)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# frozen_string_literal: false
|
||||
require 'test/unit'
|
||||
require 'irb/color'
|
||||
require 'irb/color_printer'
|
||||
require 'rubygems'
|
||||
require 'stringio'
|
||||
|
||||
|
@ -153,23 +152,6 @@ module TestIRB
|
|||
end
|
||||
end
|
||||
|
||||
IRBTestColorPrinter = Struct.new(:a)
|
||||
|
||||
def test_color_printer
|
||||
unless ripper_lexer_scan_supported?
|
||||
skip 'Ripper::Lexer#scan is supported in Ruby 2.7+'
|
||||
end
|
||||
{
|
||||
1 => "#{BLUE}#{BOLD}1#{CLEAR}\n",
|
||||
IRBTestColorPrinter.new('test') => "#{GREEN}#<struct TestIRB::TestColor::IRBTestColorPrinter#{CLEAR} a#{GREEN}=#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{RED}test#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{GREEN}>#{CLEAR}\n",
|
||||
Ripper::Lexer.new('1').scan => "[#{GREEN}#<Ripper::Lexer::Elem:#{CLEAR} on_int@1:0 END token: #{RED}#{BOLD}\"#{CLEAR}#{RED}1#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{GREEN}>#{CLEAR}]\n",
|
||||
Class.new{define_method(:pretty_print){|q| q.text("[__FILE__, __LINE__, __ENCODING__]")}}.new => "[#{CYAN}#{BOLD}__FILE__#{CLEAR}, #{CYAN}#{BOLD}__LINE__#{CLEAR}, #{CYAN}#{BOLD}__ENCODING__#{CLEAR}]\n",
|
||||
}.each do |object, result|
|
||||
actual = with_term { IRB::ColorPrinter.pp(object, '') }
|
||||
assert_equal(result, actual, "Case: IRB::ColorPrinter.pp(#{object.inspect}, '')")
|
||||
end
|
||||
end
|
||||
|
||||
def test_inspect_colorable
|
||||
{
|
||||
1 => true,
|
||||
|
@ -202,10 +184,6 @@ module TestIRB
|
|||
Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0')
|
||||
end
|
||||
|
||||
def ripper_lexer_scan_supported?
|
||||
Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0')
|
||||
end
|
||||
|
||||
def with_term
|
||||
stdout = $stdout
|
||||
io = StringIO.new
|
||||
|
|
67
test/irb/test_color_printer.rb
Normal file
67
test/irb/test_color_printer.rb
Normal file
|
@ -0,0 +1,67 @@
|
|||
# frozen_string_literal: false
|
||||
require 'test/unit'
|
||||
require 'irb/color_printer'
|
||||
require 'rubygems'
|
||||
require 'stringio'
|
||||
|
||||
module TestIRB
|
||||
class TestColorPrinter < Test::Unit::TestCase
|
||||
CLEAR = "\e[0m"
|
||||
BOLD = "\e[1m"
|
||||
RED = "\e[31m"
|
||||
GREEN = "\e[32m"
|
||||
BLUE = "\e[34m"
|
||||
CYAN = "\e[36m"
|
||||
|
||||
def setup
|
||||
@get_screen_size = Reline.method(:get_screen_size)
|
||||
Reline.instance_eval { undef :get_screen_size }
|
||||
def Reline.get_screen_size
|
||||
[36, 80]
|
||||
end
|
||||
end
|
||||
|
||||
def teardown
|
||||
Reline.instance_eval { undef :get_screen_size }
|
||||
Reline.define_singleton_method(:get_screen_size, @get_screen_size)
|
||||
end
|
||||
|
||||
IRBTestColorPrinter = Struct.new(:a)
|
||||
|
||||
def test_color_printer
|
||||
unless ripper_lexer_scan_supported?
|
||||
skip 'Ripper::Lexer#scan is supported in Ruby 2.7+'
|
||||
end
|
||||
{
|
||||
1 => "#{BLUE}#{BOLD}1#{CLEAR}\n",
|
||||
IRBTestColorPrinter.new('test') => "#{GREEN}#<struct TestIRB::TestColorPrinter::IRBTestColorPrinter#{CLEAR} a#{GREEN}=#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{RED}test#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{GREEN}>#{CLEAR}\n",
|
||||
Ripper::Lexer.new('1').scan => "[#{GREEN}#<Ripper::Lexer::Elem:#{CLEAR} on_int@1:0 END token: #{RED}#{BOLD}\"#{CLEAR}#{RED}1#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{GREEN}>#{CLEAR}]\n",
|
||||
Class.new{define_method(:pretty_print){|q| q.text("[__FILE__, __LINE__, __ENCODING__]")}}.new => "[#{CYAN}#{BOLD}__FILE__#{CLEAR}, #{CYAN}#{BOLD}__LINE__#{CLEAR}, #{CYAN}#{BOLD}__ENCODING__#{CLEAR}]\n",
|
||||
}.each do |object, result|
|
||||
actual = with_term { IRB::ColorPrinter.pp(object, '') }
|
||||
assert_equal(result, actual, "Case: IRB::ColorPrinter.pp(#{object.inspect}, '')")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ripper_lexer_scan_supported?
|
||||
Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0')
|
||||
end
|
||||
|
||||
def with_term
|
||||
stdout = $stdout
|
||||
io = StringIO.new
|
||||
def io.tty?; true; end
|
||||
$stdout = io
|
||||
|
||||
env = ENV.to_h.dup
|
||||
ENV['TERM'] = 'xterm-256color'
|
||||
|
||||
yield
|
||||
ensure
|
||||
$stdout = stdout
|
||||
ENV.replace(env) if env
|
||||
end
|
||||
end
|
||||
end
|
|
@ -42,6 +42,17 @@ module TestIRB
|
|||
IRB.conf[:VERBOSE] = false
|
||||
workspace = IRB::WorkSpace.new(Object.new)
|
||||
@context = IRB::Context.new(nil, workspace, TestInputMethod.new)
|
||||
|
||||
@get_screen_size = Reline.method(:get_screen_size)
|
||||
Reline.instance_eval { undef :get_screen_size }
|
||||
def Reline.get_screen_size
|
||||
[36, 80]
|
||||
end
|
||||
end
|
||||
|
||||
def teardown
|
||||
Reline.instance_eval { undef :get_screen_size }
|
||||
Reline.define_singleton_method(:get_screen_size, @get_screen_size)
|
||||
end
|
||||
|
||||
def test_last_value
|
||||
|
@ -447,7 +458,7 @@ module TestIRB
|
|||
irb.eval_input
|
||||
end
|
||||
assert_empty err
|
||||
if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0'
|
||||
if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
|
||||
expected = [
|
||||
:*, /Traceback \(most recent call last\):\n/,
|
||||
:*, /\t 2: from \(irb\):1:in `<main>'\n/,
|
||||
|
@ -477,7 +488,7 @@ module TestIRB
|
|||
irb.eval_input
|
||||
end
|
||||
assert_empty err
|
||||
if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0'
|
||||
if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
|
||||
expected = [
|
||||
:*, /Traceback \(most recent call last\):\n/,
|
||||
:*, /\t 2: from \(irb\):1:in `<main>'\n/,
|
||||
|
@ -513,7 +524,7 @@ module TestIRB
|
|||
irb.eval_input
|
||||
end
|
||||
assert_empty err
|
||||
if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0'
|
||||
if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
|
||||
expected = [
|
||||
:*, /Traceback \(most recent call last\):\n/,
|
||||
:*, /\t... 5 levels...\n/,
|
||||
|
@ -561,5 +572,26 @@ module TestIRB
|
|||
ensure
|
||||
$VERBOSE = verbose
|
||||
end
|
||||
|
||||
def test_lineno
|
||||
input = TestInputMethod.new([
|
||||
"\n",
|
||||
"__LINE__\n",
|
||||
"__LINE__\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"__LINE__\n",
|
||||
])
|
||||
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
|
||||
out, err = capture_output do
|
||||
irb.eval_input
|
||||
end
|
||||
assert_empty err
|
||||
assert_pattern_list([
|
||||
:*, /\b2\n/,
|
||||
:*, /\b3\n/,
|
||||
:*, /\b6\n/,
|
||||
], out)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -333,6 +333,102 @@ module TestIRB
|
|||
end
|
||||
end
|
||||
|
||||
def test_corresponding_syntax_to_keyword_for
|
||||
input_with_correct_indents = [
|
||||
Row.new(%q(for i in [1]), nil, 2, 1),
|
||||
Row.new(%q( puts i), nil, 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
|
||||
|
||||
def test_corresponding_syntax_to_keyword_for_with_do
|
||||
input_with_correct_indents = [
|
||||
Row.new(%q(for i in [1] do), nil, 2, 1),
|
||||
Row.new(%q( puts i), nil, 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
|
||||
|
||||
def test_bracket_corresponding_to_times
|
||||
input_with_correct_indents = [
|
||||
Row.new(%q(3.times { |i|), nil, 2, 1),
|
||||
Row.new(%q( puts i), nil, 2, 1),
|
||||
Row.new(%q(}), 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
|
||||
|
||||
def test_do_corresponding_to_times
|
||||
input_with_correct_indents = [
|
||||
Row.new(%q(3.times do |i|), nil, 2, 1),
|
||||
#Row.new(%q( puts i), nil, 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
|
||||
|
||||
def test_bracket_corresponding_to_loop
|
||||
input_with_correct_indents = [
|
||||
Row.new(%q(loop {), nil, 2, 1),
|
||||
Row.new(%q( 3), nil, 2, 1),
|
||||
Row.new(%q(}), 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
|
||||
|
||||
def test_do_corresponding_to_loop
|
||||
input_with_correct_indents = [
|
||||
Row.new(%q(loop do), nil, 2, 1),
|
||||
Row.new(%q( 3), nil, 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
|
||||
|
||||
def test_heredoc_with_indent
|
||||
input_with_correct_indents = [
|
||||
Row.new(%q(<<~Q), nil, 0, 0),
|
||||
|
|
|
@ -678,6 +678,34 @@ begin
|
|||
EOC
|
||||
end
|
||||
|
||||
def test_autowrap_in_the_middle_of_a_line
|
||||
start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl}, startup_message: 'Multiline REPL.')
|
||||
write("def abcdefg; end\C-b\C-b\C-b\C-b\C-b")
|
||||
%w{h i}.each do |c|
|
||||
write(c)
|
||||
end
|
||||
close
|
||||
assert_screen(<<~EOC)
|
||||
Multiline REPL.
|
||||
prompt> def abcdefgh
|
||||
i; end
|
||||
EOC
|
||||
end
|
||||
|
||||
def test_terminate_in_the_middle_of_lines
|
||||
start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl}, startup_message: 'Multiline REPL.')
|
||||
write("def hoge\n 1\n 2\n 3\n 4\nend\n")
|
||||
write("\C-p\C-p\C-p\C-e\n")
|
||||
close
|
||||
assert_screen(<<~EOC)
|
||||
prompt> 3
|
||||
prompt> 4
|
||||
prompt> end
|
||||
=> :hoge
|
||||
prompt>
|
||||
EOC
|
||||
end
|
||||
|
||||
private def write_inputrc(content)
|
||||
File.open(@inputrc_file, 'w') do |f|
|
||||
f.write content
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue