-
Notifications
You must be signed in to change notification settings - Fork 1
/
python_syntax_highlighting.py
114 lines (98 loc) · 4.22 KB
/
python_syntax_highlighting.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from PyQt6 import QtCore, QtGui
from PyQt6.QtGui import QFont
from PyQt6.QtGui import QColorConstants as Cc
import keyword
import re
BUILTINS = dir(__builtins__)
KEYWORDS = keyword.kwlist
operators = [
'=',
'==', '!=', '<', '<=', '>', '>=',
'+', '-', '*', '/', '//', '%', '**',
'+=', '-=', '*=', '/=', '%=',
'^', '|', '&', '~', '>>', '<<',
]
braces = [
'{', '}', '(', ')', '[', ']',
]
class PythonHighlighter(QtGui.QSyntaxHighlighter):
def __init__(self, doc, text_size):
super().__init__(doc)
self.text_size = text_size
self.font = "Consolas"
self.styles = {
'keyword': self.syntax_frmt(Cc.Svg.orange),
'operator': self.syntax_frmt(Cc.Svg.lightgrey),
'brace': self.syntax_frmt(Cc.Svg.lightgrey),
'string': self.syntax_frmt(Cc.Svg.lightgreen),
'comment': self.syntax_frmt(Cc.Svg.darkslategray, 'italic'),
'self': self.syntax_frmt(Cc.Svg.purple, 'italic'),
'numbers': self.syntax_frmt(Cc.Svg.dodgerblue),
'builtins': self.syntax_frmt(Cc.Svg.blueviolet)
}
def highlightBlock(self, text: str):
font_frmt = QtGui.QTextCharFormat()
font_frmt.setFontFamily(self.font)
font_frmt.setFontPointSize(self.text_size)
self.setFormat(0, len(text), font_frmt)
for desc, style in zip((operators, BUILTINS, KEYWORDS, braces),
('operator', 'builtins', 'keyword', 'brace')):
for i in desc:
expression = QtCore.QRegularExpression(rf"\b{i}\b")
match = expression.globalMatch(text)
while match.hasNext():
next_ = match.next()
self.setFormat(next_.capturedStart(), next_.capturedLength(), self.styles[style])
digit = QtCore.QRegularExpression(rf'\W(\d+)\W')
match = digit.globalMatch(text)
while match.hasNext():
next_ = match.next()
self.setFormat(next_.capturedStart(1), next_.capturedLength(1), self.styles['numbers'])
comment = QtCore.QRegularExpression(rf'#.*')
match = comment.globalMatch(text)
while match.hasNext():
next_ = match.next()
self.setFormat(next_.capturedStart(), next_.capturedLength(), self.styles['comment'])
line_strings_patterns = r"""(?:".*")|(?:'.*')"""
strings = [x.span(0) for x in re.finditer(line_strings_patterns, text)]
if strings:
for i, j in strings:
self.setFormat(i, j - i, self.styles['string'])
multi_line_strings_double = r"(?:\"\"\")"
self.setCurrentBlockState(1)
multi_line_strings_double = [x.span(0) for x in re.finditer(multi_line_strings_double, text)]
if len(multi_line_strings_double) == 2:
self.setFormat(multi_line_strings_double[0][0],
len(text) - multi_line_strings_double[1][0],
self.styles['string'])
return
if multi_line_strings_double and self.previousBlockState() == 1:
self.setCurrentBlockState(2)
self.setFormat(multi_line_strings_double[0][0],
len(text) - multi_line_strings_double[0][0],
self.styles['string'])
return
elif multi_line_strings_double and self.previousBlockState() == 2:
self.setCurrentBlockState(1)
self.setFormat(0,
multi_line_strings_double[0][1],
self.styles['string'])
elif not multi_line_strings_double and self.previousBlockState() == 2:
self.setCurrentBlockState(2)
self.setFormat(0,
len(text),
self.styles['string'])
return
def syntax_frmt(self, color, style=None):
frmt = QtGui.QTextCharFormat()
frmt.setFontFamily(self.font)
frmt.setForeground(color)
if 'bold' == style:
frmt.setFontWeight(700)
if 'italic' == style:
frmt.setFontItalic(True)
else:
frmt.setFontItalic(False)
frmt.setFontWeight(400)
frmt.setFontPointSize(self.text_size)
return frmt