def write(self, text, prompt=0, color=None): """ write(text, prompt=0, color=None) Write to the shell. If prompt is 0 (default) the text is printed before the prompt. If prompt is 1, the text is printed after the prompt, the new prompt becomes null. If prompt is 2, the given text becomes the new prompt. The color of the text can also be specified (as a hex-string). """ # From The Qt docs: Note that a cursor always moves when text is # inserted before the current position of the cursor, and it always # keeps its position when text is inserted after the current position # of the cursor. # Make sure there's text and make sure its a string if not text: return if isinstance(text, bytes): text = text.decode('utf-8') # Prepare format format = QtGui.QTextCharFormat() if color: format.setForeground(QtGui.QColor(color)) #pos1, pos2 = self._cursor1.position(), self._cursor2.position() # Just in case, clear any selection of the cursors self._cursor1.clearSelection() self._cursor2.clearSelection() if prompt == 0: # Insert text behind prompt (normal streams) self._cursor1.setKeepPositionOnInsert(False) self._cursor2.setKeepPositionOnInsert(False) text = self._handleBackspaces(text) if len(text) < 1024: # Insert text self._cursor1.insertText(text, format) else: # Insert per line (very long lines are split in smaller ones) for line in self._splitLinesForPrinting(text): self._cursor1.insertText(line, format) elif prompt == 1: # Insert command text after prompt, prompt becomes null (input) self._lastCommandCursor.setPosition(self._cursor2.position()) self._cursor1.setKeepPositionOnInsert(False) self._cursor2.setKeepPositionOnInsert(False) self._cursor2.insertText(text, format) self._cursor1.setPosition(self._cursor2.position(), A_MOVE) elif prompt == 2 and text == '\b': # Remove prompt (used when closing the kernel) self._cursor1.setPosition(self._cursor2.position(), A_KEEP) self._cursor1.removeSelectedText() self._cursor2.setPosition(self._cursor1.position(), A_MOVE) elif prompt == 2: # Insert text after prompt, inserted text becomes new prompt self._cursor1.setPosition(self._cursor2.position(), A_MOVE) self._cursor1.setKeepPositionOnInsert(True) self._cursor2.setKeepPositionOnInsert(False) self._cursor1.insertText(text, format) # Reset cursor states for the user to type his/her commands self._cursor1.setKeepPositionOnInsert(True) self._cursor2.setKeepPositionOnInsert(True) # Make sure that cursor is visible (only when cursor is at edit line) if not self.isReadOnly(): self.ensureCursorVisible() # Scroll along with the text if lines are popped from the top elif self.blockCount() == MAXBLOCKCOUNT: n = text.count('\n') sb = self.verticalScrollBar() sb.setValue(sb.value() - n)
def highlightBlock(self, line): t0 = time.time() # Make sure this is a Unicode Python string line = str(line) # Get previous state previousState = self.previousBlockState() # Get parser parser = None if hasattr(self._codeEditor, 'parser'): parser = self._codeEditor.parser() # Get function to get format nameToFormat = self._codeEditor.getStyleElementFormat # Last line? cursor1 = self._codeEditor._cursor1 cursor2 = self._codeEditor._cursor2 commandCursor = self._codeEditor._lastCommandCursor curBlock = self.currentBlock() # atLastPrompt, atCurrentPrompt = False, False if curBlock.position() == 0: pass elif curBlock.position() == commandCursor.block().position(): atLastPrompt = True elif curBlock.position() >= cursor1.block().position(): atCurrentPrompt = True if (atLastPrompt or atCurrentPrompt) and parser: if atCurrentPrompt: pos1, pos2 = cursor1.positionInBlock( ), cursor2.positionInBlock() else: pos1, pos2 = 0, commandCursor.positionInBlock() self.setCurrentBlockState(0) for token in parser.parseLine(line, previousState): # Handle block state if isinstance(token, parsers.BlockState): self.setCurrentBlockState(token.state) else: # Get format try: format = nameToFormat(token.name).textCharFormat except KeyError: #print(repr(nameToFormat(token.name))) continue # Set format #format.setFontWeight(99) if token.start >= pos2: self.setFormat(token.start, token.end - token.start, format) # Set prompt to bold if atCurrentPrompt: format = QtGui.QTextCharFormat() format.setFontWeight(99) self.setFormat(pos1, pos2 - pos1, format) #Get the indentation setting of the editors indentUsingSpaces = self._codeEditor.indentUsingSpaces() # Get user data bd = self.getCurrentBlockUserData() leadingWhitespace = line[:len(line) - len(line.lstrip())] if '\t' in leadingWhitespace and ' ' in leadingWhitespace: #Mixed whitespace bd.indentation = 0 format = QtGui.QTextCharFormat() format.setUnderlineStyle(QtGui.QTextCharFormat.SpellCheckUnderline) format.setUnderlineColor(QtCore.Qt.red) format.setToolTip('Mixed tabs and spaces') self.setFormat(0, len(leadingWhitespace), format) elif ('\t' in leadingWhitespace and indentUsingSpaces) or \ (' ' in leadingWhitespace and not indentUsingSpaces): #Whitespace differs from document setting bd.indentation = 0 format = QtGui.QTextCharFormat() format.setUnderlineStyle(QtGui.QTextCharFormat.SpellCheckUnderline) format.setUnderlineColor(QtCore.Qt.blue) format.setToolTip('Whitespace differs from document setting') self.setFormat(0, len(leadingWhitespace), format) else: # Store info for indentation guides # amount of tabs or spaces bd.indentation = len(leadingWhitespace)