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
|
||||
:ed_ignore,
|
||||
# 18 ^R
|
||||
:ed_redisplay,
|
||||
:ed_search_prev_history,
|
||||
# 19 ^S
|
||||
:ed_ignore,
|
||||
# 20 ^T
|
||||
|
|
|
@ -230,6 +230,9 @@ class Reline::LineEditor
|
|||
if @vi_arg
|
||||
prompt = "(arg: #{@vi_arg}) "
|
||||
prompt_width = calculate_width(prompt)
|
||||
elsif @searching_prompt
|
||||
prompt = @searching_prompt
|
||||
prompt_width = calculate_width(prompt)
|
||||
else
|
||||
prompt = @prompt
|
||||
prompt_width = @prompt_width
|
||||
|
@ -578,6 +581,14 @@ class Reline::LineEditor
|
|||
end
|
||||
|
||||
def input_key(key)
|
||||
if key.nil?
|
||||
if @first_char
|
||||
@line = nil
|
||||
end
|
||||
finish
|
||||
return
|
||||
end
|
||||
@first_char = false
|
||||
completion_occurs = false
|
||||
if @config.editing_mode_is?(:emacs, :vi_insert) and key == "\C-i".ord
|
||||
result = @completion_proc&.(@line)
|
||||
|
@ -733,6 +744,94 @@ class Reline::LineEditor
|
|||
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)
|
||||
if @is_multiline and @line_index > 0
|
||||
@previous_line_index = @line_index
|
||||
|
|
|
@ -1162,4 +1162,17 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
|
|||
assert_cursor_max(0)
|
||||
assert_line('')
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue