Refactor how completions are organized.
This commit is contained in:
parent
34b24aafa8
commit
0b975db4dd
@ -24,7 +24,7 @@ from PyQt5.QtCore import pyqtSlot, QObject, QTimer, Qt
|
|||||||
from qutebrowser.config import config, configdata
|
from qutebrowser.config import config, configdata
|
||||||
from qutebrowser.commands import cmdutils, runners
|
from qutebrowser.commands import cmdutils, runners
|
||||||
from qutebrowser.utils import usertypes, log, objreg, utils
|
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 (
|
from qutebrowser.completion.models.sortfilter import (
|
||||||
CompletionFilterModel as CFM)
|
CompletionFilterModel as CFM)
|
||||||
|
|
||||||
@ -82,26 +82,27 @@ class Completer(QObject):
|
|||||||
def _init_static_completions(self):
|
def _init_static_completions(self):
|
||||||
"""Initialize the static completion models."""
|
"""Initialize the static completion models."""
|
||||||
self._models[usertypes.Completion.command] = CFM(
|
self._models[usertypes.Completion.command] = CFM(
|
||||||
models.CommandCompletionModel(self), self)
|
miscmodels.CommandCompletionModel(self), self)
|
||||||
self._models[usertypes.Completion.helptopic] = CFM(
|
self._models[usertypes.Completion.helptopic] = CFM(
|
||||||
models.HelpCompletionModel(self), self)
|
miscmodels.HelpCompletionModel(self), self)
|
||||||
self._models[usertypes.Completion.url] = CFM(
|
self._models[usertypes.Completion.url] = CFM(
|
||||||
models.UrlCompletionModel(self), self,
|
urlmodel.UrlCompletionModel(self), self,
|
||||||
dumb_sort=Qt.DescendingOrder)
|
dumb_sort=Qt.DescendingOrder)
|
||||||
|
|
||||||
def _init_setting_completions(self):
|
def _init_setting_completions(self):
|
||||||
"""Initialize setting completion models."""
|
"""Initialize setting completion models."""
|
||||||
self._models[usertypes.Completion.section] = CFM(
|
self._models[usertypes.Completion.section] = CFM(
|
||||||
models.SettingSectionCompletionModel(self), self)
|
configmodel.SettingSectionCompletionModel(self), self)
|
||||||
self._models[usertypes.Completion.option] = {}
|
self._models[usertypes.Completion.option] = {}
|
||||||
self._models[usertypes.Completion.value] = {}
|
self._models[usertypes.Completion.value] = {}
|
||||||
for sectname in configdata.DATA:
|
for sectname in configdata.DATA:
|
||||||
model = models.SettingOptionCompletionModel(sectname, self)
|
model = configmodel.SettingOptionCompletionModel(sectname, self)
|
||||||
self._models[usertypes.Completion.option][sectname] = CFM(
|
self._models[usertypes.Completion.option][sectname] = CFM(
|
||||||
model, self)
|
model, self)
|
||||||
self._models[usertypes.Completion.value][sectname] = {}
|
self._models[usertypes.Completion.value][sectname] = {}
|
||||||
for opt in configdata.DATA[sectname].keys():
|
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(
|
self._models[usertypes.Completion.value][sectname][opt] = CFM(
|
||||||
model, self)
|
model, self)
|
||||||
|
|
||||||
@ -114,9 +115,9 @@ class Completer(QObject):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
self._models[usertypes.Completion.quickmark_by_url] = CFM(
|
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(
|
self._models[usertypes.Completion.quickmark_by_name] = CFM(
|
||||||
models.QuickmarkCompletionModel('name', self), self)
|
miscmodels.QuickmarkCompletionModel('name', self), self)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def init_session_completion(self):
|
def init_session_completion(self):
|
||||||
@ -126,7 +127,7 @@ class Completer(QObject):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
self._models[usertypes.Completion.sessions] = CFM(
|
self._models[usertypes.Completion.sessions] = CFM(
|
||||||
models.SessionCompletionModel(self), self)
|
miscmodels.SessionCompletionModel(self), self)
|
||||||
|
|
||||||
def _get_completion_model(self, completion, parts, cursor_part):
|
def _get_completion_model(self, completion, parts, cursor_part):
|
||||||
"""Get a completion model based on an enum member.
|
"""Get a completion model based on an enum member.
|
||||||
|
@ -17,13 +17,12 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
# 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 PyQt5.QtCore import pyqtSlot, Qt
|
||||||
|
|
||||||
from qutebrowser.config import config, configdata
|
from qutebrowser.config import config, configdata
|
||||||
from qutebrowser.utils import log, qtutils, objreg
|
from qutebrowser.utils import log, qtutils, objreg
|
||||||
from qutebrowser.commands import cmdutils
|
|
||||||
from qutebrowser.completion.models import base
|
from qutebrowser.completion.models import base
|
||||||
|
|
||||||
|
|
||||||
@ -148,168 +147,3 @@ class SettingValueCompletionModel(base.BaseCompletionModel):
|
|||||||
if not ok:
|
if not ok:
|
||||||
raise ValueError("Setting data failed! (section: {}, option: {}, "
|
raise ValueError("Setting data failed! (section: {}, option: {}, "
|
||||||
"value: {})".format(section, option, value))
|
"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)
|
|
124
qutebrowser/completion/models/miscmodels.py
Normal file
124
qutebrowser/completion/models/miscmodels.py
Normal 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)
|
61
qutebrowser/completion/models/urlmodel.py
Normal file
61
qutebrowser/completion/models/urlmodel.py
Normal 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)
|
Loading…
Reference in New Issue
Block a user