eric7/QScintilla/Lexers/LexerPython.py

branch
eric7
changeset 8312
800c432b34c8
parent 8260
2161475d9639
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2002 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a Python lexer with some additional methods.
8 """
9
10 import re
11 import contextlib
12
13 from PyQt5.Qsci import QsciLexerPython, QsciScintilla
14
15 from .SubstyledLexer import SubstyledLexer
16 import Preferences
17
18
19 class LexerPython(SubstyledLexer, QsciLexerPython):
20 """
21 Subclass to implement some additional lexer dependant methods.
22 """
23 def __init__(self, variant="", parent=None):
24 """
25 Constructor
26
27 @param variant name of the language variant (string)
28 @param parent parent widget of this lexer
29 """
30 QsciLexerPython.__init__(self, parent)
31 SubstyledLexer.__init__(self)
32
33 self.variant = variant
34 self.commentString = "#"
35
36 self.keywordSetDescriptions = [
37 self.tr("Keywords"),
38 self.tr("Highlighted identifiers"),
39 ]
40
41 ##############################################################
42 ## default sub-style definitions
43 ##############################################################
44
45 # list of style numbers, that support sub-styling
46 self.baseStyles = [11]
47
48 self.defaultSubStyles = {
49 11: {
50 0: {
51 "Description": self.tr("Standard Library Modules"),
52 "Words": """
53 __main__ _dummy_thread _thread abc aifc argparse array ascii ast asynchat
54 asyncio asyncore atexit audioop base64 bdb binascii binhex bisect builtins bz2
55 calendar cgi cgitb chunk cmath cmd code codecs codeop collections colorsys
56 compileall concurrent configparser contextlib contextvars copy copyreg
57 cProfile crypt csv ctypes curses dataclasses datetime dbm decimal difflib dis
58 distutils doctest email encodings ensurepip enum errno faulthandler fcntl
59 filecmp fileinput fnmatch formatter fractions ftplib functools gc getopt
60 getpass gettext glob graphlib grp gzip hashlib heapq hmac html http imaplib
61 imghdr imp importlib inspect io ipaddress itertools json keyword lib2to3
62 linecache locale logging lzma mailbox mailcap marshal math mimetypes mmap
63 modulefinder msilib msvcrt multiprocessing netrc nis nntplib numbers opcode
64 operator optparse os ossaudiodev parser path pathlib pdb pickle pickletools
65 pipes pkgutil platform plistlib poplib posix pprint profile pstats pty pwd
66 py_compile pyclbr pydoc queue quopri random re readline reprlib resource
67 rlcompleter runpy sched secrets select selectors shelve shlex shutil signal
68 site smtpd smtplib sndhdr socket socketserver spwd sqlite3 ssl stat statistics
69 string stringprep struct subprocess sunau symbol symtable sys sysconfig syslog
70 tabnanny tarfile telnetlib tempfile termios test textwrap threading time
71 timeit tkinter token tokenize trace traceback tracemalloc tty turtle
72 turtledemo types typing unicodedata unittest urllib uu uuid venv warnings wave
73 weakref webbrowser winreg winsound wsgiref xdrlib xml xmlrpc zipapp zipfile
74 zipimport zlib zoneinfo""",
75 "Style": {
76 "fore": 0xDD9900,
77 "font_bold": True,
78 }
79 },
80 1: {
81 "Description": self.tr("__future__ Imports"),
82 "Words": """
83 __future__ absolute_import annotations division generators generator_stop
84 nested_scopes print_function unicode_literals with_statement""",
85 "Style": {
86 "fore": 0xEE00AA,
87 "font_italic": True,
88 }
89 },
90 2: {
91 "Description": self.tr("PyQt5/6 Modules"),
92 "Words": """
93 PyQt5 PyQt6 Qsci Qt Qt3DAnimation Qt3DCore Qt3DExtras Qt3DInput Qt3DLogic
94 Qt3DRender QtBluetooth QtChart QtCore QtDataVisualization QtDBus QtDesigner
95 QtGui QtHelp QtLocation QtMacExtras QtMultimedia QtMultimediaWidgets QtNetwork
96 QtNetworkAuth QtNfc QtOpenGL QtOpenGLWidgets QtPositioning QtPrintSupport
97 QtPurchasing QtQml QtQuick QtQuick3D QtQuickWidgets QtRemoteObjects QtSensors
98 QtSerialPort QtSql QtSvg QtSvgWidgets QtTest QtTextToSpeech QtWebChannel
99 QtWebEngine QtWebEngineCore QtWebEngineWidgets QtWebSockets QtWidgets
100 QtWinExtras QtX11Extras QtXml QtXmlPatterns sip""",
101 "Style": {
102 "fore": 0x44AADD,
103 "font_bold": True,
104 }
105 },
106 3: {
107 "Description": self.tr("Cython Specifics"),
108 "Words": "cython pyximport Cython __cinit__ __dealloc__",
109 "Style": {
110 "fore": 0xdd0000,
111 "font_bold": True,
112 }
113 },
114 },
115 }
116
117 def language(self):
118 """
119 Public method to get the lexer language.
120
121 @return lexer language (string)
122 """
123 if not self.variant:
124 return QsciLexerPython.language(self)
125 else:
126 return self.variant
127
128 def initProperties(self):
129 """
130 Public slot to initialize the properties.
131 """
132 self.setIndentationWarning(
133 Preferences.getEditor("PythonBadIndentation"))
134 self.setFoldComments(Preferences.getEditor("PythonFoldComment"))
135 self.setFoldQuotes(Preferences.getEditor("PythonFoldString"))
136 if not Preferences.getEditor("PythonAutoIndent"):
137 self.setAutoIndentStyle(QsciScintilla.AiMaintain)
138 with contextlib.suppress(AttributeError):
139 self.setV2UnicodeAllowed(
140 Preferences.getEditor("PythonAllowV2Unicode"))
141 self.setV3BinaryOctalAllowed(
142 Preferences.getEditor("PythonAllowV3Binary"))
143 self.setV3BytesAllowed(Preferences.getEditor("PythonAllowV3Bytes"))
144 with contextlib.suppress(AttributeError):
145 self.setFoldQuotes(Preferences.getEditor("PythonFoldQuotes"))
146 self.setStringsOverNewlineAllowed(
147 Preferences.getEditor("PythonStringsOverNewLineAllowed"))
148 with contextlib.suppress(AttributeError):
149 self.setHighlightSubidentifiers(
150 Preferences.getEditor("PythonHighlightSubidentifier"))
151
152 def getIndentationDifference(self, line, editor):
153 """
154 Public method to determine the difference for the new indentation.
155
156 @param line line to perform the calculation for (integer)
157 @param editor QScintilla editor
158 @return amount of difference in indentation (integer)
159 """
160 indent_width = editor.getEditorConfig('IndentWidth')
161
162 lead_spaces = editor.indentation(line)
163
164 pline = line - 1
165 while pline >= 0 and re.match(r'^\s*(#.*)?$', editor.text(pline)):
166 pline -= 1
167
168 if pline < 0:
169 last = 0
170 else:
171 previous_lead_spaces = editor.indentation(pline)
172 # trailing spaces
173 m = re.search(r':\s*(#.*)?$', editor.text(pline))
174 last = previous_lead_spaces
175 if m:
176 last += indent_width
177 else:
178 # special cases, like pass (unindent) or return (also unindent)
179 m = re.search(r'(pass\s*(#.*)?$)|(^[^#]return)',
180 editor.text(pline))
181 if m:
182 last -= indent_width
183
184 indentDifference = (
185 last - lead_spaces
186 if (lead_spaces % indent_width != 0 or
187 lead_spaces == 0 or
188 self.lastIndented != line) else
189 -indent_width # __IGNORE_WARNING_W503__
190 )
191
192 return indentDifference
193
194 def autoCompletionWordSeparators(self):
195 """
196 Public method to return the list of separators for autocompletion.
197
198 @return list of separators (list of strings)
199 """
200 return ['.']
201
202 def isCommentStyle(self, style):
203 """
204 Public method to check, if a style is a comment style.
205
206 @param style style to check (integer)
207 @return flag indicating a comment style (boolean)
208 """
209 return style in [QsciLexerPython.Comment,
210 QsciLexerPython.CommentBlock]
211
212 def isStringStyle(self, style):
213 """
214 Public method to check, if a style is a string style.
215
216 @param style style to check (integer)
217 @return flag indicating a string style (boolean)
218 """
219 return style in [QsciLexerPython.DoubleQuotedString,
220 QsciLexerPython.SingleQuotedString,
221 QsciLexerPython.TripleDoubleQuotedString,
222 QsciLexerPython.TripleSingleQuotedString,
223 QsciLexerPython.UnclosedString]
224
225 def defaultKeywords(self, kwSet):
226 """
227 Public method to get the default keywords.
228
229 @param kwSet number of the keyword set (integer)
230 @return string giving the keywords (string) or None
231 """
232 if kwSet == 1:
233 if self.language() == "Python3":
234 import keyword
235 keywords = " ".join(keyword.kwlist)
236 elif self.language() == "MicroPython":
237 keywords = ("False None True and as assert break class "
238 "continue def del elif else except finally for "
239 "from global if import in is lambda nonlocal not "
240 "or pass raise return try while with yield")
241 elif self.language() == "Cython":
242 keywords = ("False None True and as assert break class "
243 "continue def del elif else except finally for "
244 "from global if import in is lambda nonlocal not "
245 "or pass raise return try while with yield "
246 "cdef cimport cpdef ctypedef")
247 else:
248 keywords = QsciLexerPython.keywords(self, kwSet)
249 else:
250 keywords = QsciLexerPython.keywords(self, kwSet)
251
252 return keywords
253
254 def maximumKeywordSet(self):
255 """
256 Public method to get the maximum keyword set.
257
258 @return maximum keyword set (integer)
259 """
260 return 2

eric ide

mercurial