mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-04-28 17:57:16 +02:00
[ui] ScriptEditor: Added syntax colorization for the script editor
Python syntax within the script editor is now highlighted making it easier to understand and write smaller code in it.
This commit is contained in:
parent
4464cdf799
commit
2e577274e6
3 changed files with 187 additions and 2 deletions
|
@ -7,6 +7,7 @@ def registerTypes():
|
|||
from meshroom.ui.components.scene3D import Scene3DHelper, TrackballController, Transformations3DHelper
|
||||
from meshroom.ui.components.csvData import CsvData
|
||||
from meshroom.ui.components.geom2D import Geom2D
|
||||
from meshroom.ui.components.scriptEditor import PySyntaxHighlighter
|
||||
|
||||
qmlRegisterType(EdgeMouseArea, "GraphEditor", 1, 0, "EdgeMouseArea")
|
||||
qmlRegisterType(ClipboardHelper, "Meshroom.Helpers", 1, 0, "ClipboardHelper") # TODO: uncreatable
|
||||
|
@ -15,5 +16,6 @@ def registerTypes():
|
|||
qmlRegisterType(Transformations3DHelper, "Meshroom.Helpers", 1, 0, "Transformations3DHelper") # TODO: uncreatable
|
||||
qmlRegisterType(TrackballController, "Meshroom.Helpers", 1, 0, "TrackballController")
|
||||
qmlRegisterType(CsvData, "DataObjects", 1, 0, "CsvData")
|
||||
qmlRegisterType(PySyntaxHighlighter, "ScriptEditor", 1, 0, "PySyntaxHighlighter")
|
||||
|
||||
qmlRegisterSingletonType(Geom2D, "Meshroom.Helpers", 1, 0, "Geom2D")
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
from PySide6.QtCore import QObject, Slot, QSettings
|
||||
|
||||
""" Script Editor for Meshroom.
|
||||
"""
|
||||
# STD
|
||||
from io import StringIO
|
||||
from contextlib import redirect_stdout
|
||||
import traceback
|
||||
|
||||
# Qt
|
||||
from PySide6 import QtCore, QtGui, QtQuick
|
||||
from PySide6.QtCore import Property, QObject, Slot, Signal, QSettings
|
||||
|
||||
|
||||
class ScriptEditorManager(QObject):
|
||||
""" Manages the script editor history and logs.
|
||||
"""
|
||||
|
@ -114,3 +120,171 @@ class ScriptEditorManager(QObject):
|
|||
settings.beginGroup(self._GROUP)
|
||||
settings.setValue(self._KEY, script)
|
||||
settings.sync()
|
||||
|
||||
|
||||
class CharFormat(QtGui.QTextCharFormat):
|
||||
""" The Char format for the syntax.
|
||||
"""
|
||||
|
||||
def __init__(self, color, bold=False, italic=False):
|
||||
""" Constructor.
|
||||
"""
|
||||
super().__init__()
|
||||
|
||||
self._color = QtGui.QColor()
|
||||
self._color.setNamedColor(color)
|
||||
|
||||
# Update the Foreground color
|
||||
self.setForeground(self._color)
|
||||
|
||||
# The font characteristics
|
||||
if bold:
|
||||
self.setFontWeight(QtGui.QFont.Bold)
|
||||
if italic:
|
||||
self.setFontItalic(True)
|
||||
|
||||
|
||||
class PySyntaxHighlighter(QtGui.QSyntaxHighlighter):
|
||||
"""Syntax highlighter for the Python language.
|
||||
"""
|
||||
|
||||
# Syntax styles that can be shared by all languages
|
||||
STYLES = {
|
||||
"keyword" : CharFormat("#9e59b3"), # Purple
|
||||
"operator" : CharFormat("#2cb8a0"), # Teal
|
||||
"brace" : CharFormat("#2f807e"), # Dark Aqua
|
||||
"defclass" : CharFormat("#c9ba49", bold=True), # Yellow
|
||||
"deffunc" : CharFormat("#4996c9", bold=True), # Blue
|
||||
"string" : CharFormat("#7dbd39"), # Greeny
|
||||
"comment" : CharFormat("#8d8d8d", italic=True), # Dark Grayish
|
||||
"self" : CharFormat("#e6ba43", italic=True), # Yellow
|
||||
"numbers" : CharFormat("#d47713"), # Orangish
|
||||
}
|
||||
|
||||
# Python keywords
|
||||
keywords = (
|
||||
"and", "assert", "break", "class", "continue", "def",
|
||||
"del", "elif", "else", "except", "exec", "finally",
|
||||
"for", "from", "global", "if", "import", "in",
|
||||
"is", "lambda", "not", "or", "pass", "print",
|
||||
"raise", "return", "try", "while", "yield",
|
||||
"None", "True", "False",
|
||||
)
|
||||
|
||||
# Python operators
|
||||
operators = (
|
||||
"=",
|
||||
# Comparison
|
||||
"==", "!=", "<", "<=", ">", ">=",
|
||||
# Arithmetic
|
||||
r"\+", "-", r"\*", "/", "//", r"\%", r"\*\*",
|
||||
# In-place
|
||||
r"\+=", "-=", r"\*=", "/=", r"\%=",
|
||||
# Bitwise
|
||||
r"\^", r"\|", r"\&", r"\~", r">>", r"<<",
|
||||
)
|
||||
|
||||
# Python braces
|
||||
braces = (r"\{", r"\}", r"\(", r"\)", r"\[", r"\]")
|
||||
|
||||
def __init__(self, parent=None):
|
||||
""" Constructor.
|
||||
|
||||
Keyword Args:
|
||||
parent (QObject): The QObject parent from the QML side.
|
||||
"""
|
||||
super().__init__(parent)
|
||||
|
||||
# The Document to highlight
|
||||
self._document = None
|
||||
|
||||
# Build a QRegExp for each of the pattern
|
||||
self._rules = self.__rules()
|
||||
|
||||
# Private
|
||||
def __rules(self):
|
||||
""" Formatting rules.
|
||||
"""
|
||||
# Set of rules accordind to which the highlight should occur
|
||||
rules = []
|
||||
|
||||
# Keyword rules
|
||||
rules += [(QtCore.QRegExp(r"\b" + w + r"\s"), 0, PySyntaxHighlighter.STYLES["keyword"]) for w in PySyntaxHighlighter.keywords]
|
||||
# Operator rules
|
||||
rules += [(QtCore.QRegExp(o), 0, PySyntaxHighlighter.STYLES["operator"]) for o in PySyntaxHighlighter.operators]
|
||||
# Braces
|
||||
rules += [(QtCore.QRegExp(b), 0, PySyntaxHighlighter.STYLES["brace"]) for b in PySyntaxHighlighter.braces]
|
||||
|
||||
# All other rules
|
||||
rules += [
|
||||
# self
|
||||
(QtCore.QRegExp(r'\bself\b'), 0, PySyntaxHighlighter.STYLES["self"]),
|
||||
|
||||
# 'def' followed by an identifier
|
||||
(QtCore.QRegExp(r'\bdef\b\s*(\w+)'), 1, PySyntaxHighlighter.STYLES["deffunc"]),
|
||||
# 'class' followed by an identifier
|
||||
(QtCore.QRegExp(r'\bclass\b\s*(\w+)'), 1, PySyntaxHighlighter.STYLES["defclass"]),
|
||||
|
||||
# Numeric literals
|
||||
(QtCore.QRegExp(r'\b[+-]?[0-9]+[lL]?\b'), 0, PySyntaxHighlighter.STYLES["numbers"]),
|
||||
(QtCore.QRegExp(r'\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b'), 0, PySyntaxHighlighter.STYLES["numbers"]),
|
||||
(QtCore.QRegExp(r'\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b'), 0, PySyntaxHighlighter.STYLES["numbers"]),
|
||||
|
||||
# Double-quoted string, possibly containing escape sequences
|
||||
(QtCore.QRegExp(r'"[^"\\]*(\\.[^"\\]*)*"'), 0, PySyntaxHighlighter.STYLES["string"]),
|
||||
# Single-quoted string, possibly containing escape sequences
|
||||
(QtCore.QRegExp(r"'[^'\\]*(\\.[^'\\]*)*'"), 0, PySyntaxHighlighter.STYLES["string"]),
|
||||
|
||||
# From '#' until a newline
|
||||
(QtCore.QRegExp(r'#[^\n]*'), 0, PySyntaxHighlighter.STYLES['comment']),
|
||||
]
|
||||
|
||||
return rules
|
||||
|
||||
def highlightBlock(self, text):
|
||||
""" Applies syntax highlighting to the given block of text.
|
||||
|
||||
Args:
|
||||
text (str): The text to highlight.
|
||||
"""
|
||||
# Do other syntax formatting
|
||||
for expression, nth, _format in self._rules:
|
||||
# fetch the index of the expression in text
|
||||
index = expression.indexIn(text, 0)
|
||||
|
||||
while index >= 0:
|
||||
# We actually want the index of the nth match
|
||||
index = expression.pos(nth)
|
||||
length = len(expression.cap(nth))
|
||||
self.setFormat(index, length, _format)
|
||||
index = expression.indexIn(text, index + length)
|
||||
|
||||
def textDoc(self):
|
||||
""" Returns the document being highlighted.
|
||||
"""
|
||||
return self._document
|
||||
|
||||
def setTextDocument(self, document):
|
||||
""" Sets the document on the Highlighter.
|
||||
|
||||
Args:
|
||||
document (QtQuick.QQuickTextDocument): The document from the QML engine.
|
||||
"""
|
||||
# If the same document is provided again
|
||||
if document == self._document:
|
||||
return
|
||||
|
||||
# Update the class document
|
||||
self._document = document
|
||||
|
||||
# Set the document on the highlighter
|
||||
self.setDocument(self._document.textDocument())
|
||||
|
||||
# Emit that the document is now changed
|
||||
self.textDocumentChanged.emit()
|
||||
|
||||
# Signals
|
||||
textDocumentChanged = Signal()
|
||||
|
||||
# Property
|
||||
textDocument = Property(QtQuick.QQuickTextDocument, textDoc, setTextDocument, notify=textDocumentChanged)
|
||||
|
|
|
@ -9,6 +9,8 @@ import Utils 1.0
|
|||
|
||||
import Qt.labs.platform 1.0 as Platform
|
||||
|
||||
import ScriptEditor 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
|
@ -339,6 +341,13 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Syntax Highlights for the Input Area for Python Based Syntax
|
||||
PySyntaxHighlighter {
|
||||
id: syntaxHighlighter
|
||||
// The document to highlight
|
||||
textDocument: input.textDocument
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue