[ruby/reline] Change quoted_insert and bracketed_paste to a single

key input
(https://github.com/ruby/reline/pull/792)

https://github.com/ruby/reline/commit/8f331edb07
This commit is contained in:
tomoya ishida 2024-12-16 22:53:30 +09:00 committed by git
parent 3c9f3c3e9b
commit 4428c51f01
7 changed files with 74 additions and 46 deletions

View File

@ -343,13 +343,14 @@ module Reline
read_io(config.keyseq_timeout) { |inputs|
line_editor.set_pasting_state(io_gate.in_pasting?)
inputs.each do |key|
if key.method_symbol == :bracketed_paste_start
text = io_gate.read_bracketed_paste
line_editor.insert_multiline_text(text)
line_editor.scroll_into_view
else
line_editor.update(key)
case key.method_symbol
when :bracketed_paste_start
# io_gate is Reline::ANSI because the key :bracketed_paste_start is only assigned in Reline::ANSI
key = Reline::Key.new(io_gate.read_bracketed_paste, :insert_multiline_text)
when :quoted_insert, :ed_quoted_insert
key = Reline::Key.new(io_gate.read_single_char(config.keyseq_timeout), :insert_raw_char)
end
line_editor.update(key)
end
}
if line_editor.finished?

View File

@ -35,6 +35,20 @@ module Reline
def reset_color_sequence
self.class::RESET_COLOR
end
# Read a single encoding valid character from the input.
def read_single_char(keyseq_timeout)
buffer = String.new(encoding: Encoding::ASCII_8BIT)
loop do
timeout = buffer.empty? ? Float::INFINITY : keyseq_timeout
c = getc(timeout)
return unless c
buffer << c
encoded = buffer.dup.force_encoding(encoding)
return encoded if encoded.valid_encoding?
end
end
end
end

View File

@ -97,25 +97,25 @@ module Reline::KeyActor
# 47 /
:ed_insert,
# 48 0
:ed_insert,
:ed_digit,
# 49 1
:ed_insert,
:ed_digit,
# 50 2
:ed_insert,
:ed_digit,
# 51 3
:ed_insert,
:ed_digit,
# 52 4
:ed_insert,
:ed_digit,
# 53 5
:ed_insert,
:ed_digit,
# 54 6
:ed_insert,
:ed_digit,
# 55 7
:ed_insert,
:ed_digit,
# 56 8
:ed_insert,
:ed_digit,
# 57 9
:ed_insert,
:ed_digit,
# 58 :
:ed_insert,
# 59 ;

View File

@ -973,6 +973,7 @@ class Reline::LineEditor
@drop_terminate_spaces = false
end
ARGUMENT_DIGIT_METHODS = %i[ed_digit vi_zero ed_argument_digit]
VI_WAITING_ACCEPT_METHODS = %i[vi_change_meta vi_delete_meta vi_yank ed_insert ed_argument_digit]
private def process_key(key, method_symbol)
@ -1004,7 +1005,7 @@ class Reline::LineEditor
method_obj = method(method_symbol)
end
if @vi_arg
if key.match?(/\A\d\z/)
if ARGUMENT_DIGIT_METHODS.include?(method_symbol)
ed_argument_digit(key)
else
if argumentable?(method_obj)
@ -1015,9 +1016,7 @@ class Reline::LineEditor
wrap_method_call(method_symbol, method_obj, key)
end
@kill_ring.process
if @vi_arg
@vi_arg = nil
end
@vi_arg = nil
end
elsif method_obj
if method_symbol == :ed_argument_digit
@ -1227,7 +1226,6 @@ class Reline::LineEditor
end
def insert_multiline_text(text)
save_old_buffer
pre = @buffer_of_lines[@line_index].byteslice(0, @byte_pointer)
post = @buffer_of_lines[@line_index].byteslice(@byte_pointer..)
lines = (pre + Reline::Unicode.safe_encode(text, encoding).gsub(/\r\n?/, "\n") + post).split("\n", -1)
@ -1235,7 +1233,6 @@ class Reline::LineEditor
@buffer_of_lines[@line_index, 1] = lines
@line_index += lines.size - 1
@byte_pointer = @buffer_of_lines[@line_index].bytesize - post.bytesize
push_input_lines
end
def insert_text(text)
@ -1419,20 +1416,16 @@ class Reline::LineEditor
alias_method :ed_digit, :ed_insert
alias_method :self_insert, :ed_insert
private def ed_quoted_insert(str, arg: 1)
@waiting_proc = proc { |key|
arg.times do
if key == "\C-j" or key == "\C-m"
key_newline(key)
elsif key != "\0"
# Ignore NUL.
ed_insert(key)
end
private def insert_raw_char(str, arg: 1)
arg.times do
if str == "\C-j" or str == "\C-m"
key_newline(str)
elsif str != "\0"
# Ignore NUL.
ed_insert(str)
end
@waiting_proc = nil
}
end
end
alias_method :quoted_insert, :ed_quoted_insert
private def ed_next_char(key, arg: 1)
byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)

