问题描述
我有一个 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 解释器中启用代码完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!