本文介绍了在嵌入式 Python 解释器中启用代码完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 PyQT 小部件解释器在工作,从这里获取的代码如下:

导入操作系统进口重新导入系统导入代码从 PyQt4.QtGui 导入 *从 PyQt4.QtCore 导入 *类 MyInterpreter(QWidget):def __init__(self, parent):super(MyInterpreter, self).__init__(parent)hBox = QHBoxLayout()self.setLayout(hBox)self.textEdit = PyInterp(self)# 这就是你将本地人传递给解释器的方式self.textEdit.initInterpreter(locals())self.resize(650, 300)self.centerOnScreen()hBox.addWidget(self.textEdit)hBox.setMargin(0)hBox.setSpacing(0)def centerOnScreen(self):# 小部件在屏幕上居中分辨率 = QDesktopWidget().screenGeometry()self.move((resolution.width()/2) - (self.frameSize().width()/2),(分辨率.高度()/2) - (self.frameSize().height()/2))类 PyInterp(QTextEdit):类 InteractiveInterpreter(code.InteractiveInterpreter):def __init__(self, locals):code.InteractiveInterpreter.__init__(self, locals)def runIt(self, command):code.InteractiveInterpreter.runsource(self, command)def __init__(self, parent):super(PyInterp, self).__init__(parent)sys.stdout = 自我sys.stderr = 自我self.refreshMarker = False # 改回>>>从 ...self.multiLine = False # 代码跨越多行self.command = '' # 要运行的命令self.printBanner() # 打印系统信息self.marker() # 制作 >>>或 ... 标记self.history = [] # 输入的命令列表self.historyIndex = -1self.interpreterLocals = {}# 设置背景和文字的颜色调色板 = QPalette()调色板.setColor(QPalette.Base, QColor(0, 0, 0))调色板.setColor(QPalette.Text, QColor(0, 255, 0))self.setPalette(调色板)self.setFont(QFont('Courier', 12))# 使用本地本地人初始化解释器self.initInterpreter(locals())def printBanner(self):self.write(sys.version)self.write(' on ' + sys.platform + '\n')self.write('PyQt4' + PYQT_VERSION_STR + '\n')msg = '输入 !hist 获取历史视图和 !hist(n) 历史索引调用'self.write(msg + '\n')定义标记(自我):如果 self.multiLine:self.insertPlainText('...')别的:self.insertPlainText('>>>')def initInterpreter(self,interpreterLocals=None):如果interpreterLocals:# 当我们传入locals时,我们不希望它被命名为self"# 所以我们用执行传递的类的名称重命名它# 并将本地人重新插入到解释器字典中selfName = interpreterLocals['self'].__class__.__name__interpreterLocalVars = interpreterLocals.pop('self')self.interpreterLocals[selfName] = interpreterLocalVars别的:self.interpreterLocals = interpreterLocalsself.interpreter = self.InteractiveInterpreter(self.interpreterLocals)def updateInterpreterLocals(self, newLocals):className = newLocals.__class__.__name__self.interpreterLocals[className] = newLocalsdef write(self, line):self.insertPlainText(行)self.ensureCursorVisible()def clearCurrentBlock(self):# 块是当前行长度 = len(self.document().lastBlock().text()[4:])如果长度 == 0:返回无别的:# 应该有更好的方法来做到这一点,但我找不到[self.textCursor().deletePreviousChar() for x in xrange(length)]返回真定义召回历史(自我):# 使用箭头键滚动历史时使用self.clearCurrentBlock()if self.historyIndex <>-1:self.insertPlainText(self.history[self.historyIndex])返回真def customCommands(self, command):if command == '!hist': # 显示历史self.append('') # 下移一行# 命令中的变量以 ____CC 为前缀并被删除# 一旦命令完成,它们就不会出现在 dir() 中备份 = self.interpreterLocals.copy()历史 = self.history[:]历史.reverse()对于 i, x 在 enumerate(history):iSize = len(str(i))delta = len(str(len(history))) - iSizeline = line = '' * delta + '%i: %s' % (i, x) + '\n'self.write(行)self.updateInterpreterLocals(备份)self.marker()返回真if re.match('!hist\(\d+\)', command): # 从历史中调用命令备份 = self.interpreterLocals.copy()历史 = self.history[:]历史.reverse()索引 = int(命令[6:-1])self.clearCurrentBlock()命令 = 历史[索引]如果命令[-1] == ':':self.multiLine = Trueself.write(命令)self.updateInterpreterLocals(备份)返回真返回错误def keyPressEvent(self, event):如果 event.key() == Qt.Key_Escape:# 正确退出self.interpreter.runIt('exit()')如果 event.key() == Qt.Key_Down:如果 self.historyIndex == len(self.history):self.historyIndex -= 1尝试:如果 self.historyIndex >-1:self.historyIndex -= 1self.recallHistory()别的:self.clearCurrentBlock()除了:经过返回无如果 event.key() == Qt.Key_Up:尝试:如果 len(self.history) - 1 >self.historyIndex:self.historyIndex += 1self.recallHistory()别的:self.historyIndex = len(self.history)除了:经过返回无如果 event.key() == Qt.Key_Home:# 将光标设置到当前块中的位置 4.4 因为那是# 标记停止blockLength = len(self.document().lastBlock().text()[4:])lineLength = len(self.document().toPlainText())位置 = 线长 - 块长textCursor = self.textCursor()textCursor.setPosition(位置)self.setTextCursor(textCursor)返回无如果 event.key() 在 [Qt.Key_Left, Qt.Key_Backspace]:# 不允许删除标记如果 self.textCursor().positionInBlock() == 4:返回无如果 event.key() 在 [Qt.Key_Return, Qt.Key_Enter] 中:# 将光标设置为行尾以避免行拆分textCursor = self.textCursor()位置 = len(self.document().toPlainText())textCursor.setPosition(位置)self.setTextCursor(textCursor)line = str(self.document().lastBlock().text())[4:] # 移除标记line.rstrip()self.historyIndex = -1如果 self.customCommands(line):返回无别的:尝试:行[-1]self.haveLine = True如果行 [-1] == ':':self.multiLine = Trueself.history.insert(0, line)除了:self.haveLine = Falseif self.haveLine 和 self.multiLine: # 多行命令self.command += line + '\n' # + command 和 lineself.append('') # 下移一行self.marker() # 处理标记样式返回无if self.haveLine 而不是 self.multiLine: # 一行命令self.command = line # line 是命令self.append('') # 下移一行self.interpreter.runIt(self.command)self.command = '' # 清除命令self.marker() # 处理标记样式返回无if self.multiLine 而不是 self.haveLine: # 多行完成self.append('') # 下移一行self.interpreter.runIt(self.command)self.command = '' # 清除命令self.multiLine = False # 回到单行self.marker() # 处理标记样式返回无如果不是 self.haveLine 而不是 self.multiLine: # 直接输入self.append('')self.marker()返回无返回无# 允许所有其他关键事件超级(PyInterp,self).keyPressEvent(事件)如果 __name__ == '__main__':app = QApplication(sys.argv)win = MyInterpreter(无)赢.show()sys.exit(app.exec_())

