Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix incremental search cancel bug #748

Merged
merged 1 commit into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 18 additions & 46 deletions lib/reline/line_editor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1665,57 +1665,29 @@ def finish
end

private def incremental_search_history(key)
unless @history_pointer
@line_backup_in_history = whole_buffer
end
backup = @buffer_of_lines.dup, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history
searcher = generate_searcher(key)
@searching_prompt = "(reverse-i-search)`': "
termination_keys = ["\C-j".ord]
termination_keys.concat(@config.isearch_terminators&.chars&.map(&:ord)) if @config.isearch_terminators
termination_keys.concat(@config.isearch_terminators.chars.map(&:ord)) if @config.isearch_terminators
@waiting_proc = ->(k) {
case k
when *termination_keys
if @history_pointer
buffer = Reline::HISTORY[@history_pointer]
else
buffer = @line_backup_in_history
end
@buffer_of_lines = buffer.split("\n")
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
@line_index = @buffer_of_lines.size - 1
chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
if k == "\C-g".ord
# cancel search and restore buffer
@buffer_of_lines, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history = backup
@searching_prompt = nil
@waiting_proc = nil
@byte_pointer = 0
when "\C-g".ord
@buffer_of_lines = @line_backup_in_history.split("\n")
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
@line_index = @buffer_of_lines.size - 1
move_history(nil, line: :end, cursor: :end, save_buffer: false)
elsif !termination_keys.include?(k) && (chr.match?(/[[:print:]]/) || k == "\C-h".ord || k == "\C-?".ord || k == "\C-r".ord || k == "\C-s".ord)
search_word, prompt_name, hit_pointer = searcher.call(k)
Reline.last_incremental_search = search_word
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
@searching_prompt += ': ' unless @is_multiline
move_history(hit_pointer, line: :end, cursor: :end) if hit_pointer
else
# terminaton_keys and other keys will terminalte
move_history(@history_pointer, line: :end, cursor: :start)
@searching_prompt = nil
@waiting_proc = nil
@byte_pointer = 0
else
chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord
search_word, prompt_name, hit_pointer = searcher.call(k)
Reline.last_incremental_search = search_word
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
@searching_prompt += ': ' unless @is_multiline
move_history(hit_pointer, line: :end, cursor: :end, save_buffer: false) if hit_pointer
else
if @history_pointer
line = Reline::HISTORY[@history_pointer]
else
line = @line_backup_in_history
end
@line_backup_in_history = whole_buffer
@buffer_of_lines = line.split("\n")
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
@line_index = @buffer_of_lines.size - 1
@searching_prompt = nil
@waiting_proc = nil
@byte_pointer = 0
end
end
}
end
Expand Down Expand Up @@ -1770,14 +1742,14 @@ def finish
end
alias_method :history_search_forward, :ed_search_next_history

private def move_history(history_pointer, line:, cursor:, save_buffer: true)
private def move_history(history_pointer, line:, cursor:)
history_pointer ||= Reline::HISTORY.size
return if history_pointer < 0 || history_pointer > Reline::HISTORY.size
old_history_pointer = @history_pointer || Reline::HISTORY.size
if old_history_pointer == Reline::HISTORY.size
@line_backup_in_history = save_buffer ? whole_buffer : ''
@line_backup_in_history = whole_buffer
else
Reline::HISTORY[old_history_pointer] = whole_buffer if save_buffer
Reline::HISTORY[old_history_pointer] = whole_buffer
end
if history_pointer == Reline::HISTORY.size
buf = @line_backup_in_history
Expand Down
23 changes: 23 additions & 0 deletions test/reline/test_key_actor_emacs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,29 @@ def test_incremental_search_history_cancel_by_symbol_key
assert_line_around_cursor('abd', 'c')
end

def test_incremental_search_history_saves_and_restores_last_input
Reline::HISTORY.concat(['abc', '123'])
input_keys("abcd")
# \C-j: terminate incremental search
input_keys("\C-r12\C-j")
assert_line_around_cursor('', '123')
input_key_by_symbol(:ed_next_history)
assert_line_around_cursor('abcd', '')
# Most non-printable keys also terminates incremental search
input_keys("\C-r12\C-i")
assert_line_around_cursor('', '123')
input_key_by_symbol(:ed_next_history)
assert_line_around_cursor('abcd', '')
# \C-g: cancel incremental search and restore input, cursor position and history index
input_key_by_symbol(:ed_prev_history)
input_keys("\C-b\C-b")
assert_line_around_cursor('1', '23')
input_keys("\C-rab\C-g")
assert_line_around_cursor('1', '23')
input_key_by_symbol(:ed_next_history)
assert_line_around_cursor('abcd', '')
end

# Unicode emoji test
def test_ed_insert_for_include_zwj_emoji
omit "This test is for UTF-8 but the locale is #{Reline.core.encoding}" if Reline.core.encoding != Encoding::UTF_8
Expand Down
Loading