aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authoraycabta <aycabta@gmail.com>2019-12-11 11:12:54 +0900
committeraycabta <aycabta@gmail.com>2019-12-11 11:13:05 +0900
commitec54ac938104517dd61887006ef8cc324b3b1b35 (patch)
treefa52642c8a639fc07aa6211ab509ac333a2dfbfb /lib
parent8e49ef5a691cc9a249acae8c7335ec53bf445dc3 (diff)
downloadruby-ec54ac938104517dd61887006ef8cc324b3b1b35.tar.gz
Support Readline.completion_quote_character by Reline
Diffstat (limited to 'lib')
-rw-r--r--lib/reline.rb6
-rw-r--r--lib/reline/line_editor.rb30
2 files changed, 28 insertions, 8 deletions
diff --git a/lib/reline.rb b/lib/reline.rb
index 2036ec7024..c4c6b97d03 100644
--- a/lib/reline.rb
+++ b/lib/reline.rb
@@ -42,6 +42,7 @@ module Reline
def initialize
self.output = STDOUT
yield self
+ @completion_quote_character = nil
end
def completion_append_character=(val)
@@ -88,6 +89,10 @@ module Reline
@config.completion_ignore_case
end
+ def completion_quote_character
+ @completion_quote_character
+ end
+
def completion_proc=(p)
raise ArgumentError unless p.respond_to?(:call)
@completion_proc = p
@@ -347,6 +352,7 @@ module Reline
def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
def_single_delegators :core, :readline
def_single_delegators :core, :completion_case_fold, :completion_case_fold=
+ def_single_delegators :core, :completion_quote_character
def_instance_delegators self, :readline
private :readline
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
index 74c5489ba7..2abe659820 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -789,9 +789,7 @@ class Reline::LineEditor
completion_occurs = false
if @config.editing_mode_is?(:emacs, :vi_insert) and key.char == "\C-i".ord
unless @config.disable_completion
- result = retrieve_completion_block
- slice = result[1]
- result = @completion_proc.(slice) if @completion_proc and slice
+ result = call_completion_proc
if result.is_a?(Array)
completion_occurs = true
complete(result)
@@ -799,9 +797,7 @@ class Reline::LineEditor
end
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
- result = retrieve_completion_block
- slice = result[1]
- result = @completion_proc.(slice) if @completion_proc and slice
+ result = call_completion_proc
if result.is_a?(Array)
completion_occurs = true
move_completed_list(result, "\C-p".ord == key.char ? :up : :down)
@@ -820,6 +816,14 @@ class Reline::LineEditor
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
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
@@ -861,7 +865,7 @@ class Reline::LineEditor
@check_new_auto_indent = false
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)}]/
quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/
before = @line.byteslice(0, @byte_pointer)
@@ -880,14 +884,18 @@ class Reline::LineEditor
if quote and slice.start_with?(closing_quote)
quote = nil
i += 1
+ rest = nil
+ break_pointer = nil
elsif quote and slice.start_with?(escaped_quote)
# skip
i += 2
elsif slice =~ quote_characters_regexp # find new "
+ rest = $'
quote = $&
closing_quote = /(?!\\)#{Regexp.escape(quote)}/
escaped_quote = /\\#{Regexp.escape(quote)}/
i += 1
+ break_pointer = i
elsif not quote and slice =~ word_break_regexp
rest = $'
i += 1
@@ -896,14 +904,20 @@ class Reline::LineEditor
i += 1
end
end
+ postposing = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer)
if rest
preposing = @line.byteslice(0, break_pointer)
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
preposing = ''
target = before
end
- postposing = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer)
[preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)]
end