Remove completion.instances, usertypes.Completion.
The new completion API no longer needs either of these. Instead of referencing an enum member, cmdutils.argument.completion now points to a function that returnsthe desired completion model. This vastly simplifies the addition of new completion types. Previously it was necessary to define the new model as well as editing usertypes and completion.models.instances. Now it is only necessary to define a single function under completion.models. This is the next step of Completion Model/View Revamping (#74).
This commit is contained in:
parent
b36cf0572d
commit
3b30b42211
@ -42,7 +42,7 @@ except ImportError:
|
||||
|
||||
import qutebrowser
|
||||
import qutebrowser.resources
|
||||
from qutebrowser.completion.models import instances as completionmodels
|
||||
from qutebrowser.completion.models import miscmodels
|
||||
from qutebrowser.commands import cmdutils, runners, cmdexc
|
||||
from qutebrowser.config import style, config, websettings, configexc
|
||||
from qutebrowser.browser import (urlmarks, adblock, history, browsertab,
|
||||
@ -459,9 +459,6 @@ def _init_modules(args, crash_handler):
|
||||
diskcache = cache.DiskCache(standarddir.cache(), parent=qApp)
|
||||
objreg.register('cache', diskcache)
|
||||
|
||||
log.init.debug("Initializing completions...")
|
||||
completionmodels.init()
|
||||
|
||||
log.init.debug("Misc initialization...")
|
||||
if config.get('ui', 'hide-wayland-decoration'):
|
||||
os.environ['QT_WAYLAND_DISABLE_WINDOWDECORATION'] = '1'
|
||||
@ -753,7 +750,7 @@ class Quitter:
|
||||
QTimer.singleShot(0, functools.partial(qApp.exit, status))
|
||||
|
||||
@cmdutils.register(instance='quitter', name='wq')
|
||||
@cmdutils.argument('name', completion=usertypes.Completion.sessions)
|
||||
@cmdutils.argument('name', completion=miscmodels.session)
|
||||
def save_and_quit(self, name=sessions.default):
|
||||
"""Save open pages and quit.
|
||||
|
||||
|
@ -41,7 +41,7 @@ from qutebrowser.utils import (message, usertypes, log, qtutils, urlutils,
|
||||
objreg, utils, typing)
|
||||
from qutebrowser.utils.usertypes import KeyMode
|
||||
from qutebrowser.misc import editor, guiprocess
|
||||
from qutebrowser.completion.models import instances, sortfilter
|
||||
from qutebrowser.completion.models import sortfilter, urlmodel, miscmodels
|
||||
|
||||
|
||||
class CommandDispatcher:
|
||||
@ -284,7 +284,7 @@ class CommandDispatcher:
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', name='open',
|
||||
maxsplit=0, scope='window')
|
||||
@cmdutils.argument('url', completion=usertypes.Completion.url)
|
||||
@cmdutils.argument('url', completion=urlmodel.url)
|
||||
@cmdutils.argument('count', count=True)
|
||||
def openurl(self, url=None, implicit=False,
|
||||
bg=False, tab=False, window=False, count=None, secure=False,
|
||||
@ -1007,7 +1007,7 @@ class CommandDispatcher:
|
||||
self._open(url, tab, bg, window)
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||
@cmdutils.argument('index', completion=usertypes.Completion.tab)
|
||||
@cmdutils.argument('index', completion=miscmodels.buffer)
|
||||
def buffer(self, index):
|
||||
"""Select tab by index or url/title best match.
|
||||
|
||||
@ -1023,7 +1023,7 @@ class CommandDispatcher:
|
||||
for part in index_parts:
|
||||
int(part)
|
||||
except ValueError:
|
||||
model = instances.get(usertypes.Completion.tab)
|
||||
model = miscmodels.buffer()
|
||||
sf = sortfilter.CompletionFilterModel(source=model)
|
||||
sf.set_pattern(index)
|
||||
if sf.count() > 0:
|
||||
@ -1229,8 +1229,7 @@ class CommandDispatcher:
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', scope='window',
|
||||
maxsplit=0)
|
||||
@cmdutils.argument('name',
|
||||
completion=usertypes.Completion.quickmark_by_name)
|
||||
@cmdutils.argument('name', completion=miscmodels.quickmark)
|
||||
def quickmark_load(self, name, tab=False, bg=False, window=False):
|
||||
"""Load a quickmark.
|
||||
|
||||
@ -1248,8 +1247,7 @@ class CommandDispatcher:
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', scope='window',
|
||||
maxsplit=0)
|
||||
@cmdutils.argument('name',
|
||||
completion=usertypes.Completion.quickmark_by_name)
|
||||
@cmdutils.argument('name', completion=miscmodels.quickmark)
|
||||
def quickmark_del(self, name=None):
|
||||
"""Delete a quickmark.
|
||||
|
||||
@ -1311,7 +1309,7 @@ class CommandDispatcher:
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', scope='window',
|
||||
maxsplit=0)
|
||||
@cmdutils.argument('url', completion=usertypes.Completion.bookmark_by_url)
|
||||
@cmdutils.argument('url', completion=miscmodels.bookmark)
|
||||
def bookmark_load(self, url, tab=False, bg=False, window=False,
|
||||
delete=False):
|
||||
"""Load a bookmark.
|
||||
@ -1333,7 +1331,7 @@ class CommandDispatcher:
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', scope='window',
|
||||
maxsplit=0)
|
||||
@cmdutils.argument('url', completion=usertypes.Completion.bookmark_by_url)
|
||||
@cmdutils.argument('url', completion=miscmodels.bookmark)
|
||||
def bookmark_del(self, url=None):
|
||||
"""Delete a bookmark.
|
||||
|
||||
@ -1507,7 +1505,7 @@ class CommandDispatcher:
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', name='help',
|
||||
scope='window')
|
||||
@cmdutils.argument('topic', completion=usertypes.Completion.helptopic)
|
||||
@cmdutils.argument('topic', completion=miscmodels.helptopic)
|
||||
def show_help(self, tab=False, bg=False, window=False, topic=None):
|
||||
r"""Show help about a command or setting.
|
||||
|
||||
|
@ -23,8 +23,8 @@ from PyQt5.QtCore import pyqtSlot, QObject, QTimer
|
||||
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.commands import cmdutils, runners
|
||||
from qutebrowser.utils import usertypes, log, utils
|
||||
from qutebrowser.completion.models import instances, sortfilter
|
||||
from qutebrowser.utils import log, utils
|
||||
from qutebrowser.completion.models import sortfilter, miscmodels
|
||||
|
||||
|
||||
class Completer(QObject):
|
||||
@ -72,7 +72,7 @@ class Completer(QObject):
|
||||
Return:
|
||||
A completion model or None.
|
||||
"""
|
||||
model = instances.get(completion)(*pos_args)
|
||||
model = completion(*pos_args)
|
||||
if model is None:
|
||||
return None
|
||||
else:
|
||||
@ -96,7 +96,7 @@ class Completer(QObject):
|
||||
log.completion.debug("After removing flags: {}".format(before_cursor))
|
||||
if not before_cursor:
|
||||
# '|' or 'set|'
|
||||
model = instances.get(usertypes.Completion.command)()
|
||||
model = miscmodels.command()
|
||||
return sortfilter.CompletionFilterModel(source=model, parent=self)
|
||||
try:
|
||||
cmd = cmdutils.cmd_dict[before_cursor[0]]
|
||||
|
@ -1,53 +0,0 @@
|
||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||
|
||||
# Copyright 2015-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||
#
|
||||
# This file is part of qutebrowser.
|
||||
#
|
||||
# qutebrowser is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# qutebrowser is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Global instances of the completion models."""
|
||||
|
||||
from qutebrowser.utils import usertypes
|
||||
from qutebrowser.completion.models import miscmodels, urlmodel, configmodel
|
||||
|
||||
|
||||
def get(completion):
|
||||
"""Get a certain completion. Initializes the completion if needed."""
|
||||
if completion == usertypes.Completion.command:
|
||||
return miscmodels.command
|
||||
if completion == usertypes.Completion.helptopic:
|
||||
return miscmodels.helptopic
|
||||
if completion == usertypes.Completion.tab:
|
||||
return miscmodels.buffer
|
||||
if completion == usertypes.Completion.quickmark_by_name:
|
||||
return miscmodels.quickmark
|
||||
if completion == usertypes.Completion.bookmark_by_url:
|
||||
return miscmodels.bookmark
|
||||
if completion == usertypes.Completion.sessions:
|
||||
return miscmodels.session
|
||||
if completion == usertypes.Completion.bind:
|
||||
return miscmodels.bind
|
||||
if completion == usertypes.Completion.section:
|
||||
return configmodel.section
|
||||
if completion == usertypes.Completion.option:
|
||||
return configmodel.option
|
||||
if completion == usertypes.Completion.value:
|
||||
return configmodel.value
|
||||
if completion == usertypes.Completion.url:
|
||||
return urlmodel.url
|
||||
|
||||
|
||||
def init():
|
||||
pass
|
@ -43,7 +43,7 @@ from qutebrowser.commands import cmdexc, cmdutils
|
||||
from qutebrowser.utils import (message, objreg, utils, standarddir, log,
|
||||
qtutils, error, usertypes)
|
||||
from qutebrowser.misc import objects
|
||||
from qutebrowser.utils.usertypes import Completion
|
||||
from qutebrowser.completion.models import configmodel
|
||||
|
||||
|
||||
UNSET = object()
|
||||
@ -794,9 +794,9 @@ class ConfigManager(QObject):
|
||||
e.__class__.__name__, e))
|
||||
|
||||
@cmdutils.register(name='set', instance='config', star_args_optional=True)
|
||||
@cmdutils.argument('section_', completion=Completion.section)
|
||||
@cmdutils.argument('option', completion=Completion.option)
|
||||
@cmdutils.argument('values', completion=Completion.value)
|
||||
@cmdutils.argument('section_', completion=configmodel.section)
|
||||
@cmdutils.argument('option', completion=configmodel.option)
|
||||
@cmdutils.argument('values', completion=configmodel.value)
|
||||
@cmdutils.argument('win_id', win_id=True)
|
||||
def set_command(self, win_id, section_=None, option=None, *values,
|
||||
temp=False, print_=False):
|
||||
|
@ -27,7 +27,8 @@ from PyQt5.QtCore import pyqtSignal, QObject
|
||||
|
||||
from qutebrowser.config import configdata, textwrapper
|
||||
from qutebrowser.commands import cmdutils, cmdexc
|
||||
from qutebrowser.utils import log, utils, qtutils, message, usertypes
|
||||
from qutebrowser.utils import log, utils, qtutils, message
|
||||
from qutebrowser.completion.models import miscmodels
|
||||
|
||||
|
||||
class KeyConfigError(Exception):
|
||||
@ -153,7 +154,7 @@ class KeyConfigParser(QObject):
|
||||
|
||||
@cmdutils.register(instance='key-config', maxsplit=1, no_cmd_split=True,
|
||||
no_replace_variables=True)
|
||||
@cmdutils.argument('command', completion=usertypes.Completion.bind)
|
||||
@cmdutils.argument('command', completion=miscmodels.bind)
|
||||
def bind(self, key, command=None, *, mode='normal', force=False):
|
||||
"""Bind a key to a command.
|
||||
|
||||
|
@ -31,10 +31,11 @@ try:
|
||||
except ImportError: # pragma: no cover
|
||||
from yaml import SafeLoader as YamlLoader, SafeDumper as YamlDumper
|
||||
|
||||
from qutebrowser.utils import (standarddir, objreg, qtutils, log, usertypes,
|
||||
message, utils)
|
||||
from qutebrowser.utils import (standarddir, objreg, qtutils, log, message,
|
||||
utils)
|
||||
from qutebrowser.commands import cmdexc, cmdutils
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.completion.models import miscmodels
|
||||
|
||||
|
||||
default = object() # Sentinel value
|
||||
@ -433,7 +434,7 @@ class SessionManager(QObject):
|
||||
return sessions
|
||||
|
||||
@cmdutils.register(instance='session-manager')
|
||||
@cmdutils.argument('name', completion=usertypes.Completion.sessions)
|
||||
@cmdutils.argument('name', completion=miscmodels.session)
|
||||
def session_load(self, name, clear=False, temp=False, force=False):
|
||||
"""Load a session.
|
||||
|
||||
@ -461,7 +462,7 @@ class SessionManager(QObject):
|
||||
win.close()
|
||||
|
||||
@cmdutils.register(name=['session-save', 'w'], instance='session-manager')
|
||||
@cmdutils.argument('name', completion=usertypes.Completion.sessions)
|
||||
@cmdutils.argument('name', completion=miscmodels.session)
|
||||
@cmdutils.argument('win_id', win_id=True)
|
||||
@cmdutils.argument('with_private', flag='p')
|
||||
def session_save(self, name: str = default, current=False, quiet=False,
|
||||
@ -500,7 +501,7 @@ class SessionManager(QObject):
|
||||
message.info("Saved session {}.".format(name))
|
||||
|
||||
@cmdutils.register(instance='session-manager')
|
||||
@cmdutils.argument('name', completion=usertypes.Completion.sessions)
|
||||
@cmdutils.argument('name', completion=miscmodels.session)
|
||||
def session_delete(self, name, force=False):
|
||||
"""Delete a session.
|
||||
|
||||
|
@ -236,13 +236,6 @@ KeyMode = enum('KeyMode', ['normal', 'hint', 'command', 'yesno', 'prompt',
|
||||
'jump_mark', 'record_macro', 'run_macro'])
|
||||
|
||||
|
||||
# Available command completions
|
||||
Completion = enum('Completion', ['command', 'section', 'option', 'value',
|
||||
'helptopic', 'quickmark_by_name',
|
||||
'bookmark_by_url', 'url', 'tab', 'sessions',
|
||||
'bind'])
|
||||
|
||||
|
||||
# Exit statuses for errors. Needs to be an int for sys.exit.
|
||||
Exit = enum('Exit', ['ok', 'reserved', 'exception', 'err_ipc', 'err_init',
|
||||
'err_config', 'err_key_config'], is_int=True, start=0)
|
||||
|
@ -26,7 +26,6 @@ from PyQt5.QtCore import QObject
|
||||
from PyQt5.QtGui import QStandardItemModel
|
||||
|
||||
from qutebrowser.completion import completer
|
||||
from qutebrowser.utils import usertypes
|
||||
from qutebrowser.commands import command, cmdutils
|
||||
|
||||
|
||||
@ -70,30 +69,45 @@ def completer_obj(qtbot, status_command_stub, config_stub, monkeypatch, stubs,
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def instances(monkeypatch):
|
||||
"""Mock the instances module so get returns a fake completion model."""
|
||||
# populate a model for each completion type, with a nested structure for
|
||||
# option and value completion
|
||||
get = lambda kind: lambda *args: FakeCompletionModel(kind, *args)
|
||||
monkeypatch.setattr(completer, 'instances', get)
|
||||
def miscmodels_patch(mocker):
|
||||
"""Patch the miscmodels module to provide fake completion functions.
|
||||
|
||||
Technically some of these are not part of miscmodels, but rolling them into
|
||||
one module is easier and sufficient for mocking. The only one referenced
|
||||
directly by Completer is miscmodels.command.
|
||||
"""
|
||||
m = mocker.patch('qutebrowser.completion.completer.miscmodels',
|
||||
autospec=True)
|
||||
m.command = lambda *args: FakeCompletionModel('command', *args)
|
||||
m.helptopic = lambda *args: FakeCompletionModel('helptopic', *args)
|
||||
m.quickmark = lambda *args: FakeCompletionModel('quickmark', *args)
|
||||
m.bookmark = lambda *args: FakeCompletionModel('bookmark', *args)
|
||||
m.session = lambda *args: FakeCompletionModel('session', *args)
|
||||
m.buffer = lambda *args: FakeCompletionModel('buffer', *args)
|
||||
m.bind = lambda *args: FakeCompletionModel('bind', *args)
|
||||
m.url = lambda *args: FakeCompletionModel('url', *args)
|
||||
m.section = lambda *args: FakeCompletionModel('section', *args)
|
||||
m.option = lambda *args: FakeCompletionModel('option', *args)
|
||||
m.value = lambda *args: FakeCompletionModel('value', *args)
|
||||
return m
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def cmdutils_patch(monkeypatch, stubs):
|
||||
def cmdutils_patch(monkeypatch, stubs, miscmodels_patch):
|
||||
"""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)
|
||||
@cmdutils.argument('section_', completion=miscmodels_patch.section)
|
||||
@cmdutils.argument('option', completion=miscmodels_patch.option)
|
||||
@cmdutils.argument('value', completion=miscmodels_patch.value)
|
||||
def set_command(section_=None, option=None, value=None):
|
||||
"""docstring."""
|
||||
pass
|
||||
|
||||
@cmdutils.argument('topic', completion=usertypes.Completion.helptopic)
|
||||
@cmdutils.argument('topic', completion=miscmodels_patch.helptopic)
|
||||
def show_help(tab=False, bg=False, window=False, topic=None):
|
||||
"""docstring."""
|
||||
pass
|
||||
|
||||
@cmdutils.argument('url', completion=usertypes.Completion.url)
|
||||
@cmdutils.argument('url', completion=miscmodels_patch.url)
|
||||
@cmdutils.argument('count', count=True)
|
||||
def openurl(url=None, implicit=False, bg=False, tab=False, window=False,
|
||||
count=None):
|
||||
@ -101,7 +115,7 @@ def cmdutils_patch(monkeypatch, stubs):
|
||||
pass
|
||||
|
||||
@cmdutils.argument('win_id', win_id=True)
|
||||
@cmdutils.argument('command', completion=usertypes.Completion.command)
|
||||
@cmdutils.argument('command', completion=miscmodels_patch.command)
|
||||
def bind(key, win_id, command=None, *, mode='normal', force=False):
|
||||
"""docstring."""
|
||||
pass
|
||||
@ -132,49 +146,45 @@ def _set_cmd_prompt(cmd, txt):
|
||||
|
||||
|
||||
@pytest.mark.parametrize('txt, kind, pattern, pos_args', [
|
||||
(':nope|', usertypes.Completion.command, 'nope', []),
|
||||
(':nope|', 'command', 'nope', []),
|
||||
(':nope |', None, '', []),
|
||||
(':set |', usertypes.Completion.section, '', []),
|
||||
(':set gen|', usertypes.Completion.section, 'gen', []),
|
||||
(':set general |', usertypes.Completion.option, '', ['general']),
|
||||
(':set what |', usertypes.Completion.option, '', ['what']),
|
||||
(':set general editor |', usertypes.Completion.value, '',
|
||||
(':set |', 'section', '', []),
|
||||
(':set gen|', 'section', 'gen', []),
|
||||
(':set general |', 'option', '', ['general']),
|
||||
(':set what |', 'option', '', ['what']),
|
||||
(':set general editor |', 'value', '', ['general', 'editor']),
|
||||
(':set general editor gv|', 'value', 'gv', ['general', 'editor']),
|
||||
(':set general editor "gvim -f"|', 'value', 'gvim -f',
|
||||
['general', 'editor']),
|
||||
(':set general editor gv|', usertypes.Completion.value, 'gv',
|
||||
['general', 'editor']),
|
||||
(':set general editor "gvim -f"|', usertypes.Completion.value, 'gvim -f',
|
||||
['general', 'editor']),
|
||||
(':set general editor "gvim |', usertypes.Completion.value, 'gvim',
|
||||
['general', 'editor']),
|
||||
(':set general huh |', usertypes.Completion.value, '', ['general', 'huh']),
|
||||
(':help |', usertypes.Completion.helptopic, '', []),
|
||||
(':help |', usertypes.Completion.helptopic, '', []),
|
||||
(':open |', usertypes.Completion.url, '', []),
|
||||
(':set general editor "gvim |', 'value', 'gvim', ['general', 'editor']),
|
||||
(':set general huh |', 'value', '', ['general', 'huh']),
|
||||
(':help |', 'helptopic', '', []),
|
||||
(':help |', 'helptopic', '', []),
|
||||
(':open |', 'url', '', []),
|
||||
(':bind |', None, '', []),
|
||||
(':bind <c-x> |', usertypes.Completion.command, '', ['<c-x>']),
|
||||
(':bind <c-x> foo|', usertypes.Completion.command, 'foo', ['<c-x>']),
|
||||
(':bind <c-x> |', 'command', '', ['<c-x>']),
|
||||
(':bind <c-x> foo|', 'command', 'foo', ['<c-x>']),
|
||||
(':bind <c-x>| foo', None, '<c-x>', []),
|
||||
(':set| general ', usertypes.Completion.command, 'set', []),
|
||||
(':|set general ', usertypes.Completion.command, 'set', []),
|
||||
(':set gene|ral ignore-case', usertypes.Completion.section, 'general', []),
|
||||
(':|', usertypes.Completion.command, '', []),
|
||||
(': |', usertypes.Completion.command, '', []),
|
||||
(':set| general ', 'command', 'set', []),
|
||||
(':|set general ', 'command', 'set', []),
|
||||
(':set gene|ral ignore-case', 'section', 'general', []),
|
||||
(':|', 'command', '', []),
|
||||
(': |', 'command', '', []),
|
||||
('/|', None, '', []),
|
||||
(':open -t|', None, '', []),
|
||||
(':open --tab|', None, '', []),
|
||||
(':open -t |', usertypes.Completion.url, '', []),
|
||||
(':open --tab |', usertypes.Completion.url, '', []),
|
||||
(':open | -t', usertypes.Completion.url, '', []),
|
||||
(':open -t |', 'url', '', []),
|
||||
(':open --tab |', 'url', '', []),
|
||||
(':open | -t', 'url', '', []),
|
||||
(':tab-detach |', None, '', []),
|
||||
(':bind --mode=caret <c-x> |', usertypes.Completion.command, '',
|
||||
['<c-x>']),
|
||||
pytest.param(':bind --mode caret <c-x> |', usertypes.Completion.command,
|
||||
'', [], marks=pytest.mark.xfail(reason='issue #74')),
|
||||
(':set -t -p |', usertypes.Completion.section, '', []),
|
||||
(':bind --mode=caret <c-x> |', 'command', '', ['<c-x>']),
|
||||
pytest.param(':bind --mode caret <c-x> |', 'command', '', [],
|
||||
marks=pytest.mark.xfail(reason='issue #74')),
|
||||
(':set -t -p |', 'section', '', []),
|
||||
(':open -- |', None, '', []),
|
||||
(':gibberish nonesense |', None, '', []),
|
||||
('/:help|', None, '', []),
|
||||
('::bind|', usertypes.Completion.command, ':bind'),
|
||||
('::bind|', 'command', ':bind', []),
|
||||
])
|
||||
def test_update_completion(txt, kind, pattern, pos_args, status_command_stub,
|
||||
completer_obj, completion_widget_stub):
|
||||
|
Loading…
Reference in New Issue
Block a user