From 4c645a4ef63cd547cd87576af76b9deb6b13de02 Mon Sep 17 00:00:00 2001 From: tompng Date: Sun, 31 Mar 2024 00:57:05 +0900 Subject: [PATCH] Move completion candidate listup logic from dialog proc to LineEditor --- lib/reline.rb | 20 +++----- lib/reline/line_editor.rb | 52 ++++++++++++--------- test/reline/yamatanooroti/test_rendering.rb | 13 ++++++ 3 files changed, 49 insertions(+), 36 deletions(-) diff --git a/lib/reline.rb b/lib/reline.rb index 87201d25f7..b43584fc9b 100644 --- a/lib/reline.rb +++ b/lib/reline.rb @@ -222,21 +222,13 @@ def get_screen_size return unless config.autocompletion journey_data = completion_journey_data - if just_cursor_moving and journey_data.nil? - # Auto complete starts only when edited - return - end - if journey_data - result = journey_data.list.drop(1) - pointer = journey_data.pointer - 1 - target = journey_data.list[journey_data.pointer] - else - pre, target, post = retrieve_completion_block(true) - return if target.nil? || target.empty? + return unless journey_data + + target = journey_data.list[journey_data.pointer] + result = journey_data.list.drop(1) + pointer = journey_data.pointer - 1 + return if target.empty? || (result == [target] && pointer < 0) - result = call_completion_proc_with_checking_args(pre, target, post) - return if result and result.size == 1 and result[0] == target - end target_width = Reline::Unicode.calculate_width(target) x = cursor_pos.x - target_width if x < 0 diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 28c76dd593..db576f4762 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -886,33 +886,32 @@ def dialog_proc_scope_completion_journey_data end private def move_completed_list(direction) - if @completion_journey_state - if (delta = { up: -1, down: +1 }[direction]) - @completion_journey_state.pointer = (@completion_journey_state.pointer + delta) % @completion_journey_state.list.size - end - else - preposing, target, postposing = retrieve_completion_block - return false unless target - - list = call_completion_proc - return false unless list.is_a?(Array) + @completion_journey_state ||= retrieve_completion_journey_state + return false unless @completion_journey_state - candidates = list.select{ |item| item.start_with?(target) } - return false if candidates.empty? - - pre = preposing.split("\n", -1).last || '' - post = postposing.split("\n", -1).first || '' - pointer = direction == :up ? candidates.size : 1 - @completion_journey_state = CompletionJourneyState.new( - @line_index, pre, target, post, [target] + candidates, pointer - ) + if (delta = { up: -1, down: +1 }[direction]) + @completion_journey_state.pointer = (@completion_journey_state.pointer + delta) % @completion_journey_state.list.size end - completed = @completion_journey_state.list[@completion_journey_state.pointer] set_current_line(@completion_journey_state.pre + completed + @completion_journey_state.post, @completion_journey_state.pre.bytesize + completed.bytesize) true end + private def retrieve_completion_journey_state + preposing, target, postposing = retrieve_completion_block + list = call_completion_proc + return unless list.is_a?(Array) + + candidates = list.select{ |item| item.start_with?(target) } + return if candidates.empty? + + pre = preposing.split("\n", -1).last || '' + post = postposing.split("\n", -1).first || '' + CompletionJourneyState.new( + @line_index, pre, target, post, [target] + candidates, 0 + ) + end + private def run_for_operators(key, method_symbol, &block) if @waiting_operator_proc if VI_MOTIONS.include?(method_symbol) @@ -1131,15 +1130,24 @@ def input_key(key) else normal_char(key) end + unless completion_occurs @completion_state = CompletionState::NORMAL @completion_journey_state = nil end + if @in_pasting clear_dialogs - else - return old_lines != @buffer_of_lines + return + end + + modified = old_lines != @buffer_of_lines + if !completion_occurs && modified && !@config.disable_completion && @config.autocompletion + # Auto complete starts only when edited + process_insert(force: true) + @completion_journey_state = retrieve_completion_journey_state end + modified end def scroll_into_view diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb index efb1e01562..53c842a04a 100644 --- a/test/reline/yamatanooroti/test_rendering.rb +++ b/test/reline/yamatanooroti/test_rendering.rb @@ -1108,6 +1108,19 @@ def test_autocomplete_target_is_wrapped EOC end + def test_force_insert_before_autocomplete + start_terminal(20, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.') + write('Sy') + write(";St\t\t") + close + assert_screen(<<~'EOC') + Multiline REPL. + prompt> Sy;Struct + String + Struct + EOC + end + def test_simple_dialog_with_scroll_key start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog long,scrollkey}, startup_message: 'Multiline REPL.') write('a')