summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authortomoya ishida <tomoyapenguin@gmail.com>2024-11-25 00:45:13 +0900
committergit <svn-admin@ruby-lang.org>2024-11-24 15:45:18 +0000
commitbf47b1b5230759dd16fc0930753d37a3eb6f30e2 (patch)
tree38a2dbd129d95c5739b2384833ff0719845d81b2 /lib
parentc6ca33995592ebc5abd7ddcff244c3ea6ae29c47 (diff)
[ruby/reline] Fix completion quote, preposing and target calculation
bug (https://github.com/ruby/reline/pull/763) https://github.com/ruby/reline/commit/d3ba7216eb
Diffstat (limited to 'lib')
-rw-r--r--lib/reline/line_editor.rb79
1 files changed, 22 insertions, 57 deletions
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
index c8a7fc9fea..72e756803c 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -1225,70 +1225,35 @@ class Reline::LineEditor
end
def retrieve_completion_block(set_completion_quote_character = false)
- if Reline.completer_word_break_characters.empty?
- word_break_regexp = nil
- else
- word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/
- end
- if Reline.completer_quote_characters.empty?
- quote_characters_regexp = nil
- else
- quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/
- end
- before = current_line.byteslice(0, @byte_pointer)
- rest = nil
- break_pointer = nil
+ quote_characters = Reline.completer_quote_characters
+ before = current_line.byteslice(0, @byte_pointer).grapheme_clusters
quote = nil
- closing_quote = nil
- escaped_quote = nil
- i = 0
- while i < @byte_pointer do
- slice = current_line.byteslice(i, @byte_pointer - i)
- unless slice.valid_encoding?
- i += 1
- next
- end
- if quote and slice.start_with?(closing_quote)
- quote = nil
- i += 1
- rest = nil
- elsif quote and slice.start_with?(escaped_quote)
- # skip
- i += 2
- elsif quote_characters_regexp and slice =~ quote_characters_regexp # find new "
- rest = $'
- quote = $&
- closing_quote = /(?!\\)#{Regexp.escape(quote)}/
- escaped_quote = /\\#{Regexp.escape(quote)}/
- i += 1
- break_pointer = i - 1
- elsif word_break_regexp and not quote and slice =~ word_break_regexp
- rest = $'
- i += 1
- before = current_line.byteslice(i, @byte_pointer - i)
- break_pointer = i
- else
- i += 1
+ unless quote_characters.empty?
+ escaped = false
+ before.each do |c|
+ if escaped
+ escaped = false
+ next
+ elsif c == '\\'
+ escaped = true
+ elsif quote
+ quote = nil if c == quote
+ elsif quote_characters.include?(c)
+ quote = c
+ end
end
end
+ word_break_characters = quote_characters + Reline.completer_word_break_characters
+ break_index = before.rindex { |c| word_break_characters.include?(c) || quote_characters.include?(c) } || -1
+ preposing = before.take(break_index + 1).join
+ target = before.drop(break_index + 1).join
postposing = current_line.byteslice(@byte_pointer, current_line.bytesize - @byte_pointer)
- if rest
- preposing = current_line.byteslice(0, break_pointer)
- target = rest
+ if target
if set_completion_quote_character and quote
Reline.core.instance_variable_set(:@completion_quote_character, quote)
- if postposing !~ /(?!\\)#{Regexp.escape(quote)}/ # closing quote
- insert_text(quote)
- end
- end
- else
- preposing = ''
- if break_pointer
- preposing = current_line.byteslice(0, break_pointer)
- else
- preposing = ''
+ insert_text(quote) # FIXME: should not be here
+ target += quote
end
- target = before
end
lines = whole_lines
if @line_index > 0