Skip to content

Commit bf0f8fa

Browse files
authored
Fix incremental search cancel bug (#748)
1 parent dd4a654 commit bf0f8fa

2 files changed

Lines changed: 41 additions & 46 deletions

File tree

lib/reline/line_editor.rb

Lines changed: 18 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,57 +1665,29 @@ def finish
16651665
end
16661666

16671667
private def incremental_search_history(key)
1668-
unless @history_pointer
1669-
@line_backup_in_history = whole_buffer
1670-
end
1668+
backup = @buffer_of_lines.dup, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history
16711669
searcher = generate_searcher(key)
16721670
@searching_prompt = "(reverse-i-search)`': "
16731671
termination_keys = ["\C-j".ord]
1674-
termination_keys.concat(@config.isearch_terminators&.chars&.map(&:ord)) if @config.isearch_terminators
1672+
termination_keys.concat(@config.isearch_terminators.chars.map(&:ord)) if @config.isearch_terminators
16751673
@waiting_proc = ->(k) {
1676-
case k
1677-
when *termination_keys
1678-
if @history_pointer
1679-
buffer = Reline::HISTORY[@history_pointer]
1680-
else
1681-
buffer = @line_backup_in_history
1682-
end
1683-
@buffer_of_lines = buffer.split("\n")
1684-
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
1685-
@line_index = @buffer_of_lines.size - 1
1674+
chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
1675+
if k == "\C-g".ord
1676+
# cancel search and restore buffer
1677+
@buffer_of_lines, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history = backup
16861678
@searching_prompt = nil
16871679
@waiting_proc = nil
1688-
@byte_pointer = 0
1689-
when "\C-g".ord
1690-
@buffer_of_lines = @line_backup_in_history.split("\n")
1691-
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
1692-
@line_index = @buffer_of_lines.size - 1
1693-
move_history(nil, line: :end, cursor: :end, save_buffer: false)
1680+
elsif !termination_keys.include?(k) && (chr.match?(/[[:print:]]/) || k == "\C-h".ord || k == "\C-?".ord || k == "\C-r".ord || k == "\C-s".ord)
1681+
search_word, prompt_name, hit_pointer = searcher.call(k)
1682+
Reline.last_incremental_search = search_word
1683+
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
1684+
@searching_prompt += ': ' unless @is_multiline
1685+
move_history(hit_pointer, line: :end, cursor: :end) if hit_pointer
1686+
else
1687+
# terminaton_keys and other keys will terminalte
1688+
move_history(@history_pointer, line: :end, cursor: :start)
16941689
@searching_prompt = nil
16951690
@waiting_proc = nil
1696-
@byte_pointer = 0
1697-
else
1698-
chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
1699-
if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord
1700-
search_word, prompt_name, hit_pointer = searcher.call(k)
1701-
Reline.last_incremental_search = search_word
1702-
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
1703-
@searching_prompt += ': ' unless @is_multiline
1704-
move_history(hit_pointer, line: :end, cursor: :end, save_buffer: false) if hit_pointer
1705-
else
1706-
if @history_pointer
1707-
line = Reline::HISTORY[@history_pointer]
1708-
else
1709-
line = @line_backup_in_history
1710-
end
1711-
@line_backup_in_history = whole_buffer
1712-
@buffer_of_lines = line.split("\n")
1713-
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
1714-
@line_index = @buffer_of_lines.size - 1
1715-
@searching_prompt = nil
1716-
@waiting_proc = nil
1717-
@byte_pointer = 0
1718-
end
17191691
end
17201692
}
17211693
end
@@ -1770,14 +1742,14 @@ def finish
17701742
end
17711743
alias_method :history_search_forward, :ed_search_next_history
17721744

1773-
private def move_history(history_pointer, line:, cursor:, save_buffer: true)
1745+
private def move_history(history_pointer, line:, cursor:)
17741746
history_pointer ||= Reline::HISTORY.size
17751747
return if history_pointer < 0 || history_pointer > Reline::HISTORY.size
17761748
old_history_pointer = @history_pointer || Reline::HISTORY.size
17771749
if old_history_pointer == Reline::HISTORY.size
1778-
@line_backup_in_history = save_buffer ? whole_buffer : ''
1750+
@line_backup_in_history = whole_buffer
17791751
else
1780-
Reline::HISTORY[old_history_pointer] = whole_buffer if save_buffer
1752+
Reline::HISTORY[old_history_pointer] = whole_buffer
17811753
end
17821754
if history_pointer == Reline::HISTORY.size
17831755
buf = @line_backup_in_history

test/reline/test_key_actor_emacs.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,29 @@ def test_incremental_search_history_cancel_by_symbol_key
13281328
assert_line_around_cursor('abd', 'c')
13291329
end
13301330

1331+
def test_incremental_search_history_saves_and_restores_last_input
1332+
Reline::HISTORY.concat(['abc', '123'])
1333+
input_keys("abcd")
1334+
# \C-j: terminate incremental search
1335+
input_keys("\C-r12\C-j")
1336+
assert_line_around_cursor('', '123')
1337+
input_key_by_symbol(:ed_next_history)
1338+
assert_line_around_cursor('abcd', '')
1339+
# Most non-printable keys also terminates incremental search
1340+
input_keys("\C-r12\C-i")
1341+
assert_line_around_cursor('', '123')
1342+
input_key_by_symbol(:ed_next_history)
1343+
assert_line_around_cursor('abcd', '')
1344+
# \C-g: cancel incremental search and restore input, cursor position and history index
1345+
input_key_by_symbol(:ed_prev_history)
1346+
input_keys("\C-b\C-b")
1347+
assert_line_around_cursor('1', '23')
1348+
input_keys("\C-rab\C-g")
1349+
assert_line_around_cursor('1', '23')
1350+
input_key_by_symbol(:ed_next_history)
1351+
assert_line_around_cursor('abcd', '')
1352+
end
1353+
13311354
# Unicode emoji test
13321355
def test_ed_insert_for_include_zwj_emoji
13331356
omit "This test is for UTF-8 but the locale is #{Reline.core.encoding}" if Reline.core.encoding != Encoding::UTF_8

0 commit comments

Comments
 (0)