1
0
Fork 0
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:
aycabta 2019-05-13 01:51:05 +09:00
parent 559cad9f2d
commit bb56b89900
3 changed files with 113 additions and 1 deletions

View file

@ -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

View file

@ -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

View file

@ -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