mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Add ed_search_prev_history to Reline
This commit is contained in:
parent
559cad9f2d
commit
bb56b89900
3 changed files with 113 additions and 1 deletions
|
@ -37,7 +37,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
|
||||||
# 17 ^Q
|
# 17 ^Q
|
||||||
:ed_ignore,
|
:ed_ignore,
|
||||||
# 18 ^R
|
# 18 ^R
|
||||||
:ed_redisplay,
|
:ed_search_prev_history,
|
||||||
# 19 ^S
|
# 19 ^S
|
||||||
:ed_ignore,
|
:ed_ignore,
|
||||||
# 20 ^T
|
# 20 ^T
|
||||||
|
|
|
@ -230,6 +230,9 @@ class Reline::LineEditor
|
||||||
if @vi_arg
|
if @vi_arg
|
||||||
prompt = "(arg: #{@vi_arg}) "
|
prompt = "(arg: #{@vi_arg}) "
|
||||||
prompt_width = calculate_width(prompt)
|
prompt_width = calculate_width(prompt)
|
||||||
|
elsif @searching_prompt
|
||||||
|
prompt = @searching_prompt
|
||||||
|
prompt_width = calculate_width(prompt)
|
||||||
else
|
else
|
||||||
prompt = @prompt
|
prompt = @prompt
|
||||||
prompt_width = @prompt_width
|
prompt_width = @prompt_width
|
||||||
|
@ -578,6 +581,14 @@ class Reline::LineEditor
|
||||||
end
|
end
|
||||||
|
|
||||||
def input_key(key)
|
def input_key(key)
|
||||||
|
if key.nil?
|
||||||
|
if @first_char
|
||||||
|
@line = nil
|
||||||
|
end
|
||||||
|
finish
|
||||||
|
return
|
||||||
|
end
|
||||||
|
@first_char = false
|
||||||
completion_occurs = false
|
completion_occurs = false
|
||||||
if @config.editing_mode_is?(:emacs, :vi_insert) and key == "\C-i".ord
|
if @config.editing_mode_is?(:emacs, :vi_insert) and key == "\C-i".ord
|
||||||
result = @completion_proc&.(@line)
|
result = @completion_proc&.(@line)
|
||||||
|
@ -733,6 +744,94 @@ class Reline::LineEditor
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private def ed_search_prev_history(key)
|
||||||
|
@line_backup_in_history = @line
|
||||||
|
searcher = Fiber.new do
|
||||||
|
search_word = String.new(encoding: @encoding)
|
||||||
|
multibyte_buf = String.new(encoding: 'ASCII-8BIT')
|
||||||
|
last_hit = nil
|
||||||
|
loop do
|
||||||
|
key = Fiber.yield(search_word)
|
||||||
|
case key
|
||||||
|
when "\C-h".ord, 127
|
||||||
|
grapheme_clusters = search_word.grapheme_clusters
|
||||||
|
if grapheme_clusters.size > 0
|
||||||
|
grapheme_clusters.pop
|
||||||
|
search_word = grapheme_clusters.join
|
||||||
|
end
|
||||||
|
else
|
||||||
|
multibyte_buf << key
|
||||||
|
if multibyte_buf.dup.force_encoding(@encoding).valid_encoding?
|
||||||
|
search_word << multibyte_buf.dup.force_encoding(@encoding)
|
||||||
|
multibyte_buf.clear
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hit = nil
|
||||||
|
if @line_backup_in_history.include?(search_word)
|
||||||
|
@history_pointer = nil
|
||||||
|
hit = @line_backup_in_history
|
||||||
|
else
|
||||||
|
hit_index = Reline::HISTORY.rindex { |item|
|
||||||
|
item.include?(search_word)
|
||||||
|
}
|
||||||
|
if hit_index
|
||||||
|
@history_pointer = hit_index
|
||||||
|
hit = Reline::HISTORY[@history_pointer]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if hit
|
||||||
|
@searching_prompt = "(reverse-i-search)`%s': %s" % [search_word, hit]
|
||||||
|
@line = hit
|
||||||
|
last_hit = hit
|
||||||
|
else
|
||||||
|
@searching_prompt = "(failed reverse-i-search)`%s': %s" % [search_word, last_hit]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
searcher.resume
|
||||||
|
@searching_prompt = "(reverse-i-search)`': "
|
||||||
|
@waiting_proc = ->(key) {
|
||||||
|
case key
|
||||||
|
when "\C-j".ord, "\C-?".ord
|
||||||
|
if @history_pointer
|
||||||
|
@line = Reline::HISTORY[@history_pointer]
|
||||||
|
else
|
||||||
|
@line = @line_backup_in_history
|
||||||
|
end
|
||||||
|
@searching_prompt = nil
|
||||||
|
@waiting_proc = nil
|
||||||
|
@cursor_max = calculate_width(@line)
|
||||||
|
@cursor = @byte_pointer = 0
|
||||||
|
when "\C-g".ord
|
||||||
|
@line = @line_backup_in_history
|
||||||
|
@history_pointer = nil
|
||||||
|
@searching_prompt = nil
|
||||||
|
@waiting_proc = nil
|
||||||
|
@line_backup_in_history = nil
|
||||||
|
@cursor_max = calculate_width(@line)
|
||||||
|
@cursor = @byte_pointer = 0
|
||||||
|
else
|
||||||
|
chr = key.is_a?(String) ? key : key.chr(Encoding::ASCII_8BIT)
|
||||||
|
if chr.match?(/[[:print:]]/)
|
||||||
|
search_word = searcher.resume(key)
|
||||||
|
else
|
||||||
|
if @history_pointer
|
||||||
|
@line = Reline::HISTORY[@history_pointer]
|
||||||
|
else
|
||||||
|
@line = @line_backup_in_history
|
||||||
|
end
|
||||||
|
@searching_prompt = nil
|
||||||
|
@waiting_proc = nil
|
||||||
|
@cursor_max = calculate_width(@line)
|
||||||
|
@cursor = @byte_pointer = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
private def ed_search_next_history(key)
|
||||||
|
end
|
||||||
|
|
||||||
private def ed_prev_history(key, arg: 1)
|
private def ed_prev_history(key, arg: 1)
|
||||||
if @is_multiline and @line_index > 0
|
if @is_multiline and @line_index > 0
|
||||||
@previous_line_index = @line_index
|
@previous_line_index = @line_index
|
||||||
|
|
|
@ -1162,4 +1162,17 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
|
||||||
assert_cursor_max(0)
|
assert_cursor_max(0)
|
||||||
assert_line('')
|
assert_line('')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_ed_search_prev_history
|
||||||
|
Reline::HISTORY.concat(%w{abc 123 AAA})
|
||||||
|
assert_line('')
|
||||||
|
assert_byte_pointer_size('')
|
||||||
|
assert_cursor(0)
|
||||||
|
assert_cursor_max(0)
|
||||||
|
input_keys("\C-ra\C-j")
|
||||||
|
assert_line('abc')
|
||||||
|
assert_byte_pointer_size('')
|
||||||
|
assert_cursor(0)
|
||||||
|
assert_cursor_max(3)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue