|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2008 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a custom lexer using pygments. |
|
8 """ |
|
9 |
|
10 import contextlib |
|
11 |
|
12 from pygments.token import Token |
|
13 from pygments.lexers import ( |
|
14 guess_lexer_for_filename, guess_lexer, find_lexer_class |
|
15 ) |
|
16 from pygments.util import ClassNotFound |
|
17 |
|
18 from PyQt6.QtGui import QColor, QFont |
|
19 |
|
20 from QScintilla.Lexers.LexerContainer import LexerContainer |
|
21 |
|
22 import Utilities |
|
23 |
|
24 PYGMENTS_DEFAULT = 0 |
|
25 PYGMENTS_COMMENT = 1 |
|
26 PYGMENTS_PREPROCESSOR = 2 |
|
27 PYGMENTS_KEYWORD = 3 |
|
28 PYGMENTS_PSEUDOKEYWORD = 4 |
|
29 PYGMENTS_TYPEKEYWORD = 5 |
|
30 PYGMENTS_OPERATOR = 6 |
|
31 PYGMENTS_WORD = 7 |
|
32 PYGMENTS_BUILTIN = 8 |
|
33 PYGMENTS_FUNCTION = 9 |
|
34 PYGMENTS_CLASS = 10 |
|
35 PYGMENTS_NAMESPACE = 11 |
|
36 PYGMENTS_EXCEPTION = 12 |
|
37 PYGMENTS_VARIABLE = 13 |
|
38 PYGMENTS_CONSTANT = 14 |
|
39 PYGMENTS_LABEL = 15 |
|
40 PYGMENTS_ENTITY = 16 |
|
41 PYGMENTS_ATTRIBUTE = 17 |
|
42 PYGMENTS_TAG = 18 |
|
43 PYGMENTS_DECORATOR = 19 |
|
44 PYGMENTS_STRING = 20 |
|
45 PYGMENTS_DOCSTRING = 21 |
|
46 PYGMENTS_SCALAR = 22 |
|
47 PYGMENTS_ESCAPE = 23 |
|
48 PYGMENTS_REGEX = 24 |
|
49 PYGMENTS_SYMBOL = 25 |
|
50 PYGMENTS_OTHER = 26 |
|
51 PYGMENTS_NUMBER = 27 |
|
52 PYGMENTS_HEADING = 28 |
|
53 PYGMENTS_SUBHEADING = 29 |
|
54 PYGMENTS_DELETED = 30 |
|
55 PYGMENTS_INSERTED = 31 |
|
56 # 32 to 39 are reserved for QScintilla internal styles |
|
57 PYGMENTS_GENERIC_ERROR = 40 |
|
58 PYGMENTS_EMPHASIZE = 41 |
|
59 PYGMENTS_STRONG = 42 |
|
60 PYGMENTS_PROMPT = 43 |
|
61 PYGMENTS_OUTPUT = 44 |
|
62 PYGMENTS_TRACEBACK = 45 |
|
63 PYGMENTS_ERROR = 46 |
|
64 PYGMENTS_MULTILINECOMMENT = 47 |
|
65 PYGMENTS_PROPERTY = 48 |
|
66 PYGMENTS_CHAR = 49 |
|
67 PYGMENTS_HEREDOC = 50 |
|
68 PYGMENTS_PUNCTUATION = 51 |
|
69 # added with Pygments 2.1 |
|
70 PYGMENTS_HASHBANG = 52 |
|
71 PYGMENTS_RESERVEDKEYWORD = 53 |
|
72 PYGMENTS_LITERAL = 54 |
|
73 PYGMENTS_DOUBLESTRING = 55 |
|
74 PYGMENTS_SINGLESTRING = 56 |
|
75 PYGMENTS_BACKTICKSTRING = 57 |
|
76 PYGMENTS_WHITESPACE = 58 |
|
77 |
|
78 #-----------------------------------------------------------------------------# |
|
79 |
|
80 TOKEN_MAP = { |
|
81 Token.Comment: PYGMENTS_COMMENT, |
|
82 Token.Comment.Hashbang: PYGMENTS_HASHBANG, |
|
83 Token.Comment.Multiline: PYGMENTS_MULTILINECOMMENT, |
|
84 Token.Comment.Preproc: PYGMENTS_PREPROCESSOR, |
|
85 Token.Comment.PreprocFile: PYGMENTS_PREPROCESSOR, |
|
86 Token.Comment.Single: PYGMENTS_COMMENT, |
|
87 Token.Comment.Special: PYGMENTS_COMMENT, |
|
88 |
|
89 Token.Escape: PYGMENTS_ESCAPE, |
|
90 |
|
91 Token.Error: PYGMENTS_ERROR, |
|
92 |
|
93 Token.Generic: PYGMENTS_DEFAULT, |
|
94 Token.Generic.Deleted: PYGMENTS_DELETED, |
|
95 Token.Generic.Emph: PYGMENTS_EMPHASIZE, |
|
96 Token.Generic.Error: PYGMENTS_GENERIC_ERROR, |
|
97 Token.Generic.Heading: PYGMENTS_HEADING, |
|
98 Token.Generic.Inserted: PYGMENTS_INSERTED, |
|
99 Token.Generic.Output: PYGMENTS_OUTPUT, |
|
100 Token.Generic.Prompt: PYGMENTS_PROMPT, |
|
101 Token.Generic.Strong: PYGMENTS_STRONG, |
|
102 Token.Generic.Subheading: PYGMENTS_SUBHEADING, |
|
103 Token.Generic.Traceback: PYGMENTS_TRACEBACK, |
|
104 |
|
105 Token.Keyword: PYGMENTS_KEYWORD, |
|
106 Token.Keyword.Constant: PYGMENTS_KEYWORD, |
|
107 Token.Keyword.Declaration: PYGMENTS_KEYWORD, |
|
108 Token.Keyword.Namespace: PYGMENTS_KEYWORD, |
|
109 Token.Keyword.Pseudo: PYGMENTS_PSEUDOKEYWORD, |
|
110 Token.Keyword.Reserved: PYGMENTS_RESERVEDKEYWORD, |
|
111 Token.Keyword.Type: PYGMENTS_TYPEKEYWORD, |
|
112 |
|
113 Token.Literal: PYGMENTS_LITERAL, |
|
114 Token.Literal.Date: PYGMENTS_LITERAL, |
|
115 |
|
116 Token.Name: PYGMENTS_DEFAULT, |
|
117 Token.Name.Attribute: PYGMENTS_ATTRIBUTE, |
|
118 Token.Name.Builtin: PYGMENTS_BUILTIN, |
|
119 Token.Name.Builtin.Pseudo: PYGMENTS_BUILTIN, |
|
120 Token.Name.Class: PYGMENTS_CLASS, |
|
121 Token.Name.Constant: PYGMENTS_CONSTANT, |
|
122 Token.Name.Decorator: PYGMENTS_DECORATOR, |
|
123 Token.Name.Entity: PYGMENTS_ENTITY, |
|
124 Token.Name.Exception: PYGMENTS_EXCEPTION, |
|
125 Token.Name.Function: PYGMENTS_FUNCTION, |
|
126 Token.Name.Function.Magic: PYGMENTS_FUNCTION, |
|
127 Token.Name.Label: PYGMENTS_LABEL, |
|
128 Token.Name.Namespace: PYGMENTS_NAMESPACE, |
|
129 Token.Name.Other: PYGMENTS_VARIABLE, |
|
130 Token.Name.Property: PYGMENTS_PROPERTY, |
|
131 Token.Name.Tag: PYGMENTS_TAG, |
|
132 Token.Name.Variable: PYGMENTS_VARIABLE, |
|
133 Token.Name.Variable.Class: PYGMENTS_VARIABLE, |
|
134 Token.Name.Variable.Global: PYGMENTS_VARIABLE, |
|
135 Token.Name.Variable.Instance: PYGMENTS_VARIABLE, |
|
136 Token.Name.Variable.Magic: PYGMENTS_VARIABLE, |
|
137 |
|
138 Token.Number: PYGMENTS_NUMBER, |
|
139 Token.Number.Bin: PYGMENTS_NUMBER, |
|
140 Token.Number.Float: PYGMENTS_NUMBER, |
|
141 Token.Number.Hex: PYGMENTS_NUMBER, |
|
142 Token.Number.Integer: PYGMENTS_NUMBER, |
|
143 Token.Number.Integer.Long: PYGMENTS_NUMBER, |
|
144 Token.Number.Oct: PYGMENTS_NUMBER, |
|
145 |
|
146 Token.Operator: PYGMENTS_OPERATOR, |
|
147 Token.Operator.Word: PYGMENTS_WORD, |
|
148 |
|
149 Token.Other: PYGMENTS_DEFAULT, |
|
150 |
|
151 Token.Punctuation: PYGMENTS_PUNCTUATION, |
|
152 |
|
153 Token.String: PYGMENTS_STRING, |
|
154 Token.String.Affix: PYGMENTS_STRING, |
|
155 Token.String.Backtick: PYGMENTS_BACKTICKSTRING, |
|
156 Token.String.Char: PYGMENTS_CHAR, |
|
157 Token.String.Delimiter: PYGMENTS_STRING, |
|
158 Token.String.Doc: PYGMENTS_DOCSTRING, |
|
159 Token.String.Double: PYGMENTS_DOUBLESTRING, |
|
160 Token.String.Escape: PYGMENTS_ESCAPE, |
|
161 Token.String.Heredoc: PYGMENTS_HEREDOC, |
|
162 Token.String.Interpol: PYGMENTS_SCALAR, |
|
163 Token.String.Other: PYGMENTS_OTHER, |
|
164 Token.String.Regex: PYGMENTS_REGEX, |
|
165 Token.String.Single: PYGMENTS_SINGLESTRING, |
|
166 Token.String.Symbol: PYGMENTS_SYMBOL, |
|
167 |
|
168 Token.Whitespace: PYGMENTS_WHITESPACE, |
|
169 |
|
170 Token.Text: PYGMENTS_DEFAULT, |
|
171 } |
|
172 |
|
173 #-----------------------------------------------------------------------------# |
|
174 |
|
175 |
|
176 class LexerPygments(LexerContainer): |
|
177 """ |
|
178 Class implementing a custom lexer using pygments. |
|
179 """ |
|
180 def __init__(self, parent=None, name=""): |
|
181 """ |
|
182 Constructor |
|
183 |
|
184 @param parent parent widget of this lexer |
|
185 @param name name of the pygments lexer to use (string) |
|
186 """ |
|
187 super().__init__(parent) |
|
188 |
|
189 self.__inReadSettings = False |
|
190 |
|
191 if name.startswith("Pygments|"): |
|
192 self.__forcedPygmentsName = True |
|
193 self.__pygmentsName = name.replace("Pygments|", "") |
|
194 elif name: |
|
195 self.__pygmentsName = name |
|
196 self.__forcedPygmentsName = True |
|
197 else: |
|
198 self.__pygmentsName = "" |
|
199 self.__forcedPygmentsName = False |
|
200 |
|
201 self.descriptions = { |
|
202 PYGMENTS_DEFAULT: self.tr("Default"), |
|
203 PYGMENTS_COMMENT: self.tr("Comment"), |
|
204 PYGMENTS_PREPROCESSOR: self.tr("Preprocessor"), |
|
205 PYGMENTS_KEYWORD: self.tr("Keyword"), |
|
206 PYGMENTS_PSEUDOKEYWORD: self.tr("Pseudo Keyword"), |
|
207 PYGMENTS_TYPEKEYWORD: self.tr("Type Keyword"), |
|
208 PYGMENTS_OPERATOR: self.tr("Operator"), |
|
209 PYGMENTS_WORD: self.tr("Word"), |
|
210 PYGMENTS_BUILTIN: self.tr("Builtin"), |
|
211 PYGMENTS_FUNCTION: self.tr("Function or method name"), |
|
212 PYGMENTS_CLASS: self.tr("Class name"), |
|
213 PYGMENTS_NAMESPACE: self.tr("Namespace"), |
|
214 PYGMENTS_EXCEPTION: self.tr("Exception"), |
|
215 PYGMENTS_VARIABLE: self.tr("Identifier"), |
|
216 PYGMENTS_CONSTANT: self.tr("Constant"), |
|
217 PYGMENTS_LABEL: self.tr("Label"), |
|
218 PYGMENTS_ENTITY: self.tr("Entity"), |
|
219 PYGMENTS_ATTRIBUTE: self.tr("Attribute"), |
|
220 PYGMENTS_TAG: self.tr("Tag"), |
|
221 PYGMENTS_DECORATOR: self.tr("Decorator"), |
|
222 PYGMENTS_STRING: self.tr("String"), |
|
223 PYGMENTS_DOCSTRING: self.tr("Documentation string"), |
|
224 PYGMENTS_SCALAR: self.tr("Scalar"), |
|
225 PYGMENTS_ESCAPE: self.tr("Escape"), |
|
226 PYGMENTS_REGEX: self.tr("Regular expression"), |
|
227 PYGMENTS_SYMBOL: self.tr("Symbol"), |
|
228 PYGMENTS_OTHER: self.tr("Other string"), |
|
229 PYGMENTS_NUMBER: self.tr("Number"), |
|
230 PYGMENTS_HEADING: self.tr("Heading"), |
|
231 PYGMENTS_SUBHEADING: self.tr("Subheading"), |
|
232 PYGMENTS_DELETED: self.tr("Deleted"), |
|
233 PYGMENTS_INSERTED: self.tr("Inserted"), |
|
234 PYGMENTS_GENERIC_ERROR: self.tr("Generic error"), |
|
235 PYGMENTS_EMPHASIZE: self.tr("Emphasized text"), |
|
236 PYGMENTS_STRONG: self.tr("Strong text"), |
|
237 PYGMENTS_PROMPT: self.tr("Prompt"), |
|
238 PYGMENTS_OUTPUT: self.tr("Output"), |
|
239 PYGMENTS_TRACEBACK: self.tr("Traceback"), |
|
240 PYGMENTS_ERROR: self.tr("Error"), |
|
241 PYGMENTS_MULTILINECOMMENT: self.tr("Comment block"), |
|
242 PYGMENTS_PROPERTY: self.tr("Property"), |
|
243 PYGMENTS_CHAR: self.tr("Character"), |
|
244 PYGMENTS_HEREDOC: self.tr("Here document"), |
|
245 PYGMENTS_PUNCTUATION: self.tr("Punctuation"), |
|
246 PYGMENTS_HASHBANG: self.tr("Hashbang"), |
|
247 PYGMENTS_RESERVEDKEYWORD: self.tr("Reserved Keyword"), |
|
248 PYGMENTS_LITERAL: self.tr("Literal"), |
|
249 PYGMENTS_DOUBLESTRING: self.tr("Double quoted string"), |
|
250 PYGMENTS_SINGLESTRING: self.tr("Single quoted string"), |
|
251 PYGMENTS_BACKTICKSTRING: self.tr("Backtick string"), |
|
252 PYGMENTS_WHITESPACE: self.tr("Whitespace"), |
|
253 } |
|
254 |
|
255 self.defaultColors = { |
|
256 PYGMENTS_DEFAULT: QColor("#000000"), |
|
257 PYGMENTS_COMMENT: QColor("#408080"), |
|
258 PYGMENTS_PREPROCESSOR: QColor("#BC7A00"), |
|
259 PYGMENTS_KEYWORD: QColor("#008000"), |
|
260 PYGMENTS_PSEUDOKEYWORD: QColor("#008000"), |
|
261 PYGMENTS_TYPEKEYWORD: QColor("#B00040"), |
|
262 PYGMENTS_OPERATOR: QColor("#666666"), |
|
263 PYGMENTS_WORD: QColor("#AA22FF"), |
|
264 PYGMENTS_BUILTIN: QColor("#008000"), |
|
265 PYGMENTS_FUNCTION: QColor("#0000FF"), |
|
266 PYGMENTS_CLASS: QColor("#0000FF"), |
|
267 PYGMENTS_NAMESPACE: QColor("#0000FF"), |
|
268 PYGMENTS_EXCEPTION: QColor("#D2413A"), |
|
269 PYGMENTS_VARIABLE: QColor("#19177C"), |
|
270 PYGMENTS_CONSTANT: QColor("#880000"), |
|
271 PYGMENTS_LABEL: QColor("#A0A000"), |
|
272 PYGMENTS_ENTITY: QColor("#999999"), |
|
273 PYGMENTS_ATTRIBUTE: QColor("#7D9029"), |
|
274 PYGMENTS_TAG: QColor("#008000"), |
|
275 PYGMENTS_DECORATOR: QColor("#AA22FF"), |
|
276 PYGMENTS_STRING: QColor("#BA2121"), |
|
277 PYGMENTS_DOCSTRING: QColor("#BA2121"), |
|
278 PYGMENTS_SCALAR: QColor("#BB6688"), |
|
279 PYGMENTS_ESCAPE: QColor("#BB6622"), |
|
280 PYGMENTS_REGEX: QColor("#BB6688"), |
|
281 PYGMENTS_SYMBOL: QColor("#19177C"), |
|
282 PYGMENTS_OTHER: QColor("#008000"), |
|
283 PYGMENTS_NUMBER: QColor("#666666"), |
|
284 PYGMENTS_HEADING: QColor("#000080"), |
|
285 PYGMENTS_SUBHEADING: QColor("#800080"), |
|
286 PYGMENTS_DELETED: QColor("#A00000"), |
|
287 PYGMENTS_INSERTED: QColor("#00A000"), |
|
288 PYGMENTS_GENERIC_ERROR: QColor("#FF0000"), |
|
289 PYGMENTS_PROMPT: QColor("#000080"), |
|
290 PYGMENTS_OUTPUT: QColor("#808080"), |
|
291 PYGMENTS_TRACEBACK: QColor("#0040D0"), |
|
292 PYGMENTS_MULTILINECOMMENT: QColor("#007F00"), |
|
293 PYGMENTS_PROPERTY: QColor("#00A0E0"), |
|
294 PYGMENTS_CHAR: QColor("#7F007F"), |
|
295 PYGMENTS_HEREDOC: QColor("#7F007F"), |
|
296 PYGMENTS_PUNCTUATION: QColor("#000000"), |
|
297 PYGMENTS_HASHBANG: QColor("#00C000"), |
|
298 PYGMENTS_RESERVEDKEYWORD: QColor("#A90D91"), |
|
299 PYGMENTS_LITERAL: QColor("#1C01CE"), |
|
300 PYGMENTS_DOUBLESTRING: QColor("#7F007F"), |
|
301 PYGMENTS_SINGLESTRING: QColor("#7F007F"), |
|
302 PYGMENTS_BACKTICKSTRING: QColor("#FFFF00"), |
|
303 PYGMENTS_WHITESPACE: QColor("#BBBBBB"), |
|
304 } |
|
305 |
|
306 self.defaultPapers = { |
|
307 PYGMENTS_ERROR: QColor("#FF0000"), |
|
308 PYGMENTS_MULTILINECOMMENT: QColor("#A8FFA8"), |
|
309 PYGMENTS_HEREDOC: QColor("#DDD0DD"), |
|
310 PYGMENTS_BACKTICKSTRING: QColor("#a08080"), |
|
311 } |
|
312 |
|
313 self.defaultEolFills = { |
|
314 PYGMENTS_ERROR: True, |
|
315 PYGMENTS_MULTILINECOMMENT: True, |
|
316 PYGMENTS_HEREDOC: True, |
|
317 PYGMENTS_BACKTICKSTRING: True, |
|
318 } |
|
319 |
|
320 def readSettings(self, qs, prefix="/Scintilla"): |
|
321 """ |
|
322 Public method to read the lexer settings. |
|
323 |
|
324 Note: Overridden to treat the Pygments lexer specially. |
|
325 |
|
326 @param qs reference to the settings object |
|
327 @type QSettings |
|
328 @param prefix prefix for the settings key (defaults to "/Scintilla") |
|
329 @type str (optional) |
|
330 """ |
|
331 self.__inReadSettings = True |
|
332 super().readSettings(qs, prefix=prefix) |
|
333 self.__inReadSettings = False |
|
334 |
|
335 def language(self): |
|
336 """ |
|
337 Public method returning the language of the lexer. |
|
338 |
|
339 @return language of the lexer (string) |
|
340 """ |
|
341 if self.__pygmentsName and not self.__inReadSettings: |
|
342 return self.__pygmentsName |
|
343 else: |
|
344 return "Guessed" |
|
345 |
|
346 def description(self, style): |
|
347 """ |
|
348 Public method returning the descriptions of the styles supported |
|
349 by the lexer. |
|
350 |
|
351 @param style style number (integer) |
|
352 @return description for the style (string) |
|
353 """ |
|
354 try: |
|
355 return self.descriptions[style] |
|
356 except KeyError: |
|
357 return "" |
|
358 |
|
359 def defaultColor(self, style): |
|
360 """ |
|
361 Public method to get the default foreground color for a style. |
|
362 |
|
363 @param style style number (integer) |
|
364 @return foreground color (QColor) |
|
365 """ |
|
366 try: |
|
367 return self.defaultColors[style] |
|
368 except KeyError: |
|
369 return LexerContainer.defaultColor(self, style) |
|
370 |
|
371 def defaultPaper(self, style): |
|
372 """ |
|
373 Public method to get the default background color for a style. |
|
374 |
|
375 @param style style number (integer) |
|
376 @return background color (QColor) |
|
377 """ |
|
378 try: |
|
379 return self.defaultPapers[style] |
|
380 except KeyError: |
|
381 return LexerContainer.defaultPaper(self, style) |
|
382 |
|
383 def defaultFont(self, style): |
|
384 """ |
|
385 Public method to get the default font for a style. |
|
386 |
|
387 @param style style number (integer) |
|
388 @return font (QFont) |
|
389 """ |
|
390 if style in [PYGMENTS_COMMENT, PYGMENTS_PREPROCESSOR, |
|
391 PYGMENTS_MULTILINECOMMENT]: |
|
392 if Utilities.isWindowsPlatform(): |
|
393 f = QFont(["Comic Sans MS"], 9) |
|
394 elif Utilities.isMacPlatform(): |
|
395 f = QFont(["Courier"], 11) |
|
396 else: |
|
397 f = QFont(["Bitstream Vera Serif"], 9) |
|
398 if style == PYGMENTS_PREPROCESSOR: |
|
399 f.setItalic(True) |
|
400 return f |
|
401 |
|
402 if style in [PYGMENTS_STRING, PYGMENTS_CHAR]: |
|
403 if Utilities.isWindowsPlatform(): |
|
404 return QFont(["Comic Sans MS"], 10) |
|
405 elif Utilities.isMacPlatform(): |
|
406 f = QFont(["Courier"], 11) |
|
407 else: |
|
408 return QFont(["Bitstream Vera Serif"], 10) |
|
409 |
|
410 if style in [PYGMENTS_KEYWORD, PYGMENTS_OPERATOR, PYGMENTS_WORD, |
|
411 PYGMENTS_BUILTIN, PYGMENTS_ATTRIBUTE, PYGMENTS_FUNCTION, |
|
412 PYGMENTS_CLASS, PYGMENTS_NAMESPACE, PYGMENTS_EXCEPTION, |
|
413 PYGMENTS_ENTITY, PYGMENTS_TAG, PYGMENTS_SCALAR, |
|
414 PYGMENTS_ESCAPE, PYGMENTS_HEADING, PYGMENTS_SUBHEADING, |
|
415 PYGMENTS_STRONG, PYGMENTS_PROMPT]: |
|
416 f = LexerContainer.defaultFont(self, style) |
|
417 f.setBold(True) |
|
418 return f |
|
419 |
|
420 if style in [PYGMENTS_DOCSTRING, PYGMENTS_EMPHASIZE]: |
|
421 f = LexerContainer.defaultFont(self, style) |
|
422 f.setItalic(True) |
|
423 return f |
|
424 |
|
425 return LexerContainer.defaultFont(self, style) |
|
426 |
|
427 def defaultEolFill(self, style): |
|
428 """ |
|
429 Public method to get the default fill to eol flag. |
|
430 |
|
431 @param style style number (integer) |
|
432 @return fill to eol flag (boolean) |
|
433 """ |
|
434 try: |
|
435 return self.defaultEolFills[style] |
|
436 except KeyError: |
|
437 return LexerContainer.defaultEolFill(self, style) |
|
438 |
|
439 def __guessLexer(self, text): |
|
440 """ |
|
441 Private method to guess a pygments lexer. |
|
442 |
|
443 @param text text to base guessing on (string) |
|
444 @return reference to the guessed lexer (pygments.lexer) |
|
445 """ |
|
446 lexer = None |
|
447 |
|
448 if self.__pygmentsName: |
|
449 lexerClass = find_lexer_class(self.__pygmentsName) |
|
450 if lexerClass is not None: |
|
451 lexer = lexerClass() |
|
452 |
|
453 elif text: |
|
454 # step 1: guess based on filename and text |
|
455 if self.editor is not None: |
|
456 fn = self.editor.getFileName() |
|
457 if fn: |
|
458 with contextlib.suppress(ClassNotFound, AttributeError): |
|
459 lexer = guess_lexer_for_filename(fn, text) |
|
460 |
|
461 # step 2: guess on text only |
|
462 if lexer is None: |
|
463 with contextlib.suppress(ClassNotFound, AttributeError): |
|
464 lexer = guess_lexer(text) |
|
465 |
|
466 return lexer |
|
467 |
|
468 def canStyle(self): |
|
469 """ |
|
470 Public method to check, if the lexer is able to style the text. |
|
471 |
|
472 @return flag indicating the lexer capability (boolean) |
|
473 """ |
|
474 if self.editor is None: |
|
475 return True |
|
476 |
|
477 text = self.editor.text() |
|
478 self.__lexer = self.__guessLexer(text) |
|
479 |
|
480 return self.__lexer is not None |
|
481 |
|
482 def name(self): |
|
483 """ |
|
484 Public method to get the name of the pygments lexer. |
|
485 |
|
486 @return name of the pygments lexer (string) |
|
487 """ |
|
488 if self.__lexer is None: |
|
489 return "" |
|
490 else: |
|
491 return self.__lexer.name |
|
492 |
|
493 def styleText(self, start, end): |
|
494 """ |
|
495 Public method to perform the styling. |
|
496 |
|
497 @param start position of first character to be styled (integer) |
|
498 @param end position of last character to be styled (integer) |
|
499 """ |
|
500 text = self.editor.text()[:end + 1] |
|
501 textLen = len(text.encode("utf-8")) |
|
502 self.__lexer = self.__guessLexer(text) |
|
503 |
|
504 cpos = 0 |
|
505 # adjust start position because pygments ignores empty line at |
|
506 # start of text |
|
507 for c in text: |
|
508 if c == "\n": |
|
509 cpos += 1 |
|
510 else: |
|
511 break |
|
512 |
|
513 self.editor.startStyling(cpos, 0x3f) |
|
514 if self.__lexer is None: |
|
515 self.editor.setStyling(len(text), PYGMENTS_DEFAULT) |
|
516 else: |
|
517 eolLen = len(self.editor.getLineSeparator()) |
|
518 for token, txt in self.__lexer.get_tokens(text): |
|
519 style = TOKEN_MAP.get(token, PYGMENTS_DEFAULT) |
|
520 |
|
521 tlen = len(txt.encode('utf-8')) |
|
522 if eolLen > 1: |
|
523 tlen += txt.count('\n') |
|
524 cpos += tlen |
|
525 if tlen and cpos < textLen: |
|
526 self.editor.setStyling(tlen, style) |
|
527 if cpos >= textLen: |
|
528 break |
|
529 self.editor.startStyling(cpos, 0x3f) |
|
530 |
|
531 def isCommentStyle(self, style): |
|
532 """ |
|
533 Public method to check, if a style is a comment style. |
|
534 |
|
535 @param style style to check (integer) |
|
536 @return flag indicating a comment style (boolean) |
|
537 """ |
|
538 return style in [PYGMENTS_COMMENT] |
|
539 |
|
540 def isStringStyle(self, style): |
|
541 """ |
|
542 Public method to check, if a style is a string style. |
|
543 |
|
544 @param style style to check (integer) |
|
545 @return flag indicating a string style (boolean) |
|
546 """ |
|
547 return style in [PYGMENTS_STRING, PYGMENTS_DOCSTRING, PYGMENTS_OTHER, |
|
548 PYGMENTS_HEADING, PYGMENTS_SUBHEADING, |
|
549 PYGMENTS_EMPHASIZE, PYGMENTS_STRONG] |
|
550 |
|
551 def defaultKeywords(self, kwSet): |
|
552 """ |
|
553 Public method to get the default keywords. |
|
554 |
|
555 @param kwSet number of the keyword set (integer) |
|
556 @return string giving the keywords (string) or None |
|
557 """ |
|
558 return None # __IGNORE_WARNING_M831__ |