From 0e195aea22a6a743ad15869ce4441288cf4d1ce4 Mon Sep 17 00:00:00 2001 From: tompng Date: Tue, 3 Sep 2024 21:06:44 +0900 Subject: [PATCH 1/2] Fix redisplay/insert_text called from pre_input_hook --- lib/reline.rb | 9 ++++-- test/reline/yamatanooroti/test_rendering.rb | 34 +++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/lib/reline.rb b/lib/reline.rb index b851144627..e636035a33 100644 --- a/lib/reline.rb +++ b/lib/reline.rb @@ -324,14 +324,17 @@ def readline(prompt = '', add_hist = false) line_editor.prompt_proc = prompt_proc line_editor.auto_indent_proc = auto_indent_proc line_editor.dig_perfect_match_proc = dig_perfect_match_proc + + # Readline calls pre_input_hook just after printing the first prompt. + line_editor.print_nomultiline_prompt pre_input_hook&.call + unless Reline::IOGate.dumb? @dialog_proc_list.each_pair do |name_sym, d| line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context) end end - line_editor.print_nomultiline_prompt line_editor.update_dialogs line_editor.rerender @@ -457,8 +460,8 @@ def ambiguous_width def_single_delegator :line_editor, :byte_pointer, :point def_single_delegator :line_editor, :byte_pointer=, :point= - def self.insert_text(*args, &block) - line_editor.insert_text(*args, &block) + def self.insert_text(text) + line_editor.insert_pasted_text(text) self end diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb index 883fcf53fb..c90d3d6a7f 100644 --- a/test/reline/yamatanooroti/test_rendering.rb +++ b/test/reline/yamatanooroti/test_rendering.rb @@ -1841,6 +1841,40 @@ def test_print_before_readline EOC end + def test_pre_input_hook_with_redisplay + code = <<~'RUBY' + puts 'Multiline REPL.' + Reline.pre_input_hook = -> do + Reline.insert_text 'abc' + Reline.redisplay # Reline doesn't need this but Readline requires calling redisplay + end + Reline.readline('prompt> ') + RUBY + start_terminal(6, 30, ['ruby', "-I#{@pwd}/lib", '-rreline', '-e', code], startup_message: 'Multiline REPL.') + assert_screen(<<~EOC) + Multiline REPL. + prompt> abc + EOC + end + + def test_pre_input_hook_with_multiline_text_insert + # Frequently used pattern of pre_input_hook + code = <<~'RUBY' + puts 'Multiline REPL.' + Reline.pre_input_hook = -> do + Reline.insert_text "abc\nef" + end + Reline.readline('>') + RUBY + start_terminal(6, 30, ['ruby', "-I#{@pwd}/lib", '-rreline', '-e', code], startup_message: 'Multiline REPL.') + write("\C-ad") + assert_screen(<<~EOC) + Multiline REPL. + >abc + def + EOC + end + def test_thread_safe start_terminal(6, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.') write("[Thread.new{Reline.readline'>'},Thread.new{Reline.readmultiline('>'){true}}].map(&:join).size\n") From 8796caf8658722f9983a199a18598c21cb269a30 Mon Sep 17 00:00:00 2001 From: tompng Date: Tue, 3 Sep 2024 23:29:15 +0900 Subject: [PATCH 2/2] Rename insert_pasted_text to insert_multiline_text It is now used from Reline.insert_text which is not inserting pasted text --- lib/reline.rb | 4 ++-- lib/reline/line_editor.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/reline.rb b/lib/reline.rb index e636035a33..ddb0224180 100644 --- a/lib/reline.rb +++ b/lib/reline.rb @@ -346,7 +346,7 @@ def readline(prompt = '', add_hist = false) inputs.each do |key| if key.char == :bracketed_paste_start text = io_gate.read_bracketed_paste - line_editor.insert_pasted_text(text) + line_editor.insert_multiline_text(text) line_editor.scroll_into_view else line_editor.update(key) @@ -461,7 +461,7 @@ def ambiguous_width def_single_delegator :line_editor, :byte_pointer=, :point= def self.insert_text(text) - line_editor.insert_pasted_text(text) + line_editor.insert_multiline_text(text) self end diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 5f7f00c979..1fd6fe6970 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -1333,7 +1333,7 @@ def confirm_multiline_termination @confirm_multiline_termination_proc.(temp_buffer.join("\n") + "\n") end - def insert_pasted_text(text) + 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..)