1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Show a menu before a document

IRB should show a menu first if a completed list has plural items. But just
shows document without menu if a completed list with plural items includes a
perfect matched item. The behavior is a bug. This commit fixes it.
This commit is contained in:
aycabta 2019-12-13 03:57:32 +09:00
parent b8d6c883b3
commit c2dfc6d869
2 changed files with 81 additions and 5 deletions

View file

@ -43,6 +43,7 @@ class Reline::LineEditor
COMPLETION = :completion COMPLETION = :completion
MENU = :menu MENU = :menu
JOURNEY = :journey JOURNEY = :journey
MENU_WITH_PERFECT_MATCH = :menu_with_perfect_match
PERFECT_MATCH = :perfect_match PERFECT_MATCH = :perfect_match
end end
@ -599,16 +600,24 @@ class Reline::LineEditor
when CompletionState::PERFECT_MATCH when CompletionState::PERFECT_MATCH
@dig_perfect_match_proc&.(@perfect_matched) @dig_perfect_match_proc&.(@perfect_matched)
end end
is_menu = (@completion_state == CompletionState::MENU) is_menu = (@completion_state == CompletionState::MENU or @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH)
result = complete_internal_proc(list, is_menu) result = complete_internal_proc(list, is_menu)
if @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH
@completion_state = CompletionState::PERFECT_MATCH
end
return if result.nil? return if result.nil?
target, preposing, completed, postposing = result target, preposing, completed, postposing = result
return if completed.nil? return if completed.nil?
if target <= completed and (@completion_state == CompletionState::COMPLETION or @completion_state == CompletionState::PERFECT_MATCH) if target <= completed and (@completion_state == CompletionState::COMPLETION)
@completion_state = CompletionState::MENU
if list.include?(completed) if list.include?(completed)
@completion_state = CompletionState::PERFECT_MATCH if list.one?
@completion_state = CompletionState::PERFECT_MATCH
else
@completion_state = CompletionState::MENU_WITH_PERFECT_MATCH
end
@perfect_matched = completed @perfect_matched = completed
else
@completion_state = CompletionState::MENU
end end
if target < completed if target < completed
@line = preposing + completed + postposing @line = preposing + completed + postposing
@ -622,7 +631,8 @@ class Reline::LineEditor
private def move_completed_list(list, direction) private def move_completed_list(list, direction)
case @completion_state case @completion_state
when CompletionState::NORMAL, CompletionState::COMPLETION, CompletionState::MENU when CompletionState::NORMAL, CompletionState::COMPLETION,
CompletionState::MENU, CompletionState::MENU_WITH_PERFECT_MATCH
@completion_state = CompletionState::JOURNEY @completion_state = CompletionState::JOURNEY
result = retrieve_completion_block result = retrieve_completion_block
return if result.nil? return if result.nil?

View file

@ -1287,6 +1287,72 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
assert_line('foo_ba') assert_line('foo_ba')
end end
def test_completion_with_perfect_match
@line_editor.completion_proc = proc { |word|
%w{
foo
foo_bar
}.map { |i|
i.encode(@encoding)
}
}
matched = nil
@line_editor.dig_perfect_match_proc = proc { |m|
matched = m
}
input_keys('fo')
assert_byte_pointer_size('fo')
assert_cursor(2)
assert_cursor_max(2)
assert_line('fo')
assert_equal(Reline::LineEditor::CompletionState::NORMAL, @line_editor.instance_variable_get(:@completion_state))
assert_equal(nil, matched)
input_keys("\C-i", false)
assert_byte_pointer_size('foo')
assert_cursor(3)
assert_cursor_max(3)
assert_line('foo')
assert_equal(Reline::LineEditor::CompletionState::MENU_WITH_PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal(nil, matched)
input_keys("\C-i", false)
assert_byte_pointer_size('foo')
assert_cursor(3)
assert_cursor_max(3)
assert_line('foo')
assert_equal(Reline::LineEditor::CompletionState::PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal(nil, matched)
input_keys("\C-i", false)
assert_byte_pointer_size('foo')
assert_cursor(3)
assert_cursor_max(3)
assert_line('foo')
assert_equal(Reline::LineEditor::CompletionState::PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal('foo', matched)
matched = nil
input_keys('_')
input_keys("\C-i", false)
assert_byte_pointer_size('foo_bar')
assert_cursor(7)
assert_cursor_max(7)
assert_line('foo_bar')
assert_equal(Reline::LineEditor::CompletionState::MENU_WITH_PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal(nil, matched)
input_keys("\C-i", false)
assert_byte_pointer_size('foo_bar')
assert_cursor(7)
assert_cursor_max(7)
assert_line('foo_bar')
assert_equal(Reline::LineEditor::CompletionState::PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal(nil, matched)
input_keys("\C-i", false)
assert_byte_pointer_size('foo_bar')
assert_cursor(7)
assert_cursor_max(7)
assert_line('foo_bar')
assert_equal(Reline::LineEditor::CompletionState::PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal('foo_bar', matched)
end
def test_completion_with_completion_ignore_case def test_completion_with_completion_ignore_case
@line_editor.completion_proc = proc { |word| @line_editor.completion_proc = proc { |word|
%w{ %w{