Skip to content

Commit

Permalink
Change quoted_insert and bracketed_paste to a single key input (#792)
Browse files Browse the repository at this point in the history
  • Loading branch information
tompng authored Dec 16, 2024
1 parent cdd7288 commit 8f331ed
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 46 deletions.
13 changes: 7 additions & 6 deletions lib/reline.rb
Original file line number Diff line number Diff line change
Expand Up @@ -343,13 +343,14 @@ def readline(prompt = '', add_hist = false)
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?
Expand Down
14 changes: 14 additions & 0 deletions lib/reline/io.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ def win?
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

Expand Down
20 changes: 10 additions & 10 deletions lib/reline/key_actor/vi_insert.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 ;
Expand Down
29 changes: 11 additions & 18 deletions lib/reline/line_editor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,7 @@ def wrap_method_call(method_symbol, method_obj, key, with_operator = false)
@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)
Expand Down Expand Up @@ -1004,7 +1005,7 @@ def wrap_method_call(method_symbol, method_obj, key, with_operator = false)
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)
Expand All @@ -1015,9 +1016,7 @@ def wrap_method_call(method_symbol, method_obj, key, with_operator = false)
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
Expand Down Expand Up @@ -1227,15 +1226,13 @@ def confirm_multiline_termination
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)
lines << '' if lines.empty?
@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)
Expand Down Expand Up @@ -1419,20 +1416,16 @@ def finish
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)
Expand Down
6 changes: 3 additions & 3 deletions test/reline/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
26 changes: 21 additions & 5 deletions test/reline/test_key_actor_emacs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,25 @@ def test_em_delete_prev_char_for_mbchar_by_plural_code_points
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
Expand Down Expand Up @@ -1474,7 +1488,9 @@ def test_ed_search_prev_next_history_in_multibyte
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

Expand Down
12 changes: 8 additions & 4 deletions test/reline/test_key_actor_vi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -344,13 +344,17 @@ def test_vi_end_big_word
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
Expand Down

0 comments on commit 8f331ed

Please sign in to comment.