18 |
18 |
19 class LexerPython(SubstyledLexer, QsciLexerPython): |
19 class LexerPython(SubstyledLexer, QsciLexerPython): |
20 """ |
20 """ |
21 Subclass to implement some additional lexer dependant methods. |
21 Subclass to implement some additional lexer dependant methods. |
22 """ |
22 """ |
|
23 |
23 def __init__(self, variant="", parent=None): |
24 def __init__(self, variant="", parent=None): |
24 """ |
25 """ |
25 Constructor |
26 Constructor |
26 |
27 |
27 @param variant name of the language variant (string) |
28 @param variant name of the language variant (string) |
28 @param parent parent widget of this lexer |
29 @param parent parent widget of this lexer |
29 """ |
30 """ |
30 QsciLexerPython.__init__(self, parent) |
31 QsciLexerPython.__init__(self, parent) |
31 SubstyledLexer.__init__(self) |
32 SubstyledLexer.__init__(self) |
32 |
33 |
33 self.variant = variant |
34 self.variant = variant |
34 self.commentString = "#" |
35 self.commentString = "#" |
35 |
36 |
36 self.keywordSetDescriptions = [ |
37 self.keywordSetDescriptions = [ |
37 self.tr("Keywords"), |
38 self.tr("Keywords"), |
38 self.tr("Highlighted identifiers"), |
39 self.tr("Highlighted identifiers"), |
39 ] |
40 ] |
40 |
41 |
41 ############################################################## |
42 ############################################################## |
42 ## default sub-style definitions |
43 ## default sub-style definitions |
43 ############################################################## |
44 ############################################################## |
44 |
45 |
45 # list of style numbers, that support sub-styling |
46 # list of style numbers, that support sub-styling |
46 self.baseStyles = [11] |
47 self.baseStyles = [11] |
47 |
48 |
48 self.defaultSubStyles = { |
49 self.defaultSubStyles = { |
49 11: { |
50 11: { |
50 0: { |
51 0: { |
51 "Description": self.tr("Standard Library Modules"), |
52 "Description": self.tr("Standard Library Modules"), |
52 "Words": """ |
53 "Words": """ |
100 QtWebEngineWidgets QtWebSockets QtWidgets QtWinExtras QtX11Extras QtXml |
101 QtWebEngineWidgets QtWebSockets QtWidgets QtWinExtras QtX11Extras QtXml |
101 QtXmlPatterns sip""", |
102 QtXmlPatterns sip""", |
102 "Style": { |
103 "Style": { |
103 "fore": 0x44AADD, |
104 "fore": 0x44AADD, |
104 "font_bold": True, |
105 "font_bold": True, |
105 } |
106 }, |
106 }, |
107 }, |
107 3: { |
108 3: { |
108 "Description": self.tr("Cython Specifics"), |
109 "Description": self.tr("Cython Specifics"), |
109 "Words": "cython pyximport Cython __cinit__ __dealloc__", |
110 "Words": "cython pyximport Cython __cinit__ __dealloc__", |
110 "Style": { |
111 "Style": { |
111 "fore": 0xdd0000, |
112 "fore": 0xDD0000, |
112 "font_bold": True, |
113 "font_bold": True, |
113 } |
114 }, |
114 }, |
115 }, |
115 }, |
116 }, |
116 } |
117 } |
117 |
118 |
118 def language(self): |
119 def language(self): |
119 """ |
120 """ |
120 Public method to get the lexer language. |
121 Public method to get the lexer language. |
121 |
122 |
122 @return lexer language (string) |
123 @return lexer language (string) |
123 """ |
124 """ |
124 if not self.variant: |
125 if not self.variant: |
125 return QsciLexerPython.language(self) |
126 return QsciLexerPython.language(self) |
126 else: |
127 else: |
127 return self.variant |
128 return self.variant |
128 |
129 |
129 def initProperties(self): |
130 def initProperties(self): |
130 """ |
131 """ |
131 Public slot to initialize the properties. |
132 Public slot to initialize the properties. |
132 """ |
133 """ |
133 self.setIndentationWarning( |
134 self.setIndentationWarning(Preferences.getEditor("PythonBadIndentation")) |
134 Preferences.getEditor("PythonBadIndentation")) |
|
135 self.setFoldComments(Preferences.getEditor("PythonFoldComment")) |
135 self.setFoldComments(Preferences.getEditor("PythonFoldComment")) |
136 self.setFoldQuotes(Preferences.getEditor("PythonFoldString")) |
136 self.setFoldQuotes(Preferences.getEditor("PythonFoldString")) |
137 if not Preferences.getEditor("PythonAutoIndent"): |
137 if not Preferences.getEditor("PythonAutoIndent"): |
138 self.setAutoIndentStyle(QsciScintilla.AiMaintain) |
138 self.setAutoIndentStyle(QsciScintilla.AiMaintain) |
139 with contextlib.suppress(AttributeError): |
139 with contextlib.suppress(AttributeError): |
140 self.setV2UnicodeAllowed( |
140 self.setV2UnicodeAllowed(Preferences.getEditor("PythonAllowV2Unicode")) |
141 Preferences.getEditor("PythonAllowV2Unicode")) |
141 self.setV3BinaryOctalAllowed(Preferences.getEditor("PythonAllowV3Binary")) |
142 self.setV3BinaryOctalAllowed( |
|
143 Preferences.getEditor("PythonAllowV3Binary")) |
|
144 self.setV3BytesAllowed(Preferences.getEditor("PythonAllowV3Bytes")) |
142 self.setV3BytesAllowed(Preferences.getEditor("PythonAllowV3Bytes")) |
145 with contextlib.suppress(AttributeError): |
143 with contextlib.suppress(AttributeError): |
146 self.setFoldQuotes(Preferences.getEditor("PythonFoldQuotes")) |
144 self.setFoldQuotes(Preferences.getEditor("PythonFoldQuotes")) |
147 self.setStringsOverNewlineAllowed( |
145 self.setStringsOverNewlineAllowed( |
148 Preferences.getEditor("PythonStringsOverNewLineAllowed")) |
146 Preferences.getEditor("PythonStringsOverNewLineAllowed") |
|
147 ) |
149 with contextlib.suppress(AttributeError): |
148 with contextlib.suppress(AttributeError): |
150 self.setHighlightSubidentifiers( |
149 self.setHighlightSubidentifiers( |
151 Preferences.getEditor("PythonHighlightSubidentifier")) |
150 Preferences.getEditor("PythonHighlightSubidentifier") |
152 |
151 ) |
|
152 |
153 def getIndentationDifference(self, line, editor): |
153 def getIndentationDifference(self, line, editor): |
154 """ |
154 """ |
155 Public method to determine the difference for the new indentation. |
155 Public method to determine the difference for the new indentation. |
156 |
156 |
157 @param line line to perform the calculation for (integer) |
157 @param line line to perform the calculation for (integer) |
158 @param editor QScintilla editor |
158 @param editor QScintilla editor |
159 @return amount of difference in indentation (integer) |
159 @return amount of difference in indentation (integer) |
160 """ |
160 """ |
161 indent_width = editor.getEditorConfig('IndentWidth') |
161 indent_width = editor.getEditorConfig("IndentWidth") |
162 |
162 |
163 lead_spaces = editor.indentation(line) |
163 lead_spaces = editor.indentation(line) |
164 |
164 |
165 pline = line - 1 |
165 pline = line - 1 |
166 while pline >= 0 and re.match(r'^\s*(#.*)?$', editor.text(pline)): |
166 while pline >= 0 and re.match(r"^\s*(#.*)?$", editor.text(pline)): |
167 pline -= 1 |
167 pline -= 1 |
168 |
168 |
169 if pline < 0: |
169 if pline < 0: |
170 last = 0 |
170 last = 0 |
171 else: |
171 else: |
172 previous_lead_spaces = editor.indentation(pline) |
172 previous_lead_spaces = editor.indentation(pline) |
173 # trailing spaces |
173 # trailing spaces |
174 m = re.search(r':\s*(#.*)?$', editor.text(pline)) |
174 m = re.search(r":\s*(#.*)?$", editor.text(pline)) |
175 last = previous_lead_spaces |
175 last = previous_lead_spaces |
176 if m: |
176 if m: |
177 last += indent_width |
177 last += indent_width |
178 else: |
178 else: |
179 # special cases, like pass (unindent) or return (also unindent) |
179 # special cases, like pass (unindent) or return (also unindent) |
180 m = re.search(r'(pass\s*(#.*)?$)|(^[^#]return)', |
180 m = re.search(r"(pass\s*(#.*)?$)|(^[^#]return)", editor.text(pline)) |
181 editor.text(pline)) |
|
182 if m: |
181 if m: |
183 last -= indent_width |
182 last -= indent_width |
184 |
183 |
185 indentDifference = ( |
184 indentDifference = ( |
186 last - lead_spaces |
185 last - lead_spaces |
187 if (lead_spaces % indent_width != 0 or |
186 if ( |
188 lead_spaces == 0 or |
187 lead_spaces % indent_width != 0 |
189 self.lastIndented != line) else |
188 or lead_spaces == 0 |
190 -indent_width # __IGNORE_WARNING_W503__ |
189 or self.lastIndented != line |
|
190 ) |
|
191 else -indent_width # __IGNORE_WARNING_W503__ |
191 ) |
192 ) |
192 |
193 |
193 return indentDifference |
194 return indentDifference |
194 |
195 |
195 def autoCompletionWordSeparators(self): |
196 def autoCompletionWordSeparators(self): |
196 """ |
197 """ |
197 Public method to return the list of separators for autocompletion. |
198 Public method to return the list of separators for autocompletion. |
198 |
199 |
199 @return list of separators (list of strings) |
200 @return list of separators (list of strings) |
200 """ |
201 """ |
201 return ['.'] |
202 return ["."] |
202 |
203 |
203 def isCommentStyle(self, style): |
204 def isCommentStyle(self, style): |
204 """ |
205 """ |
205 Public method to check, if a style is a comment style. |
206 Public method to check, if a style is a comment style. |
206 |
207 |
207 @param style style to check (integer) |
208 @param style style to check (integer) |
208 @return flag indicating a comment style (boolean) |
209 @return flag indicating a comment style (boolean) |
209 """ |
210 """ |
210 return style in [QsciLexerPython.Comment, |
211 return style in [QsciLexerPython.Comment, QsciLexerPython.CommentBlock] |
211 QsciLexerPython.CommentBlock] |
212 |
212 |
|
213 def isStringStyle(self, style): |
213 def isStringStyle(self, style): |
214 """ |
214 """ |
215 Public method to check, if a style is a string style. |
215 Public method to check, if a style is a string style. |
216 |
216 |
217 @param style style to check (integer) |
217 @param style style to check (integer) |
218 @return flag indicating a string style (boolean) |
218 @return flag indicating a string style (boolean) |
219 """ |
219 """ |
220 return style in [QsciLexerPython.DoubleQuotedString, |
220 return style in [ |
221 QsciLexerPython.SingleQuotedString, |
221 QsciLexerPython.DoubleQuotedString, |
222 QsciLexerPython.TripleDoubleQuotedString, |
222 QsciLexerPython.SingleQuotedString, |
223 QsciLexerPython.TripleSingleQuotedString, |
223 QsciLexerPython.TripleDoubleQuotedString, |
224 QsciLexerPython.UnclosedString] |
224 QsciLexerPython.TripleSingleQuotedString, |
225 |
225 QsciLexerPython.UnclosedString, |
|
226 ] |
|
227 |
226 def defaultKeywords(self, kwSet): |
228 def defaultKeywords(self, kwSet): |
227 """ |
229 """ |
228 Public method to get the default keywords. |
230 Public method to get the default keywords. |
229 |
231 |
230 @param kwSet number of the keyword set (integer) |
232 @param kwSet number of the keyword set (integer) |
231 @return string giving the keywords (string) or None |
233 @return string giving the keywords (string) or None |
232 """ |
234 """ |
233 if kwSet == 1: |
235 if kwSet == 1: |
234 if self.language() == "Python3": |
236 if self.language() == "Python3": |
235 import keyword |
237 import keyword |
|
238 |
236 keywords = " ".join(keyword.kwlist) |
239 keywords = " ".join(keyword.kwlist) |
237 elif self.language() == "MicroPython": |
240 elif self.language() == "MicroPython": |
238 keywords = ("False None True and as assert break class " |
241 keywords = ( |
239 "continue def del elif else except finally for " |
242 "False None True and as assert break class " |
240 "from global if import in is lambda nonlocal not " |
243 "continue def del elif else except finally for " |
241 "or pass raise return try while with yield") |
244 "from global if import in is lambda nonlocal not " |
|
245 "or pass raise return try while with yield" |
|
246 ) |
242 elif self.language() == "Cython": |
247 elif self.language() == "Cython": |
243 keywords = ("False None True and as assert break class " |
248 keywords = ( |
244 "continue def del elif else except finally for " |
249 "False None True and as assert break class " |
245 "from global if import in is lambda nonlocal not " |
250 "continue def del elif else except finally for " |
246 "or pass raise return try while with yield " |
251 "from global if import in is lambda nonlocal not " |
247 "cdef cimport cpdef ctypedef") |
252 "or pass raise return try while with yield " |
|
253 "cdef cimport cpdef ctypedef" |
|
254 ) |
248 else: |
255 else: |
249 keywords = QsciLexerPython.keywords(self, kwSet) |
256 keywords = QsciLexerPython.keywords(self, kwSet) |
250 else: |
257 else: |
251 keywords = QsciLexerPython.keywords(self, kwSet) |
258 keywords = QsciLexerPython.keywords(self, kwSet) |
252 |
259 |
253 return keywords |
260 return keywords |
254 |
261 |
255 def maximumKeywordSet(self): |
262 def maximumKeywordSet(self): |
256 """ |
263 """ |
257 Public method to get the maximum keyword set. |
264 Public method to get the maximum keyword set. |
258 |
265 |
259 @return maximum keyword set (integer) |
266 @return maximum keyword set (integer) |
260 """ |
267 """ |
261 return 2 |
268 return 2 |