Merge branch 'refactor_command_completion' of https://github.com/rcorre/qutebrowser into rcorre-refactor_command_completion
This commit is contained in:
commit
26e0383d45
@ -75,7 +75,6 @@ class Command:
|
|||||||
deprecated: False, or a string to describe why a command is deprecated.
|
deprecated: False, or a string to describe why a command is deprecated.
|
||||||
desc: The description of the command.
|
desc: The description of the command.
|
||||||
handler: The handler function to call.
|
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).
|
debug: Whether this is a debugging command (only shown with --debug).
|
||||||
parser: The ArgumentParser to use to parse this command.
|
parser: The ArgumentParser to use to parse this command.
|
||||||
flags_with_args: A list of flags which take an argument.
|
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._qute_args = getattr(self.handler, 'qute_args', {})
|
||||||
self.handler.qute_args = None
|
self.handler.qute_args = None
|
||||||
|
|
||||||
args = self._inspect_func()
|
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)
|
|
||||||
|
|
||||||
def _check_prerequisites(self, win_id):
|
def _check_prerequisites(self, win_id):
|
||||||
"""Check if the command is permitted to run currently.
|
"""Check if the command is permitted to run currently.
|
||||||
@ -208,6 +201,11 @@ class Command:
|
|||||||
"""Get an ArgInfo tuple for the given inspect.Parameter."""
|
"""Get an ArgInfo tuple for the given inspect.Parameter."""
|
||||||
return self._qute_args.get(param.name, ArgInfo())
|
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):
|
def _inspect_special_param(self, param):
|
||||||
"""Check if the given parameter is a special one.
|
"""Check if the given parameter is a special one.
|
||||||
|
|
||||||
|
@ -204,25 +204,18 @@ class Completer(QObject):
|
|||||||
return sortfilter.CompletionFilterModel(source=model, parent=self)
|
return sortfilter.CompletionFilterModel(source=model, parent=self)
|
||||||
# delegate completion to command
|
# delegate completion to command
|
||||||
try:
|
try:
|
||||||
completions = cmdutils.cmd_dict[parts[0]].completion
|
cmd = cmdutils.cmd_dict[parts[0]]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# entering an unknown command
|
# entering an unknown command
|
||||||
return None
|
return None
|
||||||
if completions is None:
|
|
||||||
# command without any available completions
|
|
||||||
return None
|
|
||||||
dbg_completions = [c.name for c in completions]
|
|
||||||
try:
|
try:
|
||||||
idx = cursor_part - 1
|
idx = cursor_part - 1
|
||||||
completion = completions[idx]
|
completion = cmd.get_pos_arg_info(idx).completion
|
||||||
except IndexError:
|
except IndexError:
|
||||||
# More arguments than completions
|
# user provided more positional arguments than the command takes
|
||||||
log.completion.debug("completions: {}".format(
|
return None
|
||||||
', '.join(dbg_completions)))
|
if completion is None:
|
||||||
return 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)
|
model = self._get_completion_model(completion, parts, cursor_part)
|
||||||
return model
|
return model
|
||||||
|
|
||||||
|
@ -27,8 +27,7 @@ Module attributes:
|
|||||||
|
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
from qutebrowser.completion.models import (miscmodels, urlmodel, configmodel,
|
from qutebrowser.completion.models import miscmodels, urlmodel, configmodel
|
||||||
base)
|
|
||||||
from qutebrowser.utils import objreg, usertypes, log, debug
|
from qutebrowser.utils import objreg, usertypes, log, debug
|
||||||
from qutebrowser.config import configdata
|
from qutebrowser.config import configdata
|
||||||
|
|
||||||
@ -115,13 +114,6 @@ def init_session_completion():
|
|||||||
_instances[usertypes.Completion.sessions] = model
|
_instances[usertypes.Completion.sessions] = model
|
||||||
|
|
||||||
|
|
||||||
def _init_empty_completion():
|
|
||||||
"""Initialize empty completion model."""
|
|
||||||
log.completion.debug("Initializing empty completion.")
|
|
||||||
if usertypes.Completion.empty not in _instances:
|
|
||||||
_instances[usertypes.Completion.empty] = base.BaseCompletionModel()
|
|
||||||
|
|
||||||
|
|
||||||
INITIALIZERS = {
|
INITIALIZERS = {
|
||||||
usertypes.Completion.command: _init_command_completion,
|
usertypes.Completion.command: _init_command_completion,
|
||||||
usertypes.Completion.helptopic: _init_helptopic_completion,
|
usertypes.Completion.helptopic: _init_helptopic_completion,
|
||||||
@ -133,7 +125,6 @@ INITIALIZERS = {
|
|||||||
usertypes.Completion.quickmark_by_name: init_quickmark_completions,
|
usertypes.Completion.quickmark_by_name: init_quickmark_completions,
|
||||||
usertypes.Completion.bookmark_by_url: init_bookmark_completions,
|
usertypes.Completion.bookmark_by_url: init_bookmark_completions,
|
||||||
usertypes.Completion.sessions: init_session_completion,
|
usertypes.Completion.sessions: init_session_completion,
|
||||||
usertypes.Completion.empty: _init_empty_completion,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,7 +152,6 @@ class KeyConfigParser(QObject):
|
|||||||
|
|
||||||
@cmdutils.register(instance='key-config', maxsplit=1, no_cmd_split=True)
|
@cmdutils.register(instance='key-config', maxsplit=1, no_cmd_split=True)
|
||||||
@cmdutils.argument('win_id', win_id=True)
|
@cmdutils.argument('win_id', win_id=True)
|
||||||
@cmdutils.argument('key', completion=usertypes.Completion.empty)
|
|
||||||
@cmdutils.argument('command', completion=usertypes.Completion.command)
|
@cmdutils.argument('command', completion=usertypes.Completion.command)
|
||||||
def bind(self, key, win_id, command=None, *, mode='normal', force=False):
|
def bind(self, key, win_id, command=None, *, mode='normal', force=False):
|
||||||
"""Bind a key to a command.
|
"""Bind a key to a command.
|
||||||
|
@ -238,8 +238,7 @@ KeyMode = enum('KeyMode', ['normal', 'hint', 'command', 'yesno', 'prompt',
|
|||||||
# Available command completions
|
# Available command completions
|
||||||
Completion = enum('Completion', ['command', 'section', 'option', 'value',
|
Completion = enum('Completion', ['command', 'section', 'option', 'value',
|
||||||
'helptopic', 'quickmark_by_name',
|
'helptopic', 'quickmark_by_name',
|
||||||
'bookmark_by_url', 'url', 'tab', 'sessions',
|
'bookmark_by_url', 'url', 'tab', 'sessions'])
|
||||||
'empty'])
|
|
||||||
|
|
||||||
|
|
||||||
# Exit statuses for errors. Needs to be an int for sys.exit.
|
# Exit statuses for errors. Needs to be an int for sys.exit.
|
||||||
|
@ -291,6 +291,21 @@ class TestRegister:
|
|||||||
else:
|
else:
|
||||||
assert cmd._get_call_args(win_id=0) == ([expected], {})
|
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:
|
class TestArgument:
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ from PyQt5.QtGui import QStandardItemModel
|
|||||||
|
|
||||||
from qutebrowser.completion import completer
|
from qutebrowser.completion import completer
|
||||||
from qutebrowser.utils import usertypes
|
from qutebrowser.utils import usertypes
|
||||||
|
from qutebrowser.commands import command, cmdutils
|
||||||
|
|
||||||
|
|
||||||
class FakeCompletionModel(QStandardItemModel):
|
class FakeCompletionModel(QStandardItemModel):
|
||||||
@ -91,24 +92,48 @@ def instances(monkeypatch):
|
|||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def cmdutils_patch(monkeypatch, stubs):
|
def cmdutils_patch(monkeypatch, stubs):
|
||||||
"""Patch the cmdutils module to provide fake commands."""
|
"""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('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 = {
|
cmds = {
|
||||||
'set': [usertypes.Completion.section, usertypes.Completion.option,
|
'set': set_command,
|
||||||
usertypes.Completion.value],
|
'help': show_help,
|
||||||
'help': [usertypes.Completion.helptopic],
|
'open': openurl,
|
||||||
'quickmark-load': [usertypes.Completion.quickmark_by_name],
|
'bind': bind,
|
||||||
'bookmark-load': [usertypes.Completion.bookmark_by_url],
|
'tab-detach': tab_detach,
|
||||||
'open': [usertypes.Completion.url],
|
|
||||||
'buffer': [usertypes.Completion.tab],
|
|
||||||
'session-load': [usertypes.Completion.sessions],
|
|
||||||
'bind': [usertypes.Completion.empty, usertypes.Completion.command],
|
|
||||||
'tab-detach': None,
|
|
||||||
}
|
}
|
||||||
cmd_utils = stubs.FakeCmdUtils({
|
cmd_utils = stubs.FakeCmdUtils({
|
||||||
name: stubs.FakeCommand(completion=compl)
|
name: command.Command(name=name, handler=fn)
|
||||||
for name, compl in cmds.items()
|
for name, fn in cmds.items()
|
||||||
})
|
})
|
||||||
monkeypatch.setattr('qutebrowser.completion.completer.cmdutils',
|
monkeypatch.setattr('qutebrowser.completion.completer.cmdutils', cmd_utils)
|
||||||
cmd_utils)
|
|
||||||
|
|
||||||
|
|
||||||
def _set_cmd_prompt(cmd, txt):
|
def _set_cmd_prompt(cmd, txt):
|
||||||
@ -143,21 +168,17 @@ def _validate_cmd_prompt(cmd, txt):
|
|||||||
(':set general ignore-case |', usertypes.Completion.value),
|
(':set general ignore-case |', usertypes.Completion.value),
|
||||||
(':set general huh |', None),
|
(':set general huh |', None),
|
||||||
(':help |', usertypes.Completion.helptopic),
|
(':help |', usertypes.Completion.helptopic),
|
||||||
(':quickmark-load |', usertypes.Completion.quickmark_by_name),
|
(':help |', usertypes.Completion.helptopic),
|
||||||
(':bookmark-load |', usertypes.Completion.bookmark_by_url),
|
|
||||||
(':open |', usertypes.Completion.url),
|
(':open |', usertypes.Completion.url),
|
||||||
(':buffer |', usertypes.Completion.tab),
|
(':bind |', None),
|
||||||
(':session-load |', usertypes.Completion.sessions),
|
|
||||||
(':bind |', usertypes.Completion.empty),
|
|
||||||
(':bind <c-x> |', usertypes.Completion.command),
|
(':bind <c-x> |', usertypes.Completion.command),
|
||||||
(':bind <c-x> foo|', usertypes.Completion.command),
|
(':bind <c-x> foo|', usertypes.Completion.command),
|
||||||
(':bind <c-x>| foo', usertypes.Completion.empty),
|
(':bind <c-x>| foo', None),
|
||||||
(':set| general ', usertypes.Completion.command),
|
(':set| general ', usertypes.Completion.command),
|
||||||
(':|set general ', usertypes.Completion.command),
|
(':|set general ', usertypes.Completion.command),
|
||||||
(':set gene|ral ignore-case', usertypes.Completion.section),
|
(':set gene|ral ignore-case', usertypes.Completion.section),
|
||||||
(':|', usertypes.Completion.command),
|
(':|', usertypes.Completion.command),
|
||||||
(': |', usertypes.Completion.command),
|
(': |', usertypes.Completion.command),
|
||||||
(':bookmark-load |', usertypes.Completion.bookmark_by_url),
|
|
||||||
('/|', None),
|
('/|', None),
|
||||||
(':open -t|', None),
|
(':open -t|', None),
|
||||||
(':open --tab|', None),
|
(':open --tab|', None),
|
||||||
|
Loading…
Reference in New Issue
Block a user