1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Support Readline.completion_quote_character by Reline

This commit is contained in:
aycabta 2019-12-11 11:12:54 +09:00
parent 8e49ef5a69
commit ec54ac9381
2 changed files with 28 additions and 8 deletions

View file

@ -42,6 +42,7 @@ module Reline
def initialize def initialize
self.output = STDOUT self.output = STDOUT
yield self yield self
@completion_quote_character = nil
end end
def completion_append_character=(val) def completion_append_character=(val)
@ -88,6 +89,10 @@ module Reline
@config.completion_ignore_case @config.completion_ignore_case
end end
def completion_quote_character
@completion_quote_character
end
def completion_proc=(p) def completion_proc=(p)
raise ArgumentError unless p.respond_to?(:call) raise ArgumentError unless p.respond_to?(:call)
@completion_proc = p @completion_proc = p
@ -347,6 +352,7 @@ module Reline
def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
def_single_delegators :core, :readline def_single_delegators :core, :readline
def_single_delegators :core, :completion_case_fold, :completion_case_fold= def_single_delegators :core, :completion_case_fold, :completion_case_fold=
def_single_delegators :core, :completion_quote_character
def_instance_delegators self, :readline def_instance_delegators self, :readline
private :readline private :readline

View file

@ -789,9 +789,7 @@ class Reline::LineEditor
completion_occurs = false completion_occurs = false
if @config.editing_mode_is?(:emacs, :vi_insert) and key.char == "\C-i".ord if @config.editing_mode_is?(:emacs, :vi_insert) and key.char == "\C-i".ord
unless @config.disable_completion unless @config.disable_completion
result = retrieve_completion_block result = call_completion_proc
slice = result[1]
result = @completion_proc.(slice) if @completion_proc and slice
if result.is_a?(Array) if result.is_a?(Array)
completion_occurs = true completion_occurs = true
complete(result) complete(result)
@ -799,9 +797,7 @@ class Reline::LineEditor
end end
elsif not @config.disable_completion and @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char) elsif not @config.disable_completion and @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char)
unless @config.disable_completion unless @config.disable_completion
result = retrieve_completion_block result = call_completion_proc
slice = result[1]
result = @completion_proc.(slice) if @completion_proc and slice
if result.is_a?(Array) if result.is_a?(Array)
completion_occurs = true completion_occurs = true
move_completed_list(result, "\C-p".ord == key.char ? :up : :down) move_completed_list(result, "\C-p".ord == key.char ? :up : :down)
@ -820,6 +816,14 @@ class Reline::LineEditor
end end
end end
def call_completion_proc
result = retrieve_completion_block(true)
slice = result[1]
result = @completion_proc.(slice) if @completion_proc and slice
Reline.core.instance_variable_set(:@completion_quote_character, nil)
result
end
private def process_auto_indent private def process_auto_indent
return if not @check_new_auto_indent and @previous_line_index # move cursor up or down return if not @check_new_auto_indent and @previous_line_index # move cursor up or down
if @check_new_auto_indent and @previous_line_index and @previous_line_index > 0 and @line_index > @previous_line_index if @check_new_auto_indent and @previous_line_index and @previous_line_index > 0 and @line_index > @previous_line_index
@ -861,7 +865,7 @@ class Reline::LineEditor
@check_new_auto_indent = false @check_new_auto_indent = false
end end
def retrieve_completion_block def retrieve_completion_block(set_completion_quote_character = false)
word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/ word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/
quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/ quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/
before = @line.byteslice(0, @byte_pointer) before = @line.byteslice(0, @byte_pointer)
@ -880,14 +884,18 @@ class Reline::LineEditor
if quote and slice.start_with?(closing_quote) if quote and slice.start_with?(closing_quote)
quote = nil quote = nil
i += 1 i += 1
rest = nil
break_pointer = nil
elsif quote and slice.start_with?(escaped_quote) elsif quote and slice.start_with?(escaped_quote)
# skip # skip
i += 2 i += 2
elsif slice =~ quote_characters_regexp # find new " elsif slice =~ quote_characters_regexp # find new "
rest = $'
quote = $& quote = $&
closing_quote = /(?!\\)#{Regexp.escape(quote)}/ closing_quote = /(?!\\)#{Regexp.escape(quote)}/
escaped_quote = /\\#{Regexp.escape(quote)}/ escaped_quote = /\\#{Regexp.escape(quote)}/
i += 1 i += 1
break_pointer = i
elsif not quote and slice =~ word_break_regexp elsif not quote and slice =~ word_break_regexp
rest = $' rest = $'
i += 1 i += 1
@ -896,14 +904,20 @@ class Reline::LineEditor
i += 1 i += 1
end end
end end
postposing = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer)
if rest if rest
preposing = @line.byteslice(0, break_pointer) preposing = @line.byteslice(0, break_pointer)
target = rest target = rest
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 else
preposing = '' preposing = ''
target = before target = before
end end
postposing = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer)
[preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)] [preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)]
end end