View File

@ -108,9 +108,9 @@ class Reline::TestCase < Test::Unit::TestCase
input
end
def input_key_by_symbol(method_symbol, csi: false)
dummy_char = csi ? "\e[A" : "\C-a"
@line_editor.input_key(Reline::Key.new(dummy_char, method_symbol, false))
def input_key_by_symbol(method_symbol, char: nil, csi: false)
char ||= csi ? "\e[A" : "\C-a"
@line_editor.input_key(Reline::Key.new(char, method_symbol, false))
end
def input_keys(input, convert = true)

View File

@ -138,11 +138,25 @@ class Reline::KeyActor::EmacsTest < Reline::TestCase
assert_line_around_cursor("\u3099", '')
end
def test_bracketed_paste_insert
set_line_around_cursor('A', 'Z')
input_key_by_symbol(:insert_multiline_text, char: "abc\n\C-abc")
assert_whole_lines(['Aabc', "\C-abcZ"])
assert_line_around_cursor("\C-abc", 'Z')
end
def test_ed_quoted_insert
input_keys("ab\C-v\C-acd")
assert_line_around_cursor("ab\C-acd", '')
input_keys("\C-q\C-b")
assert_line_around_cursor("ab\C-acd\C-b", '')
set_line_around_cursor('A', 'Z')
input_key_by_symbol(:insert_raw_char, char: "\C-a")
assert_line_around_cursor("A\C-a", 'Z')
end
def test_ed_quoted_insert_with_vi_arg
input_keys("a\C-[3")
input_key_by_symbol(:insert_raw_char, char: "\C-a")
input_keys("b\C-[4")
input_key_by_symbol(:insert_raw_char, char: '1')
assert_line_around_cursor("a\C-a\C-a\C-ab1111", '')
end
def test_ed_kill_line
@ -1474,7 +1488,9 @@ class Reline::KeyActor::EmacsTest < Reline::TestCase
end
def test_ignore_NUL_by_ed_quoted_insert
input_keys(%Q{"\C-v\C-@"}, false)
input_keys('"')
input_key_by_symbol(:insert_raw_char, char: 0.chr)
input_keys('"')
assert_line_around_cursor('""', '')
end

View File

@ -344,13 +344,17 @@ class Reline::ViInsertTest < Reline::TestCase
end
def test_ed_quoted_insert
input_keys("ab\C-v\C-acd")
assert_line_around_cursor("ab\C-acd", '')
input_keys('ab')
input_key_by_symbol(:insert_raw_char, char: "\C-a")
assert_line_around_cursor("ab\C-a", '')
end
def test_ed_quoted_insert_with_vi_arg
input_keys("ab\C-[3\C-v\C-aacd")
assert_line_around_cursor("a\C-a\C-a\C-abcd", '')
input_keys("ab\C-[3")
input_key_by_symbol(:insert_raw_char, char: "\C-a")
input_keys('4')
input_key_by_symbol(:insert_raw_char, char: '1')
assert_line_around_cursor("a\C-a\C-a\C-a1111", 'b')
end
def test_vi_replace_char