有没有一种简单的方法可以让一些标签完成只针对本地符号?

解决方案

我想你指的是 rlcompleter 的 Completer 对象.

你可以这样使用它:

from rlcompleter import Completer行 = str(...)完成者 = 完成者(self.interpreter.locals)建议 = completer.complete(line, 0)self.insertPlainText(建议)

数字参数表示第 n 个建议,您可以迭代它直到它返回 None.

例如,假设我们有

>>>my_data = '012345'

然后

>>>completer.complete('my_', 0)'我的数据'>>>completer.complete('my_data.s', 0)'my_data.split('>>>completer.complete('my_data.s', 1)'my_data.splitlines('

请注意,虽然上面的代码使用了 interpreter.locals,但您可以应用更广泛的搜索(但一定要提供字典).

I have got a PyQT widget interpreter working, the code picked up from here is as follows:

import os
import re
import sys
import code

from PyQt4.QtGui import *
from PyQt4.QtCore import *

class MyInterpreter(QWidget):

    def __init__(self, parent):

        super(MyInterpreter, self).__init__(parent)
        hBox = QHBoxLayout()

        self.setLayout(hBox)
        self.textEdit = PyInterp(self)

        # this is how you pass in locals to the interpreter
        self.textEdit.initInterpreter(locals())

        self.resize(650, 300)
        self.centerOnScreen()

        hBox.addWidget(self.textEdit)
        hBox.setMargin(0)
        hBox.setSpacing(0)

    def centerOnScreen(self):
        # center the widget on the screen
        resolution = QDesktopWidget().screenGeometry()
        self.move((resolution.width()  / 2) - (self.frameSize().width()  / 2),
                  (resolution.height() / 2) - (self.frameSize().height() / 2))

