[ruby/reline] In ed_search_[prev|next]_history, make the cursor come
to the end of the line when there is no search substr (https://github.com/ruby/reline/pull/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 https://github.com/ruby/reline/commit/95ee80bd70
This commit is contained in:
parent
91d4a7ae0c
commit
5d33ff36dc
@ -45,6 +45,7 @@ class Reline::LineEditor
|
|||||||
RenderedScreen = Struct.new(:base_y, :lines, :cursor_y, keyword_init: true)
|
RenderedScreen = Struct.new(:base_y, :lines, :cursor_y, keyword_init: true)
|
||||||
|
|
||||||
CompletionJourneyState = Struct.new(:line_index, :pre, :target, :post, :list, :pointer)
|
CompletionJourneyState = Struct.new(:line_index, :pre, :target, :post, :list, :pointer)
|
||||||
|
NullActionState = [nil, nil].freeze
|
||||||
|
|
||||||
class MenuInfo
|
class MenuInfo
|
||||||
attr_reader :list
|
attr_reader :list
|
||||||
@ -253,6 +254,8 @@ class Reline::LineEditor
|
|||||||
@input_lines = [[[""], 0, 0]]
|
@input_lines = [[[""], 0, 0]]
|
||||||
@input_lines_position = 0
|
@input_lines_position = 0
|
||||||
@undoing = false
|
@undoing = false
|
||||||
|
@prev_action_state = NullActionState
|
||||||
|
@next_action_state = NullActionState
|
||||||
reset_line
|
reset_line
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1131,6 +1134,9 @@ class Reline::LineEditor
|
|||||||
else
|
else
|
||||||
normal_char(key)
|
normal_char(key)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@prev_action_state, @next_action_state = @next_action_state, NullActionState
|
||||||
|
|
||||||
unless @completion_occurs
|
unless @completion_occurs
|
||||||
@completion_state = CompletionState::NORMAL
|
@completion_state = CompletionState::NORMAL
|
||||||
@completion_journey_state = nil
|
@completion_journey_state = nil
|
||||||
@ -1761,29 +1767,31 @@ class Reline::LineEditor
|
|||||||
end
|
end
|
||||||
|
|
||||||
private def ed_search_prev_history(key, arg: 1)
|
private def ed_search_prev_history(key, arg: 1)
|
||||||
substr = current_line.byteslice(0, @byte_pointer)
|
substr = prev_action_state_value(:search_history) == :empty ? '' : current_line.byteslice(0, @byte_pointer)
|
||||||
return if @history_pointer == 0
|
return if @history_pointer == 0
|
||||||
return if @history_pointer.nil? && substr.empty? && !current_line.empty?
|
return if @history_pointer.nil? && substr.empty? && !current_line.empty?
|
||||||
|
|
||||||
history_range = 0...(@history_pointer || Reline::HISTORY.size)
|
history_range = 0...(@history_pointer || Reline::HISTORY.size)
|
||||||
h_pointer, line_index = search_history(substr, history_range.reverse_each)
|
h_pointer, line_index = search_history(substr, history_range.reverse_each)
|
||||||
return unless h_pointer
|
return unless h_pointer
|
||||||
move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer)
|
move_history(h_pointer, line: line_index || :start, cursor: substr.empty? ? :end : @byte_pointer)
|
||||||
arg -= 1
|
arg -= 1
|
||||||
|
set_next_action_state(:search_history, :empty) if substr.empty?
|
||||||
ed_search_prev_history(key, arg: arg) if arg > 0
|
ed_search_prev_history(key, arg: arg) if arg > 0
|
||||||
end
|
end
|
||||||
alias_method :history_search_backward, :ed_search_prev_history
|
alias_method :history_search_backward, :ed_search_prev_history
|
||||||
|
|
||||||
private def ed_search_next_history(key, arg: 1)
|
private def ed_search_next_history(key, arg: 1)
|
||||||
substr = current_line.byteslice(0, @byte_pointer)
|
substr = prev_action_state_value(:search_history) == :empty ? '' : current_line.byteslice(0, @byte_pointer)
|
||||||
return if @history_pointer.nil?
|
return if @history_pointer.nil?
|
||||||
|
|
||||||
history_range = @history_pointer + 1...Reline::HISTORY.size
|
history_range = @history_pointer + 1...Reline::HISTORY.size
|
||||||
h_pointer, line_index = search_history(substr, history_range)
|
h_pointer, line_index = search_history(substr, history_range)
|
||||||
return if h_pointer.nil? and not substr.empty?
|
return if h_pointer.nil? and not substr.empty?
|
||||||
|
|
||||||
move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer)
|
move_history(h_pointer, line: line_index || :start, cursor: substr.empty? ? :end : @byte_pointer)
|
||||||
arg -= 1
|
arg -= 1
|
||||||
|
set_next_action_state(:search_history, :empty) if substr.empty?
|
||||||
ed_search_next_history(key, arg: arg) if arg > 0
|
ed_search_next_history(key, arg: arg) if arg > 0
|
||||||
end
|
end
|
||||||
alias_method :history_search_forward, :ed_search_next_history
|
alias_method :history_search_forward, :ed_search_next_history
|
||||||
@ -2549,4 +2557,12 @@ class Reline::LineEditor
|
|||||||
target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
|
target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
|
||||||
set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
|
set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private def prev_action_state_value(type)
|
||||||
|
@prev_action_state[0] == type ? @prev_action_state[1] : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
private def set_next_action_state(type, value)
|
||||||
|
@next_action_state = [type, value]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1242,14 +1242,22 @@ class Reline::KeyActor::EmacsTest < Reline::TestCase
|
|||||||
'12345' # new
|
'12345' # new
|
||||||
])
|
])
|
||||||
# The ed_search_prev_history doesn't have default binding
|
# The ed_search_prev_history doesn't have default binding
|
||||||
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
|
input_key_by_symbol(:ed_search_prev_history)
|
||||||
assert_line_around_cursor('', '12345')
|
assert_line_around_cursor('12345', '')
|
||||||
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
|
input_key_by_symbol(:ed_search_prev_history)
|
||||||
assert_line_around_cursor('', '12aaa')
|
assert_line_around_cursor('12aaa', '')
|
||||||
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
|
input_key_by_symbol(:ed_search_prev_history)
|
||||||
assert_line_around_cursor('', '12356')
|
assert_line_around_cursor('12356', '')
|
||||||
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
|
input_key_by_symbol(:ed_search_next_history)
|
||||||
assert_line_around_cursor('', '12356')
|
assert_line_around_cursor('12aaa', '')
|
||||||
|
input_key_by_symbol(:ed_prev_char)
|
||||||
|
input_key_by_symbol(:ed_next_char)
|
||||||
|
assert_line_around_cursor('12aaa', '')
|
||||||
|
input_key_by_symbol(:ed_search_prev_history)
|
||||||
|
assert_line_around_cursor('12aaa', '')
|
||||||
|
3.times { input_key_by_symbol(:ed_prev_char) }
|
||||||
|
input_key_by_symbol(:ed_search_prev_history)
|
||||||
|
assert_line_around_cursor('12', '356')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_ed_search_prev_history_without_match
|
def test_ed_search_prev_history_without_match
|
||||||
@ -1291,18 +1299,25 @@ class Reline::KeyActor::EmacsTest < Reline::TestCase
|
|||||||
'12345' # new
|
'12345' # new
|
||||||
])
|
])
|
||||||
# The ed_search_prev_history and ed_search_next_history doesn't have default binding
|
# The ed_search_prev_history and ed_search_next_history doesn't have default binding
|
||||||
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
|
input_key_by_symbol(:ed_search_prev_history)
|
||||||
assert_line_around_cursor('', '12345')
|
assert_line_around_cursor('12345', '')
|
||||||
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
|
input_key_by_symbol(:ed_search_prev_history)
|
||||||
assert_line_around_cursor('', '12aaa')
|
assert_line_around_cursor('12aaa', '')
|
||||||
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
|
input_key_by_symbol(:ed_search_prev_history)
|
||||||
assert_line_around_cursor('', '12356')
|
assert_line_around_cursor('12356', '')
|
||||||
@line_editor.__send__(:ed_search_next_history, "\C-n".ord)
|
input_key_by_symbol(:ed_search_next_history)
|
||||||
assert_line_around_cursor('', '12aaa')
|
assert_line_around_cursor('12aaa', '')
|
||||||
@line_editor.__send__(:ed_search_next_history, "\C-n".ord)
|
input_key_by_symbol(:ed_search_next_history)
|
||||||
assert_line_around_cursor('', '12345')
|
assert_line_around_cursor('12345', '')
|
||||||
@line_editor.__send__(:ed_search_next_history, "\C-n".ord)
|
input_key_by_symbol(:ed_search_prev_history)
|
||||||
assert_line_around_cursor('', '')
|
assert_line_around_cursor('12aaa', '')
|
||||||
|
input_key_by_symbol(:ed_prev_char)
|
||||||
|
input_key_by_symbol(:ed_next_char)
|
||||||
|
input_key_by_symbol(:ed_search_next_history)
|
||||||
|
assert_line_around_cursor('12aaa', '')
|
||||||
|
3.times { input_key_by_symbol(:ed_prev_char) }
|
||||||
|
input_key_by_symbol(:ed_search_next_history)
|
||||||
|
assert_line_around_cursor('12', '345')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_incremental_search_history_cancel_by_symbol_key
|
def test_incremental_search_history_cancel_by_symbol_key
|
||||||
|
Loading…
x
Reference in New Issue
Block a user