Skip to content

Commit

Permalink
Return only commands when completing help command's argument
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
st0012 committed Jun 17, 2024
1 parent 35de7da commit 0eb9376
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 7 deletions.
31 changes: 26 additions & 5 deletions lib/irb/completion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ def defined? do
yield
]

HELP_COMMAND_PREPOSING = /\Ahelp\s+/

def completion_candidates(preposing, target, postposing, bind:)
raise NotImplementedError
end
Expand Down Expand Up @@ -86,8 +88,8 @@ def retrieve_files_to_require_from_load_path
)
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
[]
Expand All @@ -111,8 +113,17 @@ def inspect
end

def completion_candidates(preposing, target, _postposing, bind:)
commands = command_completions(preposing, target)
preposing ||= ''
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?

result = ReplTypeCompletor.analyze(preposing + target, binding: bind, filename: @context.irb_path)

return commands unless result

commands | result.completion_candidates.map { target + _1 }
Expand Down Expand Up @@ -191,8 +202,18 @@ def completion_candidates(preposing, target, postposing, bind:)
result = complete_require_path(target, preposing, postposing)
return result if 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) }

preposing ||= ''
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:)
Expand Down
10 changes: 8 additions & 2 deletions test/irb/test_completion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ def doc_namespace(target, bind)

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

Expand Down
5 changes: 5 additions & 0 deletions test/irb/test_type_completor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ def test_empty_completion
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
Expand Down

0 comments on commit 0eb9376

Please sign in to comment.