eric6/QScintilla/Lexers/LexerPython.py

changeset 6942
2602857055c5
parent 6881
054667c5c270
child 7229
53054eb5b15a
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2002 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a Python lexer with some additional methods.
8 """
9
10 from __future__ import unicode_literals
11
12 import re
13
14 from PyQt5.Qsci import QsciLexerPython, QsciScintilla
15
16 from .SubstyledLexer import SubstyledLexer
17 import Preferences
18
19
20 class LexerPython(SubstyledLexer, QsciLexerPython):
21 """
22 Subclass to implement some additional lexer dependant methods.
23 """
24 def __init__(self, variant="", parent=None):
25 """
26 Constructor
27
28 @param variant name of the language variant (string)
29 @param parent parent widget of this lexer
30 """
31 QsciLexerPython.__init__(self, parent)
32 SubstyledLexer.__init__(self)
33
34 self.variant = variant
35 self.commentString = "#"
36
37 self.keywordSetDescriptions = [
38 self.tr("Keywords"),
39 self.tr("Highlighted identifiers"),
40 ]
41
42 ##############################################################
43 ## default sub-style definitions
44 ##############################################################
45
46 # list of style numbers, that support sub-styling
47 self.baseStyles = [11]
48
49 self.defaultSubStyles = {
50 11: {
51 0: {
52 "Description": self.tr("Standard Library Modules"),
53 "Words": """
54 __main__ _dummy_thread _thread abc aifc argparse array ast asynchat asyncio
55 asyncore atexit audioop base64 bdb binascii binhex bisect builtins bz2
56 calendar cgi cgitb chunk cmath cmd code codecs codeop collections colorsys
57 compileall concurrent configparser contextlib copy copyreg crypt csv ctypes
58 curses datetime dbm decimal difflib dis distutils dummy_threading email
59 ensurepip enum errno faulthandler fcntl filecmp fileinput fnmatch formatter
60 fpectl fractions ftplib functools gc getopt getpass gettext glob grp gzip
61 hashlib heapq hmac html http http imaplib imghdr importlib inspect io
62 ipaddress itertools json keyword linecache locale logging lzma macpath
63 mailbox mailcap marshal math mimetypes mmap modulefinder msilib msvcrt
64 multiprocessing netrc nis nntplib numbers operator os ossaudiodev parser path
65 pathlib pdb pickle pickletools pipes pkgutil platform plistlib poplib posix
66 pprint pty pwd py_compile pyclbr queue quopri random re readline reprlib
67 resource rlcompleter runpy sched 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 textwrap threading time timeit
71 tkinter token tokenize trace traceback tracemalloc tty turtle types
72 unicodedata unittest urllib uu uuid venv warnings wave weakref webbrowser
73 winreg winsound wsgiref xdrlib xml xmlrpc zipfile zipimport zlib""",
74 "Style": {
75 "fore": 0xDD9900,
76 "font_bold": True,
77 }
78 },
79 1: {
80 "Description": self.tr("__future__ Imports"),
81 "Words": """
82 __future__ with_statement unicode_literals print_function division
83 absolute_import generator_stop annotations""",
84 "Style": {
85 "fore": 0xEE00AA,
86 "font_italic": True,
87 }
88 },
89 2: {
90 "Description": self.tr("PyQt5 Modules"),
91 "Words": """
92 PyQt5 Qsci Qt QtCore QtDBus QtDesigner QtGui QtHelp QtLocation QtMacExtras
93 QtMultimedia QtMultimediaWidgets QtNetwork QtNetworkAuth QtNfc QtOpenGL
94 QtPositioning QtPrintSupport QtQml QtQuick QtQuickWidgets QtRemoteObjects
95 QtSensors QtSerialPort QtSql QtSvg QtTest QtWebChannel QtWebEngine
96 QtWebEngineCore QtWebEngineWidgets QtWebSockets QtWidgets QtWinExtras
97 QtX11Extras QtXml QtXmlPatterns sip QtWebKit QtWebKitWidgets""",
98 "Style": {
99 "fore": 0x44AADD,
100 "font_bold": True,
101 }
102 },
103 3: {
104 "Description": self.tr("Cython Specifics"),
105 "Words": "cython pyximport Cython __cinit__ __dealloc__",
106 "Style": {
107 "fore": 0xdd0000,
108 "font_bold": True,
109 }
110 },
111 },
112 }
113
114 def language(self):
115 """
116 Public method to get the lexer language.
117
118 @return lexer language (string)
119 """
120 if not self.variant:
121 return QsciLexerPython.language(self)
122 else:
123 return self.variant
124
125 def initProperties(self):
126 """
127 Public slot to initialize the properties.
128 """
129 self.setIndentationWarning(
130 Preferences.getEditor("PythonBadIndentation"))
131 self.setFoldComments(Preferences.getEditor("PythonFoldComment"))
132 self.setFoldQuotes(Preferences.getEditor("PythonFoldString"))
133 if not Preferences.getEditor("PythonAutoIndent"):
134 self.setAutoIndentStyle(QsciScintilla.AiMaintain)
135 try:
136 self.setV2UnicodeAllowed(
137 Preferences.getEditor("PythonAllowV2Unicode"))
138 self.setV3BinaryOctalAllowed(
139 Preferences.getEditor("PythonAllowV3Binary"))
140 self.setV3BytesAllowed(Preferences.getEditor("PythonAllowV3Bytes"))
141 except AttributeError:
142 pass
143 try:
144 self.setFoldQuotes(Preferences.getEditor("PythonFoldQuotes"))
145 self.setStringsOverNewlineAllowed(
146 Preferences.getEditor("PythonStringsOverNewLineAllowed"))
147 except AttributeError:
148 pass
149 try:
150 self.setHighlightSubidentifiers(
151 Preferences.getEditor("PythonHighlightSubidentifier"))
152 except AttributeError:
153 pass
154
155 def getIndentationDifference(self, line, editor):
156 """
157 Public method to determine the difference for the new indentation.
158
159 @param line line to perform the calculation for (integer)
160 @param editor QScintilla editor
161 @return amount of difference in indentation (integer)
162 """
163 indent_width = editor.getEditorConfig('IndentWidth')
164
165 lead_spaces = editor.indentation(line)
166
167 pline = line - 1
168 while pline >= 0 and re.match(r'^\s*(#.*)?$', editor.text(pline)):
169 pline -= 1
170
171 if pline < 0:
172 last = 0
173 else:
174 previous_lead_spaces = editor.indentation(pline)
175 # trailing spaces
176 m = re.search(r':\s*(#.*)?$', editor.text(pline))
177 last = previous_lead_spaces
178 if m:
179 last += indent_width
180 else:
181 # special cases, like pass (unindent) or return (also unindent)
182 m = re.search(r'(pass\s*(#.*)?$)|(^[^#]return)',
183 editor.text(pline))
184 if m:
185 last -= indent_width
186
187 if lead_spaces % indent_width != 0 or lead_spaces == 0 \
188 or self.lastIndented != line:
189 indentDifference = last - lead_spaces
190 else:
191 indentDifference = -indent_width
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() in ["Python", "Python2"]:
235 keywords = ("and as assert break class continue def del elif "
236 "else except exec finally for from global if "
237 "import in is lambda not or pass print raise "
238 "return try while with yield")
239 elif self.language() == "Python3":
240 keywords = ("False None True and as assert break class "
241 "continue def del elif else except finally for "
242 "from global if import in is lambda nonlocal not "
243 "or pass raise return try while with yield")
244 elif self.language() == "Cython":
245 keywords = ("False None True and as assert break class "
246 "continue def del elif else except finally for "
247 "from global if import in is lambda nonlocal not "
248 "or pass raise return try while with yield "
249 "cdef cimport cpdef ctypedef")
250 else:
251 keywords = QsciLexerPython.keywords(self, kwSet)
252 else:
253 keywords = QsciLexerPython.keywords(self, kwSet)
254
255 return keywords
256
257 def maximumKeywordSet(self):
258 """
259 Public method to get the maximum keyword set.
260
261 @return maximum keyword set (integer)
262 """
263 return 2

eric ide

mercurial