Skip to content

Commit 95ee80b

Browse files
authored
In ed_search_[prev|next]_history, make the cursor come to the end of the line when there is no search substr (#714)
* In ed_search_prev_history, make the cursor come to the end of the line when there is no search substr * In ed_search_next_history, make the cursor come to the end of the line when there is no search substr * Implemented ActionState to search with empty substr if the previous operation was search with empty string. * Use a simple 2-element array to represent action_state
1 parent 353ec23 commit 95ee80b

File tree

2 files changed

+55
-24
lines changed

2 files changed

+55
-24
lines changed

lib/reline/line_editor.rb

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ module CompletionState
4545
RenderedScreen = Struct.new(:base_y, :lines, :cursor_y, keyword_init: true)
4646

4747
CompletionJourneyState = Struct.new(:line_index, :pre, :target, :post, :list, :pointer)
48+
NullActionState = [nil, nil].freeze
4849

4950
class MenuInfo
5051
attr_reader :list
@@ -253,6 +254,8 @@ def reset_variables(prompt = '', encoding:)
253254
@input_lines = [[[""], 0, 0]]
254255
@input_lines_position = 0
255256
@undoing = false
257+
@prev_action_state = NullActionState
258+
@next_action_state = NullActionState
256259
reset_line
257260
end
258261

@@ -1131,6 +1134,9 @@ def input_key(key)
11311134
else
11321135
normal_char(key)
11331136
end
1137+
1138+
@prev_action_state, @next_action_state = @next_action_state, NullActionState
1139+
11341140
unless @completion_occurs
11351141
@completion_state = CompletionState::NORMAL
11361142
@completion_journey_state = nil
@@ -1761,29 +1767,31 @@ def finish
17611767
end
17621768

17631769
private def ed_search_prev_history(key, arg: 1)
1764-
substr = current_line.byteslice(0, @byte_pointer)
1770+
substr = prev_action_state_value(:search_history) == :empty ? '' : current_line.byteslice(0, @byte_pointer)
17651771
return if @history_pointer == 0
17661772
return if @history_pointer.nil? && substr.empty? && !current_line.empty?
17671773

17681774
history_range = 0...(@history_pointer || Reline::HISTORY.size)
17691775
h_pointer, line_index = search_history(substr, history_range.reverse_each)
17701776
return unless h_pointer
1771-
move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer)
1777+
move_history(h_pointer, line: line_index || :start, cursor: substr.empty? ? :end : @byte_pointer)
17721778
arg -= 1
1779+
set_next_action_state(:search_history, :empty) if substr.empty?
17731780
ed_search_prev_history(key, arg: arg) if arg > 0
17741781
end
17751782
alias_method :history_search_backward, :ed_search_prev_history
17761783

17771784
private def ed_search_next_history(key, arg: 1)
1778-
substr = current_line.byteslice(0, @byte_pointer)
1785+
substr = prev_action_state_value(:search_history) == :empty ? '' : current_line.byteslice(0, @byte_pointer)
17791786
return if @history_pointer.nil?
17801787

17811788
history_range = @history_pointer + 1...Reline::HISTORY.size
17821789
h_pointer, line_index = search_history(substr, history_range)
17831790
return if h_pointer.nil? and not substr.empty?
17841791

1785-
move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer)
1792+
move_history(h_pointer, line: line_index || :start, cursor: substr.empty? ? :end : @byte_pointer)
17861793
arg -= 1
1794+
set_next_action_state(:search_history, :empty) if substr.empty?
17871795
ed_search_next_history(key, arg: arg) if arg > 0
17881796
end
17891797
alias_method :history_search_forward, :ed_search_next_history
@@ -2549,4 +2557,12 @@ def finish
25492557
target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
25502558
set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
25512559
end
2560+
2561+
private def prev_action_state_value(type)
2562+
@prev_action_state[0] == type ? @prev_action_state[1] : nil
2563+
end
2564+
2565+
private def set_next_action_state(type, value)
2566+
@next_action_state = [type, value]
2567+
end
25522568
end

test/reline/test_key_actor_emacs.rb

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,14 +1242,22 @@ def test_ed_search_prev_history_with_empty
12421242
'12345' # new
12431243
])
12441244
# The ed_search_prev_history doesn't have default binding
1245-
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
1246-
assert_line_around_cursor('', '12345')
1247-
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
1248-
assert_line_around_cursor('', '12aaa')
1249-
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
1250-
assert_line_around_cursor('', '12356')
1251-
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
1252-
assert_line_around_cursor('', '12356')
1245+
input_key_by_symbol(:ed_search_prev_history)
1246+
assert_line_around_cursor('12345', '')
1247+
input_key_by_symbol(:ed_search_prev_history)
1248+
assert_line_around_cursor('12aaa', '')
1249+
input_key_by_symbol(:ed_search_prev_history)
1250+
assert_line_around_cursor('12356', '')
1251+
input_key_by_symbol(:ed_search_next_history)
1252+
assert_line_around_cursor('12aaa', '')
1253+
input_key_by_symbol(:ed_prev_char)
1254+
input_key_by_symbol(:ed_next_char)
1255+
assert_line_around_cursor('12aaa', '')
1256+
input_key_by_symbol(:ed_search_prev_history)
1257+
assert_line_around_cursor('12aaa', '')
1258+
3.times { input_key_by_symbol(:ed_prev_char) }
1259+
input_key_by_symbol(:ed_search_prev_history)
1260+
assert_line_around_cursor('12', '356')
12531261
end
12541262

12551263
def test_ed_search_prev_history_without_match
@@ -1291,18 +1299,25 @@ def test_ed_search_next_history_with_empty
12911299
'12345' # new
12921300
])
12931301
# The ed_search_prev_history and ed_search_next_history doesn't have default binding
1294-
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
1295-
assert_line_around_cursor('', '12345')
1296-
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
1297-
assert_line_around_cursor('', '12aaa')
1298-
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
1299-
assert_line_around_cursor('', '12356')
1300-
@line_editor.__send__(:ed_search_next_history, "\C-n".ord)
1301-
assert_line_around_cursor('', '12aaa')
1302-
@line_editor.__send__(:ed_search_next_history, "\C-n".ord)
1303-
assert_line_around_cursor('', '12345')
1304-
@line_editor.__send__(:ed_search_next_history, "\C-n".ord)
1305-
assert_line_around_cursor('', '')
1302+
input_key_by_symbol(:ed_search_prev_history)
1303+
assert_line_around_cursor('12345', '')
1304+
input_key_by_symbol(:ed_search_prev_history)
1305+
assert_line_around_cursor('12aaa', '')
1306+
input_key_by_symbol(:ed_search_prev_history)
1307+
assert_line_around_cursor('12356', '')
1308+
input_key_by_symbol(:ed_search_next_history)
1309+
assert_line_around_cursor('12aaa', '')
1310+
input_key_by_symbol(:ed_search_next_history)
1311+
assert_line_around_cursor('12345', '')
1312+
input_key_by_symbol(:ed_search_prev_history)
1313+
assert_line_around_cursor('12aaa', '')
1314+
input_key_by_symbol(:ed_prev_char)
1315+
input_key_by_symbol(:ed_next_char)
1316+
input_key_by_symbol(:ed_search_next_history)
1317+
assert_line_around_cursor('12aaa', '')
1318+
3.times { input_key_by_symbol(:ed_prev_char) }
1319+
input_key_by_symbol(:ed_search_next_history)
1320+
assert_line_around_cursor('12', '345')
13061321
end
13071322

13081323
def test_incremental_search_history_cancel_by_symbol_key

0 commit comments

Comments
 (0)