[ruby/irb] Return only commands when completing help command's

argument
(https://github.com/ruby/irb/pull/973)

The command only takes command names as arguments, so we should only
return command names as candidates.

This will help users find a command faster as completion will be
another useful hint too.

https://github.com/ruby/irb/commit/7b6557cc24
This commit is contained in:
Stan Lo 2024-07-05 18:25:06 +01:00 committed by git
parent 1afcaa3e4b
commit 32ba86c9be
3 changed files with 42 additions and 11 deletions

View File

@ -33,6 +33,8 @@ module IRB
yield
]
HELP_COMMAND_PREPOSING = /\Ahelp\s+/
def completion_candidates(preposing, target, postposing, bind:)
raise NotImplementedError
end
@ -86,8 +88,8 @@ module IRB
)
end
def command_completions(preposing, target)
if preposing.empty? && !target.empty?
def command_candidates(target)
if !target.empty?
IRB::Command.command_names.select { _1.start_with?(target) }
else
[]
@ -111,8 +113,18 @@ module IRB
end
def completion_candidates(preposing, target, _postposing, bind:)
commands = command_completions(preposing, target)
# When completing the argument of `help` command, only commands should be candidates
return command_candidates(target) if preposing.match?(HELP_COMMAND_PREPOSING)
commands = if preposing.empty?
command_candidates(target)
# It doesn't make sense to propose commands with other preposing
else
[]
end
result = ReplTypeCompletor.analyze(preposing + target, binding: bind, filename: @context.irb_path)
return commands unless result
commands | result.completion_candidates.map { target + _1 }
@ -187,12 +199,20 @@ module IRB
end
def completion_candidates(preposing, target, postposing, bind:)
if preposing && postposing
result = complete_require_path(target, preposing, postposing)
return result if result
if result = complete_require_path(target, preposing, postposing)
return result
end
commands = command_completions(preposing || '', target)
commands | retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.map{ |i| i.encode(Encoding.default_external) }
commands = command_candidates(target)
# When completing the argument of `help` command, only commands should be candidates
return commands if preposing.match?(HELP_COMMAND_PREPOSING)
# It doesn't make sense to propose commands with other preposing
commands = [] unless preposing.empty?
completion_data = retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.map{ |i| i.encode(Encoding.default_external) }
commands | completion_data
end
def doc_namespace(_preposing, matched, _postposing, bind:)
@ -470,7 +490,7 @@ module IRB
end
end
CompletionProc = ->(target, preposing = nil, postposing = nil) {
regexp_completor.completion_candidates(preposing, target, postposing, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding)
regexp_completor.completion_candidates(preposing || '', target, postposing || '', bind: IRB.conf[:MAIN_CONTEXT].workspace.binding)
}
end
deprecate_constant :InputCompletor

View File

@ -16,8 +16,14 @@ module TestIRB
class CommandCompletionTest < CompletionTest
def test_command_completion
assert_include(IRB::RegexpCompletor.new.completion_candidates('', 'show_s', '', bind: binding), 'show_source')
assert_not_include(IRB::RegexpCompletor.new.completion_candidates(';', 'show_s', '', bind: binding), 'show_source')
completor = IRB::RegexpCompletor.new
binding.eval("some_var = 1")
# completion for help command's argument should only include command names
assert_include(completor.completion_candidates('help ', 's', '', bind: binding), 'show_source')
assert_not_include(completor.completion_candidates('help ', 's', '', bind: binding), 'some_var')
assert_include(completor.completion_candidates('', 'show_s', '', bind: binding), 'show_source')
assert_not_include(completor.completion_candidates(';', 'show_s', '', bind: binding), 'show_source')
end
end

View File

@ -56,6 +56,11 @@ module TestIRB
end
def test_command_completion
binding.eval("some_var = 1")
# completion for help command's argument should only include command names
assert_include(@completor.completion_candidates('help ', 's', '', bind: binding), 'show_source')
assert_not_include(@completor.completion_candidates('help ', 's', '', bind: binding), 'some_var')
assert_include(@completor.completion_candidates('', 'show_s', '', bind: binding), 'show_source')
assert_not_include(@completor.completion_candidates(';', 'show_s', '', bind: binding), 'show_source')
end