[ruby/reline] Correct padding space calculation

fix https://github.com/ruby/irb/issues/308

This bug occurred when `dialog.width - calculate_width(s, true)` was negative.

When `dialog.width` is shorter than `old_dialog.width`, it calculates how much padding it has to do. However, there are cases where `s` is longer than `dialog.width`, as in the issue. In that case, `padding_space_with_escape_sequences` will crash.

Here, `old_dialog.width` is longer than `dialog.width`, so I changed the padding width to `old_dialog.width - dialog.width`.

https://github.com/ruby/reline/commit/c581c31e0f
This commit is contained in:
ima1zumi 2021-11-17 00:58:43 +09:00 committed by git
parent feda058531
commit f5829e2935
3 changed files with 39 additions and 1 deletions

View File

@ -858,7 +858,8 @@ class Reline::LineEditor
s = ' ' * width
else
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column + dialog.width, width)
s = padding_space_with_escape_sequences(s, dialog.width)
rerender_width = old_dialog.width - dialog.width
s = padding_space_with_escape_sequences(s, rerender_width)
end
Reline::IOGate.move_cursor_column(dialog.column + dialog.width)
@output.write "\e[0m#{s}\e[0m"

View File

@ -137,6 +137,28 @@ opt.on('--autocomplete-super-long') {
2000.times.map{ s = "Str_#{c}"; c.succ!; s }.select{ |c| c.start_with?(target) }
}
}
opt.on('--autocomplete-width-long') {
Reline.autocompletion = true
Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
%w{
remove_instance_variable
respond_to?
ruby2_keywords
rand
readline
readlines
require
require_relative
raise
respond_to_missing?
redo
rescue
retry
return
}.select{ |c| c.start_with?(target) }
}
}
opt.parse!(ARGV)
begin

View File

@ -1172,6 +1172,21 @@ begin
EOC
end
def test_autocomplete_old_dialog_width_greater_than_dialog_width
start_terminal(40, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-width-long}, startup_message: 'Multiline REPL.')
write("0+ \n12345678901234")
write("\C-p")
write("r")
write("a")
close
assert_screen(<<~'EOC')
Multiline REPL.
prompt> 0+ ra
prompt> 123rand 901234
raise
EOC
end
def write_inputrc(content)
File.open(@inputrc_file, 'w') do |f|
f.write content