Remove Command.completion.

Command completion types are now identified by ArgInfo, so just use
that directly and cut out the middle-man. This shouldn't change any
completion behavior.

Adds a test for get_pos_arg_info to test_cmdutils.

Modifies test_completer to test the use of get_pos_arg_info. Instead of
using FakeCommand, real Command objects are used, to validate that the
Completer works with the real Command interface. This also cleans out
some test cases that were testing things already covered by other cases.
This commit is contained in:
Ryan Roden-Corrent 2016-06-07 20:20:56 -04:00
parent 778ccad39f
commit c792ffda67
4 changed files with 67 additions and 39 deletions

View File

@ -75,7 +75,6 @@ class Command:
deprecated: False, or a string to describe why a command is deprecated.
desc: The description of the command.
handler: The handler function to call.
completion: Completions to use for arguments, as a list of strings.
debug: Whether this is a debugging command (only shown with --debug).
parser: The ArgumentParser to use to parse this command.
flags_with_args: A list of flags which take an argument.
@ -148,13 +147,7 @@ class Command:
self._qute_args = getattr(self.handler, 'qute_args', {})
self.handler.qute_args = None
args = self._inspect_func()
self.completion = []
for arg in args:
arg_completion = self.get_arg_info(arg).completion
if arg_completion is not None:
self.completion.append(arg_completion)
self._inspect_func()
def _check_prerequisites(self, win_id):
"""Check if the command is permitted to run currently.
@ -208,6 +201,11 @@ class Command:
"""Get an ArgInfo tuple for the given inspect.Parameter."""
return self._qute_args.get(param.name, ArgInfo())
def get_pos_arg_info(self, pos):
"""Get an ArgInfo tuple for the given positional parameter."""
name = self.pos_args[pos][0]
return self._qute_args.get(name, ArgInfo())
def _inspect_special_param(self, param):
"""Check if the given parameter is a special one.

View File

@ -204,25 +204,18 @@ class Completer(QObject):
return sortfilter.CompletionFilterModel(source=model, parent=self)
# delegate completion to command
try:
completions = cmdutils.cmd_dict[parts[0]].completion
cmd = cmdutils.cmd_dict[parts[0]]
except KeyError:
# entering an unknown command
return None
if completions is None:
# command without any available completions
return None
dbg_completions = [c.name for c in completions]
try:
idx = cursor_part - 1
completion = completions[idx]
completion = cmd.get_pos_arg_info(idx).completion
except IndexError:
# More arguments than completions
log.completion.debug("completions: {}".format(
', '.join(dbg_completions)))
# user provided more positional arguments than the command takes
return None
if completion is None:
return None
dbg_completions[idx] = '*' + dbg_completions[idx] + '*'
log.completion.debug("completions: {}".format(
', '.join(dbg_completions)))
model = self._get_completion_model(completion, parts, cursor_part)
return model

View File

@ -291,6 +291,21 @@ class TestRegister:
else:
assert cmd._get_call_args(win_id=0) == ([expected], {})
def test_pos_arg_info(self):
@cmdutils.register()
@cmdutils.argument('foo', choices=('a', 'b'))
@cmdutils.argument('bar', choices=('x', 'y'))
@cmdutils.argument('opt')
def fun(foo, bar, opt=False):
"""Blah."""
pass
cmd = cmdutils.cmd_dict['fun']
assert cmd.get_pos_arg_info(0) == command.ArgInfo(choices=('a', 'b'))
assert cmd.get_pos_arg_info(1) == command.ArgInfo(choices=('x', 'y'))
with pytest.raises(IndexError):
cmd.get_pos_arg_info(2)
class TestArgument:

View File

@ -27,6 +27,7 @@ from PyQt5.QtGui import QStandardItemModel
from qutebrowser.completion import completer
from qutebrowser.utils import usertypes
from qutebrowser.commands import command, cmdutils
class FakeCompletionModel(QStandardItemModel):
@ -91,24 +92,49 @@ def instances(monkeypatch):
@pytest.fixture(autouse=True)
def cmdutils_patch(monkeypatch, stubs):
"""Patch the cmdutils module to provide fake commands."""
@cmdutils.argument('section_', completion=usertypes.Completion.section)
@cmdutils.argument('option', completion=usertypes.Completion.option)
@cmdutils.argument('value', completion=usertypes.Completion.value)
def set_command(section_=None, option=None, value=None):
"""docstring!"""
pass
@cmdutils.argument('topic', completion=usertypes.Completion.helptopic)
def show_help(tab=False, bg=False, window=False, topic=None):
"""docstring!"""
pass
@cmdutils.argument('url', completion=usertypes.Completion.url)
@cmdutils.argument('count', count=True)
def openurl(url=None, implicit=False, bg=False, tab=False, window=False,
count=None):
"""docstring!"""
pass
@cmdutils.argument('win_id', win_id=True)
@cmdutils.argument('key', completion=usertypes.Completion.empty)
@cmdutils.argument('command', completion=usertypes.Completion.command)
def bind(key, win_id, command=None, *, mode='normal', force=False):
"""docstring!"""
# pylint: disable=unused-variable
pass
def tab_detach():
"""docstring!"""
pass
cmds = {
'set': [usertypes.Completion.section, usertypes.Completion.option,
usertypes.Completion.value],
'help': [usertypes.Completion.helptopic],
'quickmark-load': [usertypes.Completion.quickmark_by_name],
'bookmark-load': [usertypes.Completion.bookmark_by_url],
'open': [usertypes.Completion.url],
'buffer': [usertypes.Completion.tab],
'session-load': [usertypes.Completion.sessions],
'bind': [usertypes.Completion.empty, usertypes.Completion.command],
'tab-detach': None,
'set': set_command,
'help': show_help,
'open': openurl,
'bind': bind,
'tab-detach': tab_detach,
}
cmd_utils = stubs.FakeCmdUtils({
name: stubs.FakeCommand(completion=compl)
for name, compl in cmds.items()
name: command.Command(name=name, handler=fn)
for name, fn in cmds.items()
})
monkeypatch.setattr('qutebrowser.completion.completer.cmdutils',
cmd_utils)
monkeypatch.setattr('qutebrowser.completion.completer.cmdutils', cmd_utils)
def _set_cmd_prompt(cmd, txt):
@ -143,11 +169,8 @@ def _validate_cmd_prompt(cmd, txt):
(':set general ignore-case |', usertypes.Completion.value),
(':set general huh |', None),
(':help |', usertypes.Completion.helptopic),
(':quickmark-load |', usertypes.Completion.quickmark_by_name),
(':bookmark-load |', usertypes.Completion.bookmark_by_url),
(':help |', usertypes.Completion.helptopic),
(':open |', usertypes.Completion.url),
(':buffer |', usertypes.Completion.tab),
(':session-load |', usertypes.Completion.sessions),
(':bind |', usertypes.Completion.empty),
(':bind <c-x> |', usertypes.Completion.command),
(':bind <c-x> foo|', usertypes.Completion.command),
@ -157,7 +180,6 @@ def _validate_cmd_prompt(cmd, txt):
(':set gene|ral ignore-case', usertypes.Completion.section),
(':|', usertypes.Completion.command),
(': |', usertypes.Completion.command),
(':bookmark-load |', usertypes.Completion.bookmark_by_url),
('/|', None),
(':open -t|', None),
(':open --tab|', None),