Refactor completion handling

This commit is contained in:
Florian Bruhin 2014-05-01 00:23:53 +02:00
parent 746179d87c
commit 533d82417e
2 changed files with 56 additions and 29 deletions

View File

@ -17,6 +17,8 @@
"""Module containing command managers (SearchManager and CommandManager).""" """Module containing command managers (SearchManager and CommandManager)."""
import logging
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
from PyQt5.QtWebKitWidgets import QWebPage from PyQt5.QtWebKitWidgets import QWebPage
@ -40,8 +42,9 @@ def split_cmdline(text):
parts = manager.parse(text) parts = manager.parse(text)
except NoSuchCommandError: except NoSuchCommandError:
parts = text.split(' ') parts = text.split(' ')
if text.endswith(' '): if text.endswith(' '):
parts.append('') parts.append('')
logging.debug("Split parts: {}".format(parts))
return parts return parts
@ -166,10 +169,15 @@ class CommandManager:
if len(parts) == 1: if len(parts) == 1:
args = [] args = []
else: else:
logging.debug("Splitting '{}' with max {} splits".format(
parts[1], cmd.maxsplit))
args = parts[1].split(maxsplit=cmd.maxsplit) args = parts[1].split(maxsplit=cmd.maxsplit)
self._cmd = cmd self._cmd = cmd
self._args = args self._args = args
return [cmdstr] + args retargs = args[:]
if text.endswith(' ') and len(args) <= cmd.maxsplit:
retargs.append('')
return [cmdstr] + retargs
def _check(self): def _check(self):
"""Check if the argument count for the command is correct.""" """Check if the argument count for the command is correct."""

View File

@ -58,7 +58,7 @@ class CompletionView(QTreeView):
Attributes: Attributes:
_model: The currently active filter model. _model: The currently active filter model.
_lastmodel: The model set in the last iteration. _lastmodel: The model set in the last iteration.
_completion_models: dict of available completion models. _models: dict of available completion models.
_enabled: Whether showing the CompletionView is enabled. _enabled: Whether showing the CompletionView is enabled.
_completing: Whether we're currently completing something. _completing: Whether we're currently completing something.
_height: The height to use for the CompletionView. _height: The height to use for the CompletionView.
@ -107,20 +107,22 @@ class CompletionView(QTreeView):
self._enabled = config.get('completion', 'show') self._enabled = config.get('completion', 'show')
self._model = None self._model = None
self._lastmodel = None self._lastmodel = None
self._completion_models = { self._models = {
'command': CompletionFilterModel(CommandCompletionModel(self)), 'command': CompletionFilterModel(CommandCompletionModel(self)),
'section': CompletionFilterModel(SettingSectionCompletionModel( 'section': CompletionFilterModel(
self)), SettingSectionCompletionModel(self)),
'option': {},
'value': {},
} }
for sect in configdata.DATA.keys(): for sect in configdata.DATA.keys():
self._completion_models['option_' + sect] = CompletionFilterModel( self._models['option'][sect] = CompletionFilterModel(
SettingOptionCompletionModel(sect, self)) SettingOptionCompletionModel(sect, self))
self._models['value'][sect] = {}
for opt in configdata.DATA[sect].keys(): for opt in configdata.DATA[sect].keys():
try: try:
modelname = 'value_{}_{}'.format(sect, opt) self._models['value'][sect][opt] = (
self._completion_models[modelname] = ( CompletionFilterModel(SettingValueCompletionModel(
CompletionFilterModel(SettingValueCompletionModel(sect, sect, opt, self)))
opt, self)))
except NoCompletionsError: except NoCompletionsError:
pass pass
self._completing = False self._completing = False
@ -176,28 +178,39 @@ class CompletionView(QTreeView):
parts: The command chunks to get a completion for. parts: The command chunks to get a completion for.
""" """
if len(parts) == 1: if len(parts) == 1:
return 'command' # parts = [''] or something like ['set']
# try to delegate to the command return self._models['command']
# delegate completion to command
try: try:
completions = cmdutils.cmd_dict[parts[0]].completion completions = cmdutils.cmd_dict[parts[0]].completion
except KeyError: except KeyError:
# entering an unknown command
return None return None
logging.debug("completions: {}".format(completions)) logging.debug("completions: {}".format(completions))
if completions is None: if completions is None:
# command without any available completions
return None return None
try: try:
compl = completions[len(parts) - 2] idx = len(parts[1:]) - 1
completion_name = completions[idx]
logging.debug('partlen: {}, modelname {}'.format(
len(parts[1:]), completion_name))
except IndexError: except IndexError:
# More arguments than completions
return None return None
if compl == 'option': if completion_name == 'option':
compl = 'option_' + parts[-2] section = parts[-2]
elif compl == 'value': model = self._models['option'].get(section)
compl = 'value_{}_{}'.format(parts[-3], parts[-2]) elif completion_name == 'value':
if compl in self._completion_models: section = parts[-3]
return compl option = parts[-2]
try:
model = self._models['value'][section][option]
except KeyError:
model = None
else: else:
logging.debug("No completion model for {}.".format(compl)) model = self._models.get(completion_name)
return None return model
def _next_prev_item(self, prev): def _next_prev_item(self, prev):
"""Handle a tab press for the CompletionView. """Handle a tab press for the CompletionView.
@ -225,13 +238,11 @@ class CompletionView(QTreeView):
Called from cmd_text_changed(). Called from cmd_text_changed().
Args: Args:
model: An index into self._completion_models. model: The model to use.
""" """
self._lastmodel = self._model logging.debug("Setting model to {}".format(model.__class__.__name__))
m = self._completion_models[model] self.setModel(model)
logging.debug("Setting model to {}".format(m)) self._model = model
self.setModel(m)
self._model = m
self.expandAll() self.expandAll()
self.resizeColumnToContents(0) self.resizeColumnToContents(0)
@ -263,7 +274,15 @@ class CompletionView(QTreeView):
parts = split_cmdline(text) parts = split_cmdline(text)
model = self._get_new_completion(parts) model = self._get_new_completion(parts)
if model is None:
logging.debug("No completion model for {}.".format(parts))
else:
logging.debug("New completion: {} / last: {}".format(
model.srcmodel.__class__.__name__,
self._lastmodel.srcmodel.__class__.__name__ if self._lastmodel
is not None else "None"))
if model != self._lastmodel: if model != self._lastmodel:
self._lastmodel = model
if model is None: if model is None:
self.hide() self.hide()
self._completing = False self._completing = False