3

我一直在开发一个命令行工具,现在我正在为它制作一个 PyQT GUI。我想使用 readline 模块获取当前的自动完成实现,并将其放入 QLineEdit 文本框中。这可能吗?你有什么建议?

这是我使用 readline 模块所做的一个示例:

import readline

values = ['these','are','my','autocomplete','words']
completions = {}

def completer(text,state):
    try:
        matches = completions[text]
    except KeyError:
        matches = [value for value in values if text.upper() in value.upper()]
        completions[text] = matches
    try:
        return matches[state]
    except IndexError:
        return None

readline.set_completer(completer)
readline.parse_and_bind('tab: menu-complete')

whie 1:
    text = raw_input('> ')
    text.dostuff()

最终,如果我不能让 readline 模块在 QLineEdit 小部件中工作,我最终想要做的是完成一个单词列表,能够让多个单词用 +-*/( ) ETC...

谢谢!

4

1 回答 1

4

我可以告诉你,首先,尝试将 QCompleter 包装在新功能周围是一个巨大的痛苦。您必须能够满足 QCompleter 的所有接口,并围绕该实时代码桥接它。

您必须手动更新 QCompleter 上设置的 QStringListModel,并为给定的搜索前缀提供获取当前完成和完成总数的实现。

这是一个与 PopupCompletion 模式兼容的工作示例:

import re

class ReadlineCompleter(QtGui.QCompleter):

    def __init__(self, completeFn, *args, **kwargs):
        super(ReadlineCompleter, self).__init__(*args, **kwargs)
        self._completer = completeFn
        self.setModel(QtGui.QStringListModel())
        self.update()

    def setCompletionPrefix(self, val):
        super(ReadlineCompleter, self).setCompletionPrefix(val)
        self.update()

    def currentCompletion(self):
        state = self.currentRow()
        return self._completionAt(state)

    def completionCount(self):
        state = 0
        while True:
            result = self._completionAt(state)
            if not result:
                break
            state += 1
        return state

    def update(self):
        matches = [self._completionAt(i) for i in xrange(self.completionCount())]
        self.model().setStringList(matches)

    def _completionAt(self, state):
        text = str(self.completionPrefix())

        # regex to split on any whitespace, or the char set +*/^()-
        match = re.match(r'^(.*)([\s+*/^()-]+)(.*)$', text)
        if match:
            prefix, sep, text = match.groups()

        result = self._completer(str(text), state)

        if result and match:
            result = sep.join([prefix, result])

        return '' if result is None else result     

请注意,在该_completionAt()方法中,我添加了您想要的额外功能,用于检测分隔符模式。你可以很明显地调整它。但它会拆分最后一部分并使用该值来检查完成,然后再次使用前缀重新加入结果。

用法

重要的。您需要将textChanged来自 QLineEdit 的信号连接到完成器以强制更新。否则,完成程序中不会使用任何功能。

line = QtGui.QLineEdit()
comp = ReadlineCompleter(completer)
comp.setCompletionMode(comp.PopupCompletion)
line.setCompleter(comp)
# important
line.textChanged.connect(comp.setCompletionPrefix)

这里有一些例子展示了其他人如何在自定义行编辑中填写功能,他们完全绕过完成者的标准信号并自己触发它。你可以看到它的一点点努力。

于 2012-07-09T20:51:51.177 回答