tre-adding console.py (deleted by mistake) - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 9e70c7fae4af8351bfa133b57b204d387302fe4e DIR parent e54a746a5795ed498a8f8e2883f5a62eb7c106d2 HTML Author: thomasv <thomasv@gitorious> Date: Mon, 30 Sep 2013 10:41:09 +0200 re-adding console.py (deleted by mistake) Diffstat: A gui/qt/console.py | 315 +++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+), 0 deletions(-) --- DIR diff --git a/gui/qt/console.py b/gui/qt/console.py t@@ -0,0 +1,315 @@ +# source: http://stackoverflow.com/questions/2758159/how-to-embed-a-python-interpreter-in-a-pyqt-widget + +import sys, os, re +import traceback, platform +from PyQt4 import QtCore +from PyQt4 import QtGui +from electrum import util + + +if platform.system() == 'Windows': + MONOSPACE_FONT = 'Lucida Console' +elif platform.system() == 'Darwin': + MONOSPACE_FONT = 'Monaco' +else: + MONOSPACE_FONT = 'monospace' + + +class Console(QtGui.QPlainTextEdit): + def __init__(self, prompt='>> ', startup_message='', parent=None): + QtGui.QPlainTextEdit.__init__(self, parent) + + self.prompt = prompt + self.history = [] + self.namespace = {} + self.construct = [] + + self.setGeometry(50, 75, 600, 400) + self.setWordWrapMode(QtGui.QTextOption.WrapAnywhere) + self.setUndoRedoEnabled(False) + self.document().setDefaultFont(QtGui.QFont(MONOSPACE_FONT, 10, QtGui.QFont.Normal)) + self.showMessage(startup_message) + + self.updateNamespace({'run':self.run_script}) + self.set_json(False) + + def set_json(self, b): + self.is_json = b + + def run_script(self, filename): + with open(filename) as f: + script = f.read() + result = eval(script, self.namespace, self.namespace) + + + + def updateNamespace(self, namespace): + self.namespace.update(namespace) + + def showMessage(self, message): + self.appendPlainText(message) + self.newPrompt() + + def clear(self): + self.setPlainText('') + self.newPrompt() + + def newPrompt(self): + if self.construct: + prompt = '.' * len(self.prompt) + else: + prompt = self.prompt + + self.completions_pos = self.textCursor().position() + self.completions_visible = False + + self.appendPlainText(prompt) + self.moveCursor(QtGui.QTextCursor.End) + + def getCommand(self): + doc = self.document() + curr_line = unicode(doc.findBlockByLineNumber(doc.lineCount() - 1).text()) + curr_line = curr_line.rstrip() + curr_line = curr_line[len(self.prompt):] + return curr_line + + def setCommand(self, command): + if self.getCommand() == command: + return + + doc = self.document() + curr_line = unicode(doc.findBlockByLineNumber(doc.lineCount() - 1).text()) + self.moveCursor(QtGui.QTextCursor.End) + for i in range(len(curr_line) - len(self.prompt)): + self.moveCursor(QtGui.QTextCursor.Left, QtGui.QTextCursor.KeepAnchor) + + self.textCursor().removeSelectedText() + self.textCursor().insertText(command) + self.moveCursor(QtGui.QTextCursor.End) + + + def show_completions(self, completions): + if self.completions_visible: + self.hide_completions() + + c = self.textCursor() + c.setPosition(self.completions_pos) + + completions = map(lambda x: x.split('.')[-1], completions) + t = '\n' + ' '.join(completions) + if len(t) > 500: + t = t[:500] + '...' + c.insertText(t) + self.completions_end = c.position() + + self.moveCursor(QtGui.QTextCursor.End) + self.completions_visible = True + + + def hide_completions(self): + if not self.completions_visible: + return + c = self.textCursor() + c.setPosition(self.completions_pos) + l = self.completions_end - self.completions_pos + for x in range(l): c.deleteChar() + + self.moveCursor(QtGui.QTextCursor.End) + self.completions_visible = False + + + def getConstruct(self, command): + if self.construct: + prev_command = self.construct[-1] + self.construct.append(command) + if not prev_command and not command: + ret_val = '\n'.join(self.construct) + self.construct = [] + return ret_val + else: + return '' + else: + if command and command[-1] == (':'): + self.construct.append(command) + return '' + else: + return command + + def getHistory(self): + return self.history + + def setHisory(self, history): + self.history = history + + def addToHistory(self, command): + if command.find("importprivkey") > -1: + return + + if command and (not self.history or self.history[-1] != command): + self.history.append(command) + self.history_index = len(self.history) + + def getPrevHistoryEntry(self): + if self.history: + self.history_index = max(0, self.history_index - 1) + return self.history[self.history_index] + return '' + + def getNextHistoryEntry(self): + if self.history: + hist_len = len(self.history) + self.history_index = min(hist_len, self.history_index + 1) + if self.history_index < hist_len: + return self.history[self.history_index] + return '' + + def getCursorPosition(self): + c = self.textCursor() + return c.position() - c.block().position() - len(self.prompt) + + def setCursorPosition(self, position): + self.moveCursor(QtGui.QTextCursor.StartOfLine) + for i in range(len(self.prompt) + position): + self.moveCursor(QtGui.QTextCursor.Right) + + def register_command(self, c, func): + methods = { c: func} + self.updateNamespace(methods) + + + def runCommand(self): + command = self.getCommand() + self.addToHistory(command) + + command = self.getConstruct(command) + + if command: + tmp_stdout = sys.stdout + + class stdoutProxy(): + def __init__(self, write_func): + self.write_func = write_func + self.skip = False + + def flush(self): + pass + + def write(self, text): + if not self.skip: + stripped_text = text.rstrip('\n') + self.write_func(stripped_text) + QtCore.QCoreApplication.processEvents() + self.skip = not self.skip + + if type(self.namespace.get(command)) == type(lambda:None): + self.appendPlainText("'%s' is a function. Type '%s()' to use it in the Python console."%(command, command)) + self.newPrompt() + return + + sys.stdout = stdoutProxy(self.appendPlainText) + try: + try: + result = eval(command, self.namespace, self.namespace) + if result != None: + if self.is_json: + util.print_json(result) + else: + self.appendPlainText(repr(result)) + except SyntaxError: + exec command in self.namespace + except SystemExit: + self.close() + except: + traceback_lines = traceback.format_exc().split('\n') + # Remove traceback mentioning this file, and a linebreak + for i in (3,2,1,-1): + traceback_lines.pop(i) + self.appendPlainText('\n'.join(traceback_lines)) + sys.stdout = tmp_stdout + self.newPrompt() + self.set_json(False) + + + def keyPressEvent(self, event): + if event.key() == QtCore.Qt.Key_Tab: + self.completions() + return + + self.hide_completions() + + if event.key() in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return): + self.runCommand() + return + if event.key() == QtCore.Qt.Key_Home: + self.setCursorPosition(0) + return + if event.key() == QtCore.Qt.Key_PageUp: + return + elif event.key() in (QtCore.Qt.Key_Left, QtCore.Qt.Key_Backspace): + if self.getCursorPosition() == 0: + return + elif event.key() == QtCore.Qt.Key_Up: + self.setCommand(self.getPrevHistoryEntry()) + return + elif event.key() == QtCore.Qt.Key_Down: + self.setCommand(self.getNextHistoryEntry()) + return + elif event.key() == QtCore.Qt.Key_L and event.modifiers() == QtCore.Qt.ControlModifier: + self.clear() + + super(Console, self).keyPressEvent(event) + + + + def completions(self): + cmd = self.getCommand() + lastword = re.split(' |\(|\)',cmd)[-1] + beginning = cmd[0:-len(lastword)] + + path = lastword.split('.') + ns = self.namespace.keys() + + if len(path) == 1: + ns = ns + prefix = '' + else: + obj = self.namespace.get(path[0]) + prefix = path[0] + '.' + ns = dir(obj) + + + completions = [] + for x in ns: + if x[0] == '_':continue + xx = prefix + x + if xx.startswith(lastword): + completions.append(xx) + completions.sort() + + if not completions: + self.hide_completions() + elif len(completions) == 1: + self.hide_completions() + self.setCommand(beginning + completions[0]) + else: + # find common prefix + p = os.path.commonprefix(completions) + if len(p)>len(lastword): + self.hide_completions() + self.setCommand(beginning + p) + else: + self.show_completions(completions) + + +welcome_message = ''' + --------------------------------------------------------------- + Welcome to a primitive Python interpreter. + --------------------------------------------------------------- +''' + +if __name__ == '__main__': + app = QtGui.QApplication(sys.argv) + console = Console(startup_message=welcome_message) + console.updateNamespace({'myVar1' : app, 'myVar2' : 1234}) + console.show(); + sys.exit(app.exec_())