class PyInterp(QTextEdit):

    class InteractiveInterpreter(code.InteractiveInterpreter):

        def __init__(self, locals):
            code.InteractiveInterpreter.__init__(self, locals)

        def runIt(self, command):
            code.InteractiveInterpreter.runsource(self, command)


    def __init__(self,  parent):
        super(PyInterp,  self).__init__(parent)

        sys.stdout              = self
        sys.stderr              = self
        self.refreshMarker      = False # to change back to >>> from ...
        self.multiLine          = False # code spans more than one line
        self.command            = ''    # command to be ran
        self.printBanner()              # print sys info
        self.marker()                   # make the >>> or ... marker
        self.history            = []    # list of commands entered
        self.historyIndex       = -1
        self.interpreterLocals  = {}

        # setting the color for bg and text
        palette = QPalette()
        palette.setColor(QPalette.Base, QColor(0, 0, 0))
        palette.setColor(QPalette.Text, QColor(0, 255, 0))
        self.setPalette(palette)
        self.setFont(QFont('Courier', 12))

        # initilize interpreter with self locals
        self.initInterpreter(locals())


    def printBanner(self):
        self.write(sys.version)
        self.write(' on ' + sys.platform + '\n')
        self.write('PyQt4 ' + PYQT_VERSION_STR + '\n')
        msg = 'Type !hist for a history view and !hist(n) history index recall'
        self.write(msg + '\n')


    def marker(self):
        if self.multiLine:
            self.insertPlainText('... ')
        else:
            self.insertPlainText('>>> ')

    def initInterpreter(self, interpreterLocals=None):
        if interpreterLocals:
            # when we pass in locals, we don't want it to be named "self"
            # so we rename it with the name of the class that did the passing
            # and reinsert the locals back into the interpreter dictionary
            selfName = interpreterLocals['self'].__class__.__name__
            interpreterLocalVars = interpreterLocals.pop('self')
            self.interpreterLocals[selfName] = interpreterLocalVars
        else:
            self.interpreterLocals = interpreterLocals
        self.interpreter = self.InteractiveInterpreter(self.interpreterLocals)

    def updateInterpreterLocals(self, newLocals):
        className = newLocals.__class__.__name__
        self.interpreterLocals[className] = newLocals

    def write(self, line):
        self.insertPlainText(line)
        self.ensureCursorVisible()

    def clearCurrentBlock(self):
        # block being current row
        length = len(self.document().lastBlock().text()[4:])
        if length == 0:
            return None
        else:
            # should have a better way of doing this but I can't find it
            [self.textCursor().deletePreviousChar() for x in xrange(length)]
        return True

    def recallHistory(self):
        # used when using the arrow keys to scroll through history
        self.clearCurrentBlock()
        if self.historyIndex <> -1:
            self.insertPlainText(self.history[self.historyIndex])
        return True

    def customCommands(self, command):

        if command == '!hist': # display history
            self.append('') # move down one line
            # vars that are in the command are prefixed with ____CC and deleted
            # once the command is done so they don't show up in dir()
            backup = self.interpreterLocals.copy()
            history = self.history[:]
            history.reverse()
            for i, x in enumerate(history):
                iSize = len(str(i))
                delta = len(str(len(history))) - iSize
                line = line  = ' ' * delta + '%i: %s' % (i, x) + '\n'
                self.write(line)
            self.updateInterpreterLocals(backup)
            self.marker()
            return True

        if re.match('!hist\(\d+\)', command): # recall command from history
            backup = self.interpreterLocals.copy()
            history = self.history[:]
            history.reverse()
            index = int(command[6:-1])
            self.clearCurrentBlock()
            command = history[index]
            if command[-1] == ':':
                self.multiLine = True
            self.write(command)
            self.updateInterpreterLocals(backup)
            return True

        return False

    def keyPressEvent(self, event):

        if event.key() == Qt.Key_Escape:
            # proper exit
            self.interpreter.runIt('exit()')

        if event.key() == Qt.Key_Down:
            if self.historyIndex == len(self.history):
                self.historyIndex -= 1
            try:
                if self.historyIndex > -1:
                    self.historyIndex -= 1
                    self.recallHistory()
                else:
                    self.clearCurrentBlock()
            except:
                pass
            return None

        if event.key() == Qt.Key_Up:
            try:
                if len(self.history) - 1 > self.historyIndex:
                    self.historyIndex += 1
                    self.recallHistory()
                else:
                    self.historyIndex = len(self.history)
            except:
                pass
            return None

        if event.key() == Qt.Key_Home:
            # set cursor to position 4 in current block. 4 because that's where
            # the marker stops
            blockLength = len(self.document().lastBlock().text()[4:])
            lineLength  = len(self.document().toPlainText())
            position = lineLength - blockLength
            textCursor  = self.textCursor()
            textCursor.setPosition(position)
            self.setTextCursor(textCursor)
            return None

        if event.key() in [Qt.Key_Left, Qt.Key_Backspace]:
            # don't allow deletion of marker
            if self.textCursor().positionInBlock() == 4:
                return None

        if event.key() in [Qt.Key_Return, Qt.Key_Enter]:
            # set cursor to end of line to avoid line splitting
            textCursor = self.textCursor()
            position   = len(self.document().toPlainText())
            textCursor.setPosition(position)
            self.setTextCursor(textCursor)

            line = str(self.document().lastBlock().text())[4:] # remove marker
            line.rstrip()
            self.historyIndex = -1

            if self.customCommands(line):
                return None
            else:
                try:
                    line[-1]
                    self.haveLine = True
                    if line[-1] == ':':
                        self.multiLine = True
                    self.history.insert(0, line)
                except:
                    self.haveLine = False

                if self.haveLine and self.multiLine: # multi line command
                    self.command += line + '\n' # + command and line
                    self.append('') # move down one line
                    self.marker() # handle marker style
                    return None

                if self.haveLine and not self.multiLine: # one line command
                    self.command = line # line is the command
                    self.append('') # move down one line
                    self.interpreter.runIt(self.command)
                    self.command = '' # clear command
                    self.marker() # handle marker style
                    return None

                if self.multiLine and not self.haveLine: #  multi line done
                    self.append('') # move down one line
                    self.interpreter.runIt(self.command)
                    self.command = '' # clear command
                    self.multiLine = False # back to single line
                    self.marker() # handle marker style
                    return None

                if not self.haveLine and not self.multiLine: # just enter
                    self.append('')
                    self.marker()
                    return None
                return None

        # allow all other key events
        super(PyInterp, self).keyPressEvent(event)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = MyInterpreter(None)
    win.show()
    sys.exit(app.exec_())

Is there an easy way of getting some tab completion going just for local symbols ?

解决方案

I think you are referring to rlcompleter's Completer object.

You can used it like so:

from rlcompleter import Completer

line = str(...)

completer = Completer(self.interpreter.locals)
suggestion = completer.complete(line, 0)
self.insertPlainText(suggestion)

The numeric argument indicates the n-th suggestion, and you can iterate over it until it returns None.

For example, say we have

>>> my_data = '012345'

then

>>> completer.complete('my_', 0)
'my_data'
>>> completer.complete('my_data.s', 0)
'my_data.split('
>>> completer.complete('my_data.s', 1)
'my_data.splitlines('


Note that while the code above uses interpreter.locals, you can apply a wider search (but be sure to provide a dictionary).

这篇关于在嵌入式 Python 解释器中启用代码完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-25 20:17