From 1f469de90ce3417b580c5ecafbe3afa9435c8850 Mon Sep 17 00:00:00 2001 From: aycabta Date: Tue, 23 Mar 2021 21:43:39 +0900 Subject: [PATCH] Support preposing and postposing for Reline.completion_proc --- lib/reline/line_editor.rb | 34 ++++++++++++++++- test/reline/test_string_processing.rb | 54 +++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 870b89b550..4e5860ceb9 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -1158,8 +1158,25 @@ def input_key(key) def call_completion_proc result = retrieve_completion_block(true) - slice = result[1] - result = @completion_proc.(slice) if @completion_proc and slice + preposing, target, postposing = result + if @completion_proc and target + argnum = @completion_proc.parameters.inject(0) { |result, item| + case item.first + when :req, :opt + result + 1 + when :rest + break 3 + end + } + case argnum + when 1 + result = @completion_proc.(target) + when 2 + result = @completion_proc.(target, preposing) + when 3..Float::INFINITY + result = @completion_proc.(target, preposing, postposing) + end + end Reline.core.instance_variable_set(:@completion_quote_character, nil) result end @@ -1264,6 +1281,19 @@ def retrieve_completion_block(set_completion_quote_character = false) end target = before end + if @is_multiline + if @previous_line_index + lines = whole_lines(index: @previous_line_index, line: @line) + else + lines = whole_lines + end + if @line_index > 0 + preposing = lines[0..(@line_index - 1)].join("\n") + "\n" + preposing + end + if (lines.size - 1) > @line_index + postposing = postposing + "\n" + lines[(@line_index + 1)..-1].join("\n") + end + end [preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)] end diff --git a/test/reline/test_string_processing.rb b/test/reline/test_string_processing.rb index e76fa384f2..0e0ee9cc04 100644 --- a/test/reline/test_string_processing.rb +++ b/test/reline/test_string_processing.rb @@ -20,4 +20,58 @@ def test_calculate_width_with_escape_sequence width = @line_editor.send(:calculate_width, "\1\e[31m\2RubyColor\1\e[34m\2 default string \1\e[m\2>", true) assert_equal('RubyColor default string >'.size, width) end + + def test_completion_proc_with_preposing_and_postposing + buf = ['def hoge', ' puts :aaa', 'end'] + + @line_editor.instance_variable_set(:@is_multiline, true) + @line_editor.instance_variable_set(:@buffer_of_lines, buf) + @line_editor.instance_variable_set(:@line, buf[1]) + @line_editor.instance_variable_set(:@byte_pointer, 3) + @line_editor.instance_variable_set(:@cursor, 3) + @line_editor.instance_variable_set(:@cursor_max, 11) + @line_editor.instance_variable_set(:@line_index, 1) + @line_editor.instance_variable_set(:@completion_proc, proc { |target| + assert_equal('p', target) + }) + @line_editor.__send__(:call_completion_proc) + + @line_editor.instance_variable_set(:@is_multiline, true) + @line_editor.instance_variable_set(:@buffer_of_lines, buf) + @line_editor.instance_variable_set(:@line, buf[1]) + @line_editor.instance_variable_set(:@byte_pointer, 6) + @line_editor.instance_variable_set(:@cursor, 6) + @line_editor.instance_variable_set(:@cursor_max, 11) + @line_editor.instance_variable_set(:@line_index, 1) + @line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post| + assert_equal('puts', target) + assert_equal("def hoge\n ", pre) + assert_equal(" :aaa\nend", post) + }) + @line_editor.__send__(:call_completion_proc) + + @line_editor.instance_variable_set(:@line, buf[0]) + @line_editor.instance_variable_set(:@byte_pointer, 6) + @line_editor.instance_variable_set(:@cursor, 6) + @line_editor.instance_variable_set(:@cursor_max, 8) + @line_editor.instance_variable_set(:@line_index, 0) + @line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post| + assert_equal('ho', target) + assert_equal('def ', pre) + assert_equal("ge\n puts :aaa\nend", post) + }) + @line_editor.__send__(:call_completion_proc) + + @line_editor.instance_variable_set(:@line, buf[2]) + @line_editor.instance_variable_set(:@byte_pointer, 1) + @line_editor.instance_variable_set(:@cursor, 1) + @line_editor.instance_variable_set(:@cursor_max, 3) + @line_editor.instance_variable_set(:@line_index, 2) + @line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post| + assert_equal('e', target) + assert_equal("def hoge\n puts :aaa\n", pre) + assert_equal('nd', post) + }) + @line_editor.__send__(:call_completion_proc) + end end