src/eric7/QScintilla/Lexers/LexerPython.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2002 - 2022 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 PyQt6.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 QtCharts QtCore QtDataVisualization QtDBus
95 QtDesigner QtGui QtHelp QtLocation QtMacExtras QtMultimedia
96 QtMultimediaWidgets QtNetwork QtNetworkAuth QtNfc QtOpenGL QtOpenGLWidgets
97 QtPositioning QtPrintSupport QtPurchasing QtQml QtQuick QtQuick3D
98 QtQuickWidgets QtRemoteObjects QtSensors QtSerialPort QtSql QtSvg QtSvgWidgets
99 QtTest QtTextToSpeech QtWebChannel QtWebEngine QtWebEngineCore
100 QtWebEngineWidgets QtWebSockets QtWidgets QtWinExtras QtX11Extras QtXml
101 QtXmlPatterns sip""",
102 "Style": {
103 "fore": 0x44AADD,
104 "font_bold": True,
105 }
106 },
107 3: {
108 "Description": self.tr("Cython Specifics"),
109 "Words": "cython pyximport Cython __cinit__ __dealloc__",
110 "Style": {
111 "fore": 0xdd0000,
112 "font_bold": True,
113 }
114 },
115 },
116 }
117
118 def language(self):
119 """
120 Public method to get the lexer language.
121
122 @return lexer language (string)
123 """
124 if not self.variant:
125 return QsciLexerPython.language(self)
126 else:
127 return self.variant
128
129 def initProperties(self):
130 """
131 Public slot to initialize the properties.
132 """
133 self.setIndentationWarning(
134 Preferences.getEditor("PythonBadIndentation"))
135 self.setFoldComments(Preferences.getEditor("PythonFoldComment"))
136 self.setFoldQuotes(Preferences.getEditor("PythonFoldString"))
137 if not Preferences.getEditor("PythonAutoIndent"):
138 self.setAutoIndentStyle(QsciScintilla.AiMaintain)
139 with contextlib.suppress(AttributeError):
140 self.setV2UnicodeAllowed(
141 Preferences.getEditor("PythonAllowV2Unicode"))
142 self.setV3BinaryOctalAllowed(
143 Preferences.getEditor("PythonAllowV3Binary"))
144 self.setV3BytesAllowed(Preferences.getEditor("PythonAllowV3Bytes"))
145 with contextlib.suppress(AttributeError):
146 self.setFoldQuotes(Preferences.getEditor("PythonFoldQuotes"))
147 self.setStringsOverNewlineAllowed(
148 Preferences.getEditor("PythonStringsOverNewLineAllowed"))
149 with contextlib.suppress(AttributeError):
150 self.setHighlightSubidentifiers(
151 Preferences.getEditor("PythonHighlightSubidentifier"))
152
153 def getIndentationDifference(self, line, editor):
154 """
155 Public method to determine the difference for the new indentation.
156
157 @param line line to perform the calculation for (integer)
158 @param editor QScintilla editor
159 @return amount of difference in indentation (integer)
160 """
161 indent_width = editor.getEditorConfig('IndentWidth')
162
163 lead_spaces = editor.indentation(line)
164
165 pline = line - 1
166 while pline >= 0 and re.match(r'^\s*(#.*)?$', editor.text(pline)):
167 pline -= 1
168
169 if pline < 0:
170 last = 0
171 else:
172 previous_lead_spaces = editor.indentation(pline)
173 # trailing spaces
174 m = re.search(r':\s*(#.*)?$', editor.text(pline))
175 last = previous_lead_spaces
176 if m:
177 last += indent_width
178 else:
179 # special cases, like pass (unindent) or return (also unindent)
180 m = re.search(r'(pass\s*(#.*)?$)|(^[^#]return)',
181 editor.text(pline))
182 if m:
183 last -= indent_width
184
185 indentDifference = (
186 last - lead_spaces
187 if (lead_spaces % indent_width != 0 or
188 lead_spaces == 0 or
189 self.lastIndented != line) else
190 -indent_width # __IGNORE_WARNING_W503__
191 )
192
193 return indentDifference
194
195 def autoCompletionWordSeparators(self):
196 """
197 Public method to return the list of separators for autocompletion.
198
199 @return list of separators (list of strings)
200 """
201 return ['.']
202
203 def isCommentStyle(self, style):
204 """
205 Public method to check, if a style is a comment style.
206
207 @param style style to check (integer)
208 @return flag indicating a comment style (boolean)
209 """
210 return style in [QsciLexerPython.Comment,
211 QsciLexerPython.CommentBlock]
212
213 def isStringStyle(self, style):
214 """
215 Public method to check, if a style is a string style.
216
217 @param style style to check (integer)
218 @return flag indicating a string style (boolean)
219 """
220 return style in [QsciLexerPython.DoubleQuotedString,
221 QsciLexerPython.SingleQuotedString,
222 QsciLexerPython.TripleDoubleQuotedString,
223 QsciLexerPython.TripleSingleQuotedString,
224 QsciLexerPython.UnclosedString]
225
226 def defaultKeywords(self, kwSet):
227 """
228 Public method to get the default keywords.
229
230 @param kwSet number of the keyword set (integer)
231 @return string giving the keywords (string) or None
232 """
233 if kwSet == 1:
234 if self.language() == "Python3":
235 import keyword
236 keywords = " ".join(keyword.kwlist)
237 elif self.language() == "MicroPython":
238 keywords = ("False None True and as assert break class "
239 "continue def del elif else except finally for "
240 "from global if import in is lambda nonlocal not "
241 "or pass raise return try while with yield")
242 elif self.language() == "Cython":
243 keywords = ("False None True and as assert break class "
244 "continue def del elif else except finally for "
245 "from global if import in is lambda nonlocal not "
246 "or pass raise return try while with yield "
247 "cdef cimport cpdef ctypedef")
248 else:
249 keywords = QsciLexerPython.keywords(self, kwSet)
250 else:
251 keywords = QsciLexerPython.keywords(self, kwSet)
252
253 return keywords
254
255 def maximumKeywordSet(self):
256 """
257 Public method to get the maximum keyword set.
258
259 @return maximum keyword set (integer)
260 """
261 return 2

eric ide

mercurial