1
2
3 import sys
4
5 from PyQt4.QtCore import QRegExp
6 from PyQt4.QtGui import QColor, QTextCharFormat, QFont, QSyntaxHighlighter
7
22
23
24
25 STYLES = {
26 'keyword': format('blue'),
27 'operator': format('red'),
28 'brace': format('darkGray'),
29 'defclass': format('black', 'bold'),
30 'string': format('magenta'),
31 'string2': format('darkMagenta'),
32 'comment': format('darkGreen', 'italic'),
33 'self': format('black', 'italic'),
34 'numbers': format('brown'),
35 }
36
37
39 """Syntax highlighter for the Python language.
40 """
41
42 keywords = [
43 'and', 'assert', 'break', 'class', 'continue', 'def',
44 'del', 'elif', 'else', 'except', 'exec', 'finally',
45 'for', 'from', 'global', 'if', 'import', 'in',
46 'is', 'lambda', 'not', 'or', 'pass', 'print',
47 'raise', 'return', 'try', 'while', 'yield',
48 'None', 'True', 'False',
49 ]
50
51
52 operators = [
53 '=',
54
55 '==', '!=', '<', '<=', '>', '>=',
56
57 '\+', '-', '\*', '/', '//', '\%', '\*\*',
58
59 '\+=', '-=', '\*=', '/=', '\%=',
60
61 '\^', '\|', '\&', '\~', '>>', '<<',
62 ]
63
64
65 braces = [
66 '\{', '\}', '\(', '\)', '\[', '\]',
67 ]
69 QSyntaxHighlighter.__init__(self, document)
70
71
72
73
74 self.tri_single = (QRegExp("'''"), 1, STYLES['string2'])
75 self.tri_double = (QRegExp('"""'), 2, STYLES['string2'])
76
77 rules = []
78
79
80 rules += [(r'\b%s\b' % w, 0, STYLES['keyword'])
81 for w in PythonHighlighter.keywords]
82 rules += [(r'%s' % o, 0, STYLES['operator'])
83 for o in PythonHighlighter.operators]
84 rules += [(r'%s' % b, 0, STYLES['brace'])
85 for b in PythonHighlighter.braces]
86
87
88 rules += [
89
90 (r'\bself\b', 0, STYLES['self']),
91
92
93 (r'"[^"\\]*(\\.[^"\\]*)*"', 0, STYLES['string']),
94
95 (r"'[^'\\]*(\\.[^'\\]*)*'", 0, STYLES['string']),
96
97
98 (r'\bdef\b\s*(\w+)', 1, STYLES['defclass']),
99
100 (r'\bclass\b\s*(\w+)', 1, STYLES['defclass']),
101
102
103 (r'#[^\n]*', 0, STYLES['comment']),
104
105
106 (r'\b[+-]?[0-9]+[lL]?\b', 0, STYLES['numbers']),
107 (r'\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b', 0, STYLES['numbers']),
108 (r'\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b', 0, STYLES['numbers']),
109 ]
110
111
112 self.rules = [(QRegExp(pat), index, fmt)
113 for (pat, index, fmt) in rules]
114
115
117 """Apply syntax highlighting to the given block of text.
118 """
119
120 for expression, nth, format in self.rules:
121 index = expression.indexIn(text, 0)
122
123 while index >= 0:
124
125 index = expression.pos(nth)
126 length = expression.cap(nth).length()
127 self.setFormat(index, length, format)
128 index = expression.indexIn(text, index + length)
129
130 self.setCurrentBlockState(0)
131
132
133 in_multiline = self.match_multiline(text, *self.tri_single)
134 if not in_multiline:
135 in_multiline = self.match_multiline(text, *self.tri_double)
136
137
139 """Do highlighting of multi-line strings. ``delimiter`` should be a
140 ``QRegExp`` for triple-single-quotes or triple-double-quotes, and
141 ``in_state`` should be a unique integer to represent the corresponding
142 state changes when inside those strings. Returns True if we're still
143 inside a multi-line string when this function is finished.
144 """
145
146 if self.previousBlockState() == in_state:
147 start = 0
148 add = 0
149
150 else:
151 start = delimiter.indexIn(text)
152
153 add = delimiter.matchedLength()
154
155
156 while start >= 0:
157
158 end = delimiter.indexIn(text, start + add)
159
160 if end >= add:
161 length = end - start + add + delimiter.matchedLength()
162 self.setCurrentBlockState(0)
163
164 else:
165 self.setCurrentBlockState(in_state)
166 length = text.length() - start + add
167
168 self.setFormat(start, length, style)
169
170 start = delimiter.indexIn(text, start + length)
171
172
173 if self.currentBlockState() == in_state:
174 return True
175 else:
176 return False
177