-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
239 additions
and
5 deletions.
There are no files selected for viewing
227 changes: 227 additions & 0 deletions
227
package/PartSeg/common_backend/python_syntax_highlight.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
# pragma: no cover | ||
# syntax.py code copied from https://wiki.python.org/moin/PyQt/Python%20syntax%20highlighting | ||
|
||
from qtpy import QtCore, QtGui | ||
|
||
|
||
def format(color, style=""): | ||
"""Return a QTextCharFormat with the given attributes.""" | ||
_color = QtGui.QColor() | ||
_color.setNamedColor(color) | ||
|
||
_format = QtGui.QTextCharFormat() | ||
_format.setForeground(_color) | ||
if "bold" in style: | ||
_format.setFontWeight(QtGui.QFont.Bold) | ||
if "italic" in style: | ||
_format.setFontItalic(True) | ||
|
||
return _format | ||
|
||
|
||
# Syntax styles that can be shared by all languages | ||
STYLES = { | ||
"keyword": format("blue"), | ||
"operator": format("red"), | ||
"brace": format("darkGray"), | ||
"defclass": format("black", "bold"), | ||
"string": format("magenta"), | ||
"string2": format("darkMagenta"), | ||
"comment": format("darkGreen", "italic"), | ||
"self": format("black", "italic"), | ||
"numbers": format("brown"), | ||
} | ||
|
||
|
||
class PythonHighlighter(QtGui.QSyntaxHighlighter): | ||
"""Syntax highlighter for the Python language.""" | ||
|
||
# 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"\~", | ||
">>", | ||
"<<", | ||
] | ||
|
||
# Python braces | ||
braces = [ | ||
r"\{", | ||
r"\}", | ||
r"\(", | ||
r"\)", | ||
r"\[", | ||
r"\]", | ||
] | ||
|
||
def __init__(self, parent: QtGui.QTextDocument) -> None: | ||
super().__init__(parent) | ||
|
||
# Multi-line strings (expression, flag, style) | ||
self.tri_single = (QtCore.QRegExp("'''"), 1, STYLES["string2"]) | ||
self.tri_double = (QtCore.QRegExp('"""'), 2, STYLES["string2"]) | ||
|
||
rules = [] | ||
|
||
# Keyword, operator, and brace rules | ||
rules += [(r"\b%s\b" % w, 0, STYLES["keyword"]) for w in PythonHighlighter.keywords] | ||
rules += [(f"{o}", 0, STYLES["operator"]) for o in PythonHighlighter.operators] | ||
rules += [(f"{b}", 0, STYLES["brace"]) for b in PythonHighlighter.braces] | ||
|
||
# All other rules | ||
rules += [ | ||
# 'self' | ||
(r"\bself\b", 0, STYLES["self"]), | ||
# 'def' followed by an identifier | ||
(r"\bdef\b\s*(\w+)", 1, STYLES["defclass"]), | ||
# 'class' followed by an identifier | ||
(r"\bclass\b\s*(\w+)", 1, STYLES["defclass"]), | ||
# Numeric literals | ||
(r"\b[+-]?[0-9]+[lL]?\b", 0, STYLES["numbers"]), | ||
(r"\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b", 0, STYLES["numbers"]), | ||
(r"\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b", 0, STYLES["numbers"]), | ||
# Double-quoted string, possibly containing escape sequences | ||
(r'"[^"\\]*(\\.[^"\\]*)*"', 0, STYLES["string"]), | ||
# Single-quoted string, possibly containing escape sequences | ||
(r"'[^'\\]*(\\.[^'\\]*)*'", 0, STYLES["string"]), | ||
# From '#' until a newline | ||
(r"#[^\n]*", 0, STYLES["comment"]), | ||
] | ||
|
||
# Build a QRegExp for each pattern | ||
self.rules = [(QtCore.QRegExp(pat), index, fmt) for (pat, index, fmt) in rules] | ||
|
||
def highlightBlock(self, text): | ||
"""Apply syntax highlighting to the given block of text.""" | ||
self.tripleQuoutesWithinStrings = [] | ||
# Do other syntax formatting | ||
for expression, nth, format in self.rules: | ||
index = expression.indexIn(text, 0) | ||
if index >= 0 and expression.pattern() in [r'"[^"\\]*(\\.[^"\\]*)*"', r"'[^'\\]*(\\.[^'\\]*)*'"]: | ||
inner_index = self.tri_single[0].indexIn(text, index + 1) | ||
if inner_index == -1: | ||
inner_index = self.tri_double[0].indexIn(text, index + 1) | ||
|
||
if inner_index != -1: | ||
self.tripleQuoutesWithinStrings.extend(range(inner_index, inner_index + 3)) | ||
|
||
while index >= 0: | ||
# skipping triple quotes within strings | ||
if index in self.tripleQuoutesWithinStrings: | ||
index += 1 | ||
expression.indexIn(text, index) | ||
continue | ||
|
||
# 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) | ||
|
||
self.setCurrentBlockState(0) | ||
|
||
# Do multi-line strings | ||
in_multiline = self.match_multiline(text, *self.tri_single) | ||
if not in_multiline: | ||
in_multiline = self.match_multiline(text, *self.tri_double) | ||
|
||
def match_multiline(self, text, delimiter, in_state, style): | ||
"""Do highlighting of multi-line strings. ``delimiter`` should be a | ||
``QRegExp`` for triple-single-quotes or triple-double-quotes, and | ||
``in_state`` should be a unique integer to represent the corresponding | ||
state changes when inside those strings. Returns True if we're still | ||
inside a multi-line string when this function is finished. | ||
""" | ||
# If inside triple-single quotes, start at 0 | ||
if self.previousBlockState() == in_state: | ||
start = 0 | ||
add = 0 | ||
# Otherwise, look for the delimiter on this line | ||
else: | ||
start = delimiter.indexIn(text) | ||
# skipping triple quotes within strings | ||
if start in self.tripleQuoutesWithinStrings: | ||
return False | ||
# Move past this match | ||
add = delimiter.matchedLength() | ||
|
||
# As long as there's a delimiter match on this line... | ||
while start >= 0: | ||
# Look for the ending delimiter | ||
end = delimiter.indexIn(text, start + add) | ||
# Ending delimiter on this line? | ||
if end >= add: | ||
length = end - start + add + delimiter.matchedLength() | ||
self.setCurrentBlockState(0) | ||
# No; multi-line string | ||
else: | ||
self.setCurrentBlockState(in_state) | ||
length = len(text) - start + add | ||
# Apply formatting | ||
self.setFormat(start, length, style) | ||
# Look for the next match | ||
start = delimiter.indexIn(text, start + length) | ||
|
||
# Return True if still inside a multi-line string, False otherwise | ||
return self.currentBlockState() == in_state |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,3 +34,4 @@ xlsxwriter | |
sphinx!=3.5.0 | ||
pydantic!=1.8 | ||
vispy | ||
traceback-with-variables |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters