Source code for nukescripts.blinkscripteditor
import PySide2
import re, sys, traceback, os
import rlcompleter
from .usdhighlighter import UsdHighlighter
from io import StringIO
import nuke_internal as nuke
#Syntax highlighting colour definitions
kwdsFgColour = PySide2.QtGui.QColor(122, 136, 53)
stringLiteralsFgColourDQ = PySide2.QtGui.QColor(226, 138, 138)
stringLiteralsFgColourSQ = PySide2.QtGui.QColor(110, 160, 121)
commentsFgColour = PySide2.QtGui.QColor(188, 179, 84)
blinkTypesColour = PySide2.QtGui.QColor(25, 25, 80)
blinkFuncsColour = PySide2.QtGui.QColor(3, 185, 191)
#Need to add in the proper methods here
[docs]class ScriptInputArea(PySide2.QtWidgets.QPlainTextEdit, PySide2.QtCore.QObject) :
#Signal that will be emitted when the user has changed the text
userChangedEvent = PySide2.QtCore.Signal()
def __init__(self, output, editor, parent=None, language='blink'):
super(ScriptInputArea, self).__init__(parent)
# Font will be setup by showEvent function, reading settings from preferences
#Setup vars
self._output = output
self._editor = editor
self._errorLine = 0
self._showErrorHighlight = True
self._completer = None
self._currentCompletion = None
self._completerShowing = False
self._showLineNumbers = True
self.setStyleSheet("background-color: rgb(81, 81, 81);")
#Setup completer
self._completer = PySide2.QtWidgets.QCompleter(self)
self._completer.setWidget(self)
self._completer.setCompletionMode(PySide2.QtWidgets.QCompleter.UnfilteredPopupCompletion)
self._completer.setCaseSensitivity(PySide2.QtCore.Qt.CaseSensitive)
self._completer.setModel(PySide2.QtCore.QStringListModel())
#Setup line numbers
self._lineNumberArea = LineNumberArea(self, parent=self)
#Add highlighter
if language == 'usd':
self._highlighterInput = UsdHighlighter(self.document(), parent=self)
else:
self._highlighterInput = InputHighlighter(self.document(), parent=self)
#Setup connections
self.cursorPositionChanged.connect(self.highlightCurrentLine)
self._completer.activated.connect(self.insertCompletion)
self._completer.highlighted.connect(self.completerHighlightChanged)
self.blockCountChanged.connect(self.updateLineNumberAreaWidth)
self.updateRequest.connect(self.updateLineNumberArea)
self.updateLineNumberAreaWidth()
self._lineNumberArea.setVisible( self._showLineNumbers )
self.setCursorWidth(PySide2.QtGui.QFontMetricsF(self.font()).width(' '))
def lineNumberAreaWidth(self) :
if not self._showLineNumbers :
return 0
digits = 1
maxNum = max(1, self.blockCount())
while (maxNum >= 10) :
maxNum /= 10
digits += 1
space = 5 + self.fontMetrics().width('9') * digits
return space
def updateLineNumberAreaWidth(self) :
self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0)
def updateLineNumberArea(self, rect, dy) :
if (dy) :
self._lineNumberArea.scroll(0, dy)
else :
self._lineNumberArea.update(0, rect.y(), self._lineNumberArea.width(), rect.height())
if (rect.contains(self.viewport().rect())) :
self.updateLineNumberAreaWidth()
[docs] def resizeEvent(self, event) :
PySide2.QtWidgets.QPlainTextEdit.resizeEvent(self, event)
cr = self.contentsRect()
self._lineNumberArea.setGeometry(PySide2.QtCore.QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height()))
def getFontFromHieroPrefs(self):
# May raise an ImportError in Nuke standalone
from hiero.core import ApplicationSettings
fontStr = ApplicationSettings().value("scripteditor/font")
# Setup new font and copy settings
font = PySide2.QtGui.QFont()
font.fromString(fontStr)
return font
def getFontFromNukePrefs(self):
# Get the font from the preferences for Nuke's Script Editor
font = PySide2.QtGui.QFont(nuke.toNode("preferences").knob("ScriptEditorFont").value())
# Set the size, also according to the Script Editor Preferences
fontSize = nuke.toNode("preferences").knob("ScriptEditorFontSize").getValue()
font.setPixelSize(fontSize);
return font
def setFontFromPrefs(self):
try:
font = self.getFontFromHieroPrefs()
except ImportError:
font = self.getFontFromNukePrefs()
# Set the font for the text editor
self.setFont(font);
# Make sure the font used for the line numbers matches the text
self._lineNumberArea.setFont(font);
[docs] def showEvent(self, event):
PySide2.QtWidgets.QPlainTextEdit.showEvent(self, event)
self.setFontFromPrefs()
def lineNumberAreaPaintEvent(self, event) :
painter = PySide2.QtGui.QPainter(self._lineNumberArea)
painter.fillRect(event.rect(), self.palette().base())
block = self.firstVisibleBlock()
blockNumber = block.blockNumber()
top = int( self.blockBoundingGeometry(block).translated(self.contentOffset()).top() )
bottom = top + int( self.blockBoundingRect(block).height() )
currentLine = self.document().findBlock(self.textCursor().position()).blockNumber()
font = painter.font()
pen = painter.pen()
painter.setPen( self.palette().color(PySide2.QtGui.QPalette.Text) )
while (block.isValid() and top <= event.rect().bottom()) :
if (block.isVisible() and bottom >= event.rect().top()) :
if ( blockNumber == currentLine ) :
painter.setPen(PySide2.QtGui.QColor(255, 255, 255))
font.setBold(True)
painter.setFont(font)
elif ( blockNumber == int(self._errorLine) - 1 ) :
painter.setPen(PySide2.QtGui.QColor(127, 0, 0))
font.setBold(True)
painter.setFont(font)
else :
painter.setPen(PySide2.QtGui.QColor(35, 35, 35))
font.setBold(False)
painter.setFont(font)
number = "%s" % str(blockNumber + 1)
painter.drawText(0, top, self._lineNumberArea.width(), self.fontMetrics().height(), PySide2.QtCore.Qt.AlignRight, number)
#Move to the next block
block = block.next()
top = bottom
bottom = top + int(self.blockBoundingRect(block).height())
blockNumber += 1
def highlightCurrentLine(self) :
extraSelections = []
if (self._showErrorHighlight and not self.isReadOnly()) :
selection = PySide2.QtWidgets.QTextEdit.ExtraSelection()
lineColor = PySide2.QtGui.QColor(255, 255, 255, 40)
selection.format.setBackground(lineColor)
selection.format.setProperty(PySide2.QtGui.QTextFormat.FullWidthSelection, True)
selection.cursor = self.textCursor()
selection.cursor.clearSelection()
extraSelections.append(selection)
self.setExtraSelections(extraSelections)
self._errorLine = 0
def highlightErrorLine(self) :
extraSelections = []
if (self._showErrorHighlight and not self.isReadOnly()) :
if (self._errorLine != 0) :
selection = PySide2.QtWidgets.QTextEdit.ExtraSelection()
selection.format.setBackground(PySide2.QtGui.QColor(255, 0, 0, 40))
selection.format.setProperty(PySide2.QtGui.QTextFormat.OutlinePen, PySide2.QtGui.QPen(PySide2.QtGui.QColor(127, 0, 0, 0)))
selection.format.setProperty(PySide2.QtGui.QTextFormat.FullWidthSelection, True)
pos = self.document().findBlockByLineNumber(int(self._errorLine)-1).position()
cursor = self.textCursor()
cursor.setPosition(pos)
selection.cursor = cursor
selection.cursor.clearSelection()
extraSelections.append(selection)
self.setExtraSelections(extraSelections)
[docs] def keyPressEvent(self, event) :
lScriptEditorMod = ((event.modifiers() and (PySide2.QtCore.Qt.ControlModifier or PySide2.QtCore.Qt.AltModifier)) == PySide2.QtCore.Qt.ControlModifier)
lScriptEditorShift = ((event.modifiers() and (PySide2.QtCore.Qt.ShiftModifier)) != 0)
lKey = event.key()
#TODO Query Completer Showing
self._completerShowing = self._completer.popup().isVisible()
if not self._completerShowing :
if (lScriptEditorMod and (lKey == PySide2.QtCore.Qt.Key_Return or lKey == PySide2.QtCore.Qt.Key_Enter)) :
if (self._editor) :
self._editor.runScript()
return
#elif lScriptEditorMod and lScriptEditorShift and lKey == PySide2.QtCore.Qt.Key_BraceLeft :
# self.decreaseIndentationSelected()
# return
#elif lScriptEditorMod and lScriptEditorShift and lKey == PySide2.QtCore.Qt.Key_BraceRight :
# self.increaseIndentationSelected()
# return
elif lScriptEditorMod and lKey == PySide2.QtCore.Qt.Key_Slash :
self.commentSelected()
return
elif lScriptEditorMod and lKey == PySide2.QtCore.Qt.Key_Backspace :
self._editor.clearOutput()
return
elif lKey == PySide2.QtCore.Qt.Key_Tab or (lScriptEditorMod and lKey == PySide2.QtCore.Qt.Key_Space) :
#Ok.
#If you have a selection you should indent
#ElIf line is blank it should always pass through the key event
#Else get the last
tc = self.textCursor()
if tc.hasSelection() :
print("Indenting")
self.increaseIndentationSelected()
else :
#Show completion
colNum = tc.columnNumber()
posNum = tc.position()
inputText = self.toPlainText()
inputTextToCursor = self.toPlainText()[0:posNum]
inputTextSplit = inputText.splitlines()
inputTextToCursorSplit = inputTextToCursor.splitlines()
runningLength = 0
currentLine = None
for line in inputTextToCursorSplit :
length = len(line)
runningLength += length
if runningLength >= posNum :
currentLine = line
break
runningLength += 1
if currentLine :
if len(currentLine.strip()) == 0 :
tc = self.textCursor()
tc.insertText(" ")
return
token = currentLine.split(" ")[-1]
if "(" in token :
token = token.split("(")[-1]
if len(token)>0:
self.completeTokenUnderCursor(token)
else :
tc = self.textCursor()
tc.insertText(" ")
else :
tc = self.textCursor()
tc.insertText(" ")
#print mid(tc.position() - tc.columnNumber(), tc.columnNumber())
else :
PySide2.QtWidgets.QPlainTextEdit.keyPressEvent(self, event)
return
else :
tc = self.textCursor()
if lKey == PySide2.QtCore.Qt.Key_Return or lKey == PySide2.QtCore.Qt.Key_Enter :
self.insertCompletion(self._currentCompletion)
self._currentCompletion = ""
self._completer.popup().hide()
self._completerShowing = False
elif lKey == PySide2.QtCore.Qt.Key_Right or lKey == PySide2.QtCore.Qt.Key_Escape:
self._completer.popup().hide()
self._completerShowing = False
elif lKey == PySide2.QtCore.Qt.Key_Tab or (lScriptEditorMod and lKey == PySide2.QtCore.Qt.Key_Space) :
self._currentCompletion = ""
self._completer.popup().hide()
else :
PySide2.QtWidgets.QPlainTextEdit.keyPressEvent(self, event)
#Edit completion model
colNum = tc.columnNumber()
posNum = tc.position()
inputText = self.toPlainText()
inputTextSplit = inputText.splitlines()
runningLength = 0
currentLine = None
for line in inputTextSplit :
length = len(line)
runningLength += length
if runningLength >= posNum :
currentLine = line
break
runningLength += 1
if currentLine :
token = currentLine.split(" ")[-1]
if "(" in token :
token = token.split("(")[-1]
self.completeTokenUnderCursor(token)
#PySide2.QtWidgets.QPlainTextEdit.keyPressEvent(self, event)
return
def insertIndent(self, tc) :
tc.beginEditBlock()
tc.insertText("\t")
tc.endEditBlock
def commentSelected(self) :
return
tc = self.textCursor();
if tc.hasSelection() :
tc.beginEditBlock()
self.ExtendSelectionToCompleteLines(tc)
start = tc.selectionStart()
end = tc.selectionEnd()
tc.setPosition(start)
if self.document().characterAt(start) == '#' :
#Comment
print("Uncommenting")
# prevPosition = end
# while tc.position() != prevPosition :
# tc.insertText("#");
# prevPosition = tc.position()
# tc.movePosition(PySide2.QtGui.QTextCursor.NextBlock, PySide2.QtGui.QTextCursorMoveAnchor)
else :
#Uncomment
print("Commenting")
# prevPosition = end
# while tc.position() != prevPosition :
# if self.document().characterAt(tc.position()) == '#' :
# tc.deleteChar()
# prevPosition = tc.position()
# tc.movePosition(PySide2.QtGui.QTextCursor.NextBlock, PySide2.QtGui.QTextCursor.MoveAnchor)
#self.select(start, tc.position())
#tc.endEditBlock()
#self.ensureCursorVisible()
def ExtendSelectionToCompleteLines(self, tc) :
lPos = tc.position()
lAnchor = tc.anchor()
tc.setPosition(tc.anchor());
if (lPos >= lAnchor) :
print("Moving to start of line")
#Position was after the anchor. Move to the start of the line,
tc.movePosition(PySide2.QtGui.QTextCursor.StartOfLine)
tc.setPosition(lPos, PySide2.QtGui.QTextCursor.KeepAnchor)
#Don't extend if the position was at the beginning of a new line
lSelected = tc.selectedText()
if lSelected != "" and lSelected[-2:-1] != "\n" :
tc.movePosition(PySide2.QtGui.QTextCursor.EndOfLine, PySide2.QtGui.QTextCursor.KeepAnchor)
else :
print("Moving to end of line")
#Position was before the anchor. Move to the end of the line,
#then select to the start of the line where the position was.
#Don't select to the end of the current line if the anchor was at the beginning
tc.movePosition(PySide2.QtGui.QTextCursor.PreviousCharacter,PySide2.QtGui.QTextCursor.KeepAnchor)
lSelected = tc.selectedText()
tc.movePosition(PySide2.QtGui.QTextCursor.NextCharacter)
if lSelected != "" and lSelected[-2:-1] != "\n" :
tc.movePosition(PySide2.QtGui.QTextCursor.EndOfLine)
tc.setPosition(lPos, PySide2.QtGui.QTextCursor.KeepAnchor)
tc.movePosition(PySide2.QtGui.QTextCursor.StartOfLine, PySide2.QtGui.QTextCursor.KeepAnchor)
def increaseIndentationSelected(self) :
print("Need to fix indenting")
return
tc = self.textCursor()
if tc.hasSelection() :
start = tc.selectionStart()
self.ExtendSelectionToCompleteLines(tc)
selected = tc.selectedText()
self.insertIndent(tc)
#replace paragraph things here
paraReplace = "\n" + ("\t")
indentedParas = selected.replace('\n', paraReplace)
textSplit = selected.splitlines()
indentedText = paraReplace.join(textSplit)
tc.beginEditBlock()
tc.removeSelectedText()
tc.insertText(indentedText)
tc.endEditBlock()
print("Need to fix selection after indenting")
self.setTextCursor(tc)
end = tc.selectionEnd()
tc.setPosition(start)
tc.setPosition(end, PySide2.QtGui.QTextCursor.KeepAnchor)
self.ensureCursorVisible()
def decreaseIndentationSelected(self):
print("Need to fix unindenting")
return
tc = self.textCursor()
if (tc.hasSelection()) :
start = tc.selectionStart()
self.ExtendSelectionToCompleteLines(tc)
return
selected = tc.selectedText()
#Get rid of indents
textSplit = selected.splitlines()
unsplitLines = []
unindentedText = selected
for line in textSplit :
print(type(line))
unsplitLines.append(line.replace('\t', '', 1))
unindentedText = "\n".join(unsplitLines)
tc.beginEditBlock()
tc.removeSelectedText()
tc.insertText(unindentedText)
tc.endEditBlock()
end = tc.selectionEnd()
tc.setPosition(start)
tc.setPosition(end, PySide2.QtGui.QTextCursor.KeepAnchor)
#tc.select(start, tc.position())
self.setTextCursor(tc)
self.ensureCursorVisible()
def completionsForToken(self, token):
comp = rlcompleter.Completer()
completions = []
completion = 1
for x in range(0, 1000):
completion = comp.complete(token, x)
if completion is not None:
completions.append(completion)
else :
break
return completions
def completeTokenUnderCursor(self, token) :
#Clean token
token = token.lstrip().rstrip()
completionList = self.completionsForToken(token)
if len(completionList) == 0 :
return
#Set model for _completer to completion list
self._completer.model().setStringList(completionList)
#Set the prefix
self._completer.setCompletionPrefix(token)
#Check if we need to make it visible
if self._completer.popup().isVisible() :
rect = self.cursorRect();
rect.setWidth(self._completer.popup().sizeHintForColumn(0) + self._completer.popup().verticalScrollBar().sizeHint().width())
self._completer.complete(rect)
return
#Make it visible
if len(completionList) == 1 :
self.insertCompletion(completionList[0]);
else :
rect = self.cursorRect();
rect.setWidth(self._completer.popup().sizeHintForColumn(0) + self._completer.popup().verticalScrollBar().sizeHint().width())
self._completer.complete(rect)
return
def insertCompletion(self, completion):
if completion :
completionNoToken = completion[len(self._completer.completionPrefix()):]
lCursor = self.textCursor()
lCursor.insertText(completionNoToken)
return
def completerHighlightChanged(self, highlighted):
self._currentCompletion = highlighted
# void ScriptInputArea::insertCompletion(const QString& completion)
# {
# QString suffix = completion;
# suffix.remove(0, _completer->completionPrefix().length());
# QTextCursor lCursor = textCursor();
# lCursor.insertText(suffix);
# }
def getErrorLineFromTraceback(self, tracebackStr) :
finalLine = None
for line in tracebackStr.split('\n') :
if 'File "<string>", line' in line :
finalLine = line
if finalLine == None :
return 0
try :
errorLine = finalLine.split(',')[1].split(' ')[2]
return errorLine
except :
return 0
def runScript(self):
_selection = False;
self.highlightCurrentLine()
#Get text
text = self.toPlainText()
#Check if we've got some text selected. If so, replace text with selected text
tc = self.textCursor()
if tc.hasSelection() :
_selection = True
rawtext = tc.selectedText()
rawSplit = rawtext.splitlines()
rawJoined = '\n'.join(rawSplit)
text = rawJoined.lstrip().rstrip()
#Fix syntax error if last line is a comment with no new line
if not text.endswith('\n') :
text = text + '\n'
#JERRY has a lock here
#Compile
result = None
compileSuccess = False
runError = False
try :
compiled = compile(text, '<string>', 'exec')
compileSuccess = True
except Exception as e:
result = traceback.format_exc()
runError = True
compileSuccess = False
oldStdOut = sys.stdout
if compileSuccess :
#Override stdout to capture exec results
buffer = StringIO()
sys.stdout = buffer
try :
exec(compiled, globals())
except Exception as e:
runError = True
result = traceback.format_exc()
else :
result = buffer.getvalue()
sys.stdout = oldStdOut
#print "STDOUT Restored"
#Update output
self._output.updateOutput( text )
self._output.updateOutput( "\n# Result: \n" )
self._output.updateOutput( result )
self._output.updateOutput( "\n" )
if runError :
#print "There was an error"
#print "result is %s " % result
self._errorLine = self.getErrorLineFromTraceback(result)
self.highlightErrorLine()
#Need to add in the proper methods here
[docs]class InputHighlighter(PySide2.QtGui.QSyntaxHighlighter) :
def __init__(self, doc, parent=None):
super(InputHighlighter, self).__init__(parent)
self.setDocument(doc)
self._rules = []
self._keywords = PySide2.QtGui.QTextCharFormat()
self._strings = PySide2.QtGui.QTextCharFormat()
self._stringSingleQuotes = PySide2.QtGui.QTextCharFormat()
self._comment = PySide2.QtGui.QTextCharFormat()
self._blinkFuncs = PySide2.QtGui.QTextCharFormat()
self._blinkTypes = PySide2.QtGui.QTextCharFormat()
self._keywords.setForeground(kwdsFgColour)
self._keywords.setFontWeight(PySide2.QtGui.QFont.Bold)
#Construct rules for C++ keywords
#keywordPatterns = ["\\bchar\\b" , "\\bclass\\b" , "\\bconst\\b"
# , "\\bdouble\\b" , "\\benum\\b" , "\\bexplicit\\b"
# , "\\bfriend\\b" , "\\binline\\b" , "\\bint\\b"
# , "\\blong\\b" , "\\bnamespace\\b" , "\\boperator\\b"
# , "\\bprivate\\b" , "\\bprotected\\b" , "\\bpublic\\b"
# , "\\bshort\\b" , "\\bsignals\\b" , "\\bsigned\\b"
# , "\\bslots\\b" , "\\bstatic\\b" , "\\bstruct\\b"
# , "\\btemplate\\b" , "\\btypedef\\b" , "\\btypename\\b"
# , "\\bunion\\b" , "\\bunsigned\\b" , "\\bvirtual\\b"
# , "\\bvoid\\b" , "\\bvolatile\\b"]
#Construct rules for RIP++ keywords
keywordPatterns = ["\\bchar\\b" ,
"\\bclass\\b" ,
"\\bconst\\b" ,
"\\bdouble\\b" ,
"\\benum\\b" ,
"\\bexplicit\\b" ,
"\\bfriend\\b" ,
"\\binline\\b" ,
"\\bint\\b" ,
"\\blong\\b" ,
"\\bnamespace\\b" ,
"\\boperator\\b" ,
"\\bprivate\\b" ,
"\\bprotected\\b" ,
"\\bpublic\\b" ,
"\\bshort\\b" ,
"\\bsigned\\b" ,
"\\bstatic\\b" ,
"\\bstruct\\b" ,
"\\btemplate\\b" ,
"\\btypedef\\b" ,
"\\btypename\\b" ,
"\\bunion\\b" ,
"\\bunsigned\\b" ,
"\\bvirtual\\b" ,
"\\bvoid\\b" ,
"\\bvolatile\\b",
"\\blocal\\b",
"\\bparam\\b",
"\\bkernel\\b",
]
for pattern in keywordPatterns:
rule = {}
rule['pattern'] = pattern
rule['format'] = self._keywords
self._rules.append(rule)
#Blink funcs
self._blinkFuncs.setForeground(blinkFuncsColour)
#self._blinkFuncs.setFontWeight(PySide2.QtGui.QFont.Bold)
blinkFuncPatterns = ["\\bdefine\\b" ,
"\\bdefineParam\\b" ,
"\\bprocess\\b" ,
"\\binit\\b" ,
"\\bsetRange\\b" ,
"\\bsetAxis\\b" ,
"\\bmedian\\b" ,
"\\bbilinear\\b" ,
]
for pattern in blinkFuncPatterns:
rule = {}
rule['pattern'] = pattern
rule['format'] = self._blinkFuncs
self._rules.append(rule)
#Blink types
self._blinkTypes.setForeground(blinkTypesColour)
#self._blinkTypes.setFontWeight(PySide2.QtGui.QFont.Bold)
blinkTypesPatterns = ["\\bImage\\b" ,
"\\beRead\\b" ,
"\\beWrite\\b" ,
"\\beEdgeClamped\\b" ,
"\\beEdgeConstant\\b" ,
"\\beEdgeNull\\b" ,
"\\beAccessPoint\\b" ,
"\\beAccessRanged1D\\b" ,
"\\beAccessRanged2D\\b" ,
"\\beAccessRandom\\b" ,
"\\beComponentWise\\b" ,
"\\bePixelWise\\b" ,
"\\bImageComputationKernel\\b" ,
"\\bint\\b" ,
"\\bint2\\b" ,
"\\bint3\\b" ,
"\\bint4\\b" ,
"\\bfloat\\b" ,
"\\bfloat2\\b" ,
"\\bfloat3\\b" ,
"\\bfloat4\\b" ,
"\\bfloat3x3\\b" ,
"\\bfloat4x4\\b" ,
"\\bbool\\b" ,
]
for pattern in blinkTypesPatterns:
rule = {}
rule['pattern'] = pattern
rule['format'] = self._blinkTypes
self._rules.append(rule)
#String Literals
self._strings.setForeground(stringLiteralsFgColourDQ)
rule = {}
rule['pattern'] = "\"([^\"\\\\]|\\\\.)*\""
rule['format'] = self._strings
self._rules.append(rule)
#String single quotes
self._stringSingleQuotes.setForeground(stringLiteralsFgColourSQ)
rule = {}
rule['pattern'] = "'([^'\\\\]|\\\\.)*'"
rule['format'] = self._stringSingleQuotes
self._rules.append(rule)
#Comments
self._comment.setForeground(commentsFgColour)
rule = {}
rule['pattern'] = "//[^\n]*"
rule['format'] = self._comment
self._rules.append(rule)
[docs] def highlightBlock(self, text) :
text = str(text)
for rule in self._rules :
expression = rule['pattern']
if len(text) > 0 :
results = re.finditer(expression, text)
#Loop through all results
for result in results :
index = result.start()
length = result.end() - result.start()
self.setFormat(index, length, rule['format'])
[docs]class LineNumberArea(PySide2.QtWidgets.QWidget):
def __init__(self, scriptInputWidget, parent=None):
super(LineNumberArea, self).__init__(parent)
self._scriptInputWidget = scriptInputWidget
#self.setStyleSheet("QWidget { background-color: blue; }");
self.setStyleSheet("text-align: center;")
[docs] def sizeHint(self) :
return PySide2.QtCore.QSize(self._scriptInputWidget.lineNumberAreaWidth(), 0)