Refactor how completions are organized.

This commit is contained in:
Florian Bruhin 2015-03-11 23:07:58 +01:00
parent 34b24aafa8
commit 0b975db4dd
4 changed files with 197 additions and 177 deletions

View File

@ -24,7 +24,7 @@ from PyQt5.QtCore import pyqtSlot, QObject, QTimer, Qt
from qutebrowser.config import config, configdata
from qutebrowser.commands import cmdutils, runners
from qutebrowser.utils import usertypes, log, objreg, utils
from qutebrowser.completion.models import completion as models
from qutebrowser.completion.models import miscmodels, urlmodel, configmodel
from qutebrowser.completion.models.sortfilter import (
CompletionFilterModel as CFM)
@ -82,26 +82,27 @@ class Completer(QObject):
def _init_static_completions(self):
"""Initialize the static completion models."""
self._models[usertypes.Completion.command] = CFM(
models.CommandCompletionModel(self), self)
miscmodels.CommandCompletionModel(self), self)
self._models[usertypes.Completion.helptopic] = CFM(
models.HelpCompletionModel(self), self)
miscmodels.HelpCompletionModel(self), self)
self._models[usertypes.Completion.url] = CFM(
models.UrlCompletionModel(self), self,
urlmodel.UrlCompletionModel(self), self,
dumb_sort=Qt.DescendingOrder)
def _init_setting_completions(self):
"""Initialize setting completion models."""
self._models[usertypes.Completion.section] = CFM(
models.SettingSectionCompletionModel(self), self)
configmodel.SettingSectionCompletionModel(self), self)
self._models[usertypes.Completion.option] = {}
self._models[usertypes.Completion.value] = {}
for sectname in configdata.DATA:
model = models.SettingOptionCompletionModel(sectname, self)
model = configmodel.SettingOptionCompletionModel(sectname, self)
self._models[usertypes.Completion.option][sectname] = CFM(
model, self)
self._models[usertypes.Completion.value][sectname] = {}
for opt in configdata.DATA[sectname].keys():
model = models.SettingValueCompletionModel(sectname, opt, self)
model = configmodel.SettingValueCompletionModel(sectname, opt,
self)
self._models[usertypes.Completion.value][sectname][opt] = CFM(
model, self)
@ -114,9 +115,9 @@ class Completer(QObject):
except KeyError:
pass
self._models[usertypes.Completion.quickmark_by_url] = CFM(
models.QuickmarkCompletionModel('url', self), self)
miscmodels.QuickmarkCompletionModel('url', self), self)
self._models[usertypes.Completion.quickmark_by_name] = CFM(
models.QuickmarkCompletionModel('name', self), self)
miscmodels.QuickmarkCompletionModel('name', self), self)
@pyqtSlot()
def init_session_completion(self):
@ -126,7 +127,7 @@ class Completer(QObject):
except KeyError:
pass
self._models[usertypes.Completion.sessions] = CFM(
models.SessionCompletionModel(self), self)
miscmodels.SessionCompletionModel(self), self)
def _get_completion_model(self, completion, parts, cursor_part):
"""Get a completion model based on an enum member.

View File

@ -17,13 +17,12 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""CompletionModels for different usages."""
"""CompletionModels for the config."""
from PyQt5.QtCore import pyqtSlot, Qt
from qutebrowser.config import config, configdata
from qutebrowser.utils import log, qtutils, objreg
from qutebrowser.commands import cmdutils
from qutebrowser.completion.models import base
@ -148,168 +147,3 @@ class SettingValueCompletionModel(base.BaseCompletionModel):
if not ok:
raise ValueError("Setting data failed! (section: {}, option: {}, "
"value: {})".format(section, option, value))
class CommandCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with all commands and descriptions."""
# pylint: disable=abstract-method
def __init__(self, parent=None):
super().__init__(parent)
assert cmdutils.cmd_dict
cmdlist = []
for obj in set(cmdutils.cmd_dict.values()):
if (obj.hide or (obj.debug and not objreg.get('args').debug) or
obj.deprecated):
pass
else:
cmdlist.append((obj.name, obj.desc))
for name, cmd in config.section('aliases').items():
cmdlist.append((name, "Alias for '{}'".format(cmd)))
cat = self.new_category("Commands")
for (name, desc) in sorted(cmdlist):
self.new_item(cat, name, desc)
class HelpCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with help topics."""
# pylint: disable=abstract-method
def __init__(self, parent=None):
super().__init__(parent)
self._init_commands()
self._init_settings()
def _init_commands(self):
"""Fill completion with :command entries."""
assert cmdutils.cmd_dict
cmdlist = []
for obj in set(cmdutils.cmd_dict.values()):
if (obj.hide or (obj.debug and not objreg.get('args').debug) or
obj.deprecated):
pass
else:
cmdlist.append((':' + obj.name, obj.desc))
cat = self.new_category("Commands")
for (name, desc) in sorted(cmdlist):
self.new_item(cat, name, desc)
def _init_settings(self):
"""Fill completion with section->option entries."""
cat = self.new_category("Settings")
for sectname, sectdata in configdata.DATA.items():
for optname in sectdata.keys():
try:
desc = sectdata.descriptions[optname]
except (KeyError, AttributeError):
# Some stuff (especially ValueList items) don't have a
# description.
desc = ""
else:
desc = desc.splitlines()[0]
name = '{}->{}'.format(sectname, optname)
self.new_item(cat, name, desc)
class UrlCompletionModel(base.BaseCompletionModel):
"""A model which combines quickmarks and web history URLs.
Used for the `open` command."""
# pylint: disable=abstract-method
def __init__(self, parent=None):
super().__init__(parent)
self._quickcat = self.new_category("Quickmarks")
self._histcat = self.new_category("History")
self._histstore = objreg.get('web-history')
WebHistoryCompletionModel.fill_model(self, cat=self._histcat)
QuickmarkCompletionModel.fill_model(self, cat=self._quickcat)
self._histstore.item_added.connect(
lambda e: WebHistoryCompletionModel.history_changed(
self, e, self._histcat))
class WebHistoryCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with global browsing history."""
# pylint: disable=abstract-method
def __init__(self, parent=None):
super().__init__(parent)
self._histcat = self.new_category("History")
self._histstore = objreg.get('web-history')
self.fill_model(self, self._histcat, self._histstore)
self._histstore.item_added.connect(
lambda e: self.history_changed(e, self._histcat))
@staticmethod
def fill_model(model, cat=None, histstore=None):
"""Fill the given model/category with the given history."""
if not histstore:
histstore = objreg.get('web-history')
if not cat:
cat = model.new_category("History")
for entry in histstore:
atime = int(entry.atime)
model.new_item(cat, entry.url, "", str(atime), sort=atime)
def history_changed(self, entry, cat):
"""Slot called when a new history item was added."""
if entry.url:
atime = int(entry.atime)
self.new_item(cat, entry.url, "", str(atime), sort=atime)
class QuickmarkCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with all quickmarks."""
# pylint: disable=abstract-method
def __init__(self, match_field='url', parent=None):
super().__init__(parent)
self.fill_model(self, match_field)
@staticmethod
def fill_model(model, match_field='url', cat=None):
"""Fill the given model/category with quickmarks."""
if not cat:
cat = model.new_category("Quickmarks")
quickmarks = objreg.get('quickmark-manager').marks.items()
if match_field == 'url':
for qm_name, qm_url in quickmarks:
model.new_item(cat, qm_url, qm_name)
elif match_field == 'name':
for qm_name, qm_url in quickmarks:
model.new_item(cat, qm_name, qm_url)
else:
raise ValueError("Invalid value '{}' for match_field!".format(
match_field))
class SessionCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with session names."""
# pylint: disable=abstract-method
def __init__(self, parent=None):
super().__init__(parent)
cat = self.new_category("Sessions")
for name in objreg.get('session-manager').list_sessions():
self.new_item(cat, name)

View File

@ -0,0 +1,124 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 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/>.
"""Misc. CompletionModels."""
from qutebrowser.config import config, configdata
from qutebrowser.utils import objreg
from qutebrowser.commands import cmdutils
from qutebrowser.completion.models import base
class CommandCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with all commands and descriptions."""
# pylint: disable=abstract-method
def __init__(self, parent=None):
super().__init__(parent)
assert cmdutils.cmd_dict
cmdlist = []
for obj in set(cmdutils.cmd_dict.values()):
if (obj.hide or (obj.debug and not objreg.get('args').debug) or
obj.deprecated):
pass
else:
cmdlist.append((obj.name, obj.desc))
for name, cmd in config.section('aliases').items():
cmdlist.append((name, "Alias for '{}'".format(cmd)))
cat = self.new_category("Commands")
for (name, desc) in sorted(cmdlist):
self.new_item(cat, name, desc)
class HelpCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with help topics."""
# pylint: disable=abstract-method
def __init__(self, parent=None):
super().__init__(parent)
self._init_commands()
self._init_settings()
def _init_commands(self):
"""Fill completion with :command entries."""
assert cmdutils.cmd_dict
cmdlist = []
for obj in set(cmdutils.cmd_dict.values()):
if (obj.hide or (obj.debug and not objreg.get('args').debug) or
obj.deprecated):
pass
else:
cmdlist.append((':' + obj.name, obj.desc))
cat = self.new_category("Commands")
for (name, desc) in sorted(cmdlist):
self.new_item(cat, name, desc)
def _init_settings(self):
"""Fill completion with section->option entries."""
cat = self.new_category("Settings")
for sectname, sectdata in configdata.DATA.items():
for optname in sectdata.keys():
try:
desc = sectdata.descriptions[optname]
except (KeyError, AttributeError):
# Some stuff (especially ValueList items) don't have a
# description.
desc = ""
else:
desc = desc.splitlines()[0]
name = '{}->{}'.format(sectname, optname)
self.new_item(cat, name, desc)
class QuickmarkCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with all quickmarks."""
# pylint: disable=abstract-method
def __init__(self, match_field='url', parent=None):
super().__init__(parent)
cat = self.new_category("Quickmarks")
quickmarks = objreg.get('quickmark-manager').marks.items()
if match_field == 'url':
for qm_name, qm_url in quickmarks:
self.new_item(cat, qm_url, qm_name)
elif match_field == 'name':
for qm_name, qm_url in quickmarks:
self.new_item(cat, qm_name, qm_url)
else:
raise ValueError("Invalid value '{}' for match_field!".format(
match_field))
class SessionCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with session names."""
# pylint: disable=abstract-method
def __init__(self, parent=None):
super().__init__(parent)
cat = self.new_category("Sessions")
for name in objreg.get('session-manager').list_sessions():
self.new_item(cat, name)

View File

@ -0,0 +1,61 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 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/>.
"""CompletionModels for URLs."""
from PyQt5.QtCore import pyqtSlot
from qutebrowser.utils import objreg
from qutebrowser.completion.models import base
class UrlCompletionModel(base.BaseCompletionModel):
"""A model which combines quickmarks and web history URLs.
Used for the `open` command."""
# pylint: disable=abstract-method
def __init__(self, parent=None):
super().__init__(parent)
self._quickmark_cat = self.new_category("Quickmarks")
self._history_cat = self.new_category("History")
quickmarks = objreg.get('quickmark-manager').marks.items()
history = objreg.get('web-history')
for qm_name, qm_url in quickmarks:
self.new_item(self._quickmark_cat, qm_url, qm_name)
for entry in history:
atime = int(entry.atime)
self.new_item(self._history_cat, entry.url, "", str(atime),
sort=atime)
history.item_added.connect(self.on_history_item_added)
@pyqtSlot(object)
def on_history_item_added(self, item):
"""Slot called when a new history item was added."""
if item.url:
atime = int(item.atime)
self.new_item(self._quickmark_cat, item.url, "", str(atime),
sort=atime)