[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| read_io(config.keyseq_timeout) { |inputs|
line_editor.set_pasting_state(io_gate.in_pasting?) line_editor.set_pasting_state(io_gate.in_pasting?)
inputs.each do |key| inputs.each do |key|
if key.method_symbol == :bracketed_paste_start case key.method_symbol
text = io_gate.read_bracketed_paste when :bracketed_paste_start
line_editor.insert_multiline_text(text) # io_gate is Reline::ANSI because the key :bracketed_paste_start is only assigned in Reline::ANSI
line_editor.scroll_into_view key = Reline::Key.new(io_gate.read_bracketed_paste, :insert_multiline_text)
else when :quoted_insert, :ed_quoted_insert
line_editor.update(key) key = Reline::Key.new(io_gate.read_single_char(config.keyseq_timeout), :insert_raw_char)
end end
line_editor.update(key)
end end
} }
if line_editor.finished? if line_editor.finished?

View File

@ -35,6 +35,20 @@ module Reline
def reset_color_sequence def reset_color_sequence
self.class::RESET_COLOR self.class::RESET_COLOR
end 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
end end

View File

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

View File

@ -973,6 +973,7 @@ class Reline::LineEditor
@drop_terminate_spaces = false @drop_terminate_spaces = false
end 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] 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) private def process_key(key, method_symbol)
@ -1004,7 +1005,7 @@ class Reline::LineEditor
method_obj = method(method_symbol) method_obj = method(method_symbol)
end end
if @vi_arg if @vi_arg
if key.match?(/\A\d\z/) if ARGUMENT_DIGIT_METHODS.include?(method_symbol)
ed_argument_digit(key) ed_argument_digit(key)
else else
if argumentable?(method_obj) if argumentable?(method_obj)
@ -1015,10 +1016,8 @@ class Reline::LineEditor
wrap_method_call(method_symbol, method_obj, key) wrap_method_call(method_symbol, method_obj, key)
end end
@kill_ring.process @kill_ring.process
if @vi_arg
@vi_arg = nil @vi_arg = nil
end end
end
elsif method_obj elsif method_obj
if method_symbol == :ed_argument_digit if method_symbol == :ed_argument_digit
wrap_method_call(method_symbol, method_obj, key) wrap_method_call(method_symbol, method_obj, key)
@ -1227,7 +1226,6 @@ class Reline::LineEditor
end end
def insert_multiline_text(text) def insert_multiline_text(text)
save_old_buffer
pre = @buffer_of_lines[@line_index].byteslice(0, @byte_pointer) pre = @buffer_of_lines[@line_index].byteslice(0, @byte_pointer)
post = @buffer_of_lines[@line_index].byteslice(@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) 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 @buffer_of_lines[@line_index, 1] = lines
@line_index += lines.size - 1 @line_index += lines.size - 1
@byte_pointer = @buffer_of_lines[@line_index].bytesize - post.bytesize @byte_pointer = @buffer_of_lines[@line_index].bytesize - post.bytesize
push_input_lines
end end
def insert_text(text) def insert_text(text)
@ -1419,20 +1416,16 @@ class Reline::LineEditor
alias_method :ed_digit, :ed_insert alias_method :ed_digit, :ed_insert
alias_method :self_insert, :ed_insert alias_method :self_insert, :ed_insert
private def ed_quoted_insert(str, arg: 1) private def insert_raw_char(str, arg: 1)
@waiting_proc = proc { |key|
arg.times do arg.times do
if key == "\C-j" or key == "\C-m" if str == "\C-j" or str == "\C-m"
key_newline(key) key_newline(str)
elsif key != "\0" elsif str != "\0"
# Ignore NUL. # Ignore NUL.
ed_insert(key) ed_insert(str)
end end
end end
@waiting_proc = nil
}
end end
alias_method :quoted_insert, :ed_quoted_insert
private def ed_next_char(key, arg: 1) private def ed_next_char(key, arg: 1)
byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer) 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 input
end end
def input_key_by_symbol(method_symbol, csi: false) def input_key_by_symbol(method_symbol, char: nil, csi: false)
dummy_char = csi ? "\e[A" : "\C-a" char ||= csi ? "\e[A" : "\C-a"
@line_editor.input_key(Reline::Key.new(dummy_char, method_symbol, false)) @line_editor.input_key(Reline::Key.new(char, method_symbol, false))
end end
def input_keys(input, convert = true) def input_keys(input, convert = true)

View File

@ -138,11 +138,25 @@ class Reline::KeyActor::EmacsTest < Reline::TestCase
assert_line_around_cursor("\u3099", '') assert_line_around_cursor("\u3099", '')
end 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 def test_ed_quoted_insert
input_keys("ab\C-v\C-acd") set_line_around_cursor('A', 'Z')
assert_line_around_cursor("ab\C-acd", '') input_key_by_symbol(:insert_raw_char, char: "\C-a")
input_keys("\C-q\C-b") assert_line_around_cursor("A\C-a", 'Z')
assert_line_around_cursor("ab\C-acd\C-b", '') 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 end
def test_ed_kill_line def test_ed_kill_line
@ -1474,7 +1488,9 @@ class Reline::KeyActor::EmacsTest < Reline::TestCase
end end
def test_ignore_NUL_by_ed_quoted_insert 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('""', '') assert_line_around_cursor('""', '')
end end

View File

@ -344,13 +344,17 @@ class Reline::ViInsertTest < Reline::TestCase
end end
def test_ed_quoted_insert def test_ed_quoted_insert
input_keys("ab\C-v\C-acd") input_keys('ab')
assert_line_around_cursor("ab\C-acd", '') input_key_by_symbol(:insert_raw_char, char: "\C-a")
assert_line_around_cursor("ab\C-a", '')
end end
def test_ed_quoted_insert_with_vi_arg def test_ed_quoted_insert_with_vi_arg
input_keys("ab\C-[3\C-v\C-aacd") input_keys("ab\C-[3")
assert_line_around_cursor("a\C-a\C-a\C-abcd", '') 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 end
def test_vi_replace_char def test_vi_replace_char