source: node_modules/highlight.js/lib/languages/python.js@ d24f17c

main
Last change on this file since d24f17c was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 8.6 KB
RevLine 
[d24f17c]1/**
2 * @param {string} value
3 * @returns {RegExp}
4 * */
5
6/**
7 * @param {RegExp | string } re
8 * @returns {string}
9 */
10function source(re) {
11 if (!re) return null;
12 if (typeof re === "string") return re;
13
14 return re.source;
15}
16
17/**
18 * @param {RegExp | string } re
19 * @returns {string}
20 */
21function lookahead(re) {
22 return concat('(?=', re, ')');
23}
24
25/**
26 * @param {...(RegExp | string) } args
27 * @returns {string}
28 */
29function concat(...args) {
30 const joined = args.map((x) => source(x)).join("");
31 return joined;
32}
33
34/*
35Language: Python
36Description: Python is an interpreted, object-oriented, high-level programming language with dynamic semantics.
37Website: https://www.python.org
38Category: common
39*/
40
41function python(hljs) {
42 const RESERVED_WORDS = [
43 'and',
44 'as',
45 'assert',
46 'async',
47 'await',
48 'break',
49 'class',
50 'continue',
51 'def',
52 'del',
53 'elif',
54 'else',
55 'except',
56 'finally',
57 'for',
58 'from',
59 'global',
60 'if',
61 'import',
62 'in',
63 'is',
64 'lambda',
65 'nonlocal|10',
66 'not',
67 'or',
68 'pass',
69 'raise',
70 'return',
71 'try',
72 'while',
73 'with',
74 'yield'
75 ];
76
77 const BUILT_INS = [
78 '__import__',
79 'abs',
80 'all',
81 'any',
82 'ascii',
83 'bin',
84 'bool',
85 'breakpoint',
86 'bytearray',
87 'bytes',
88 'callable',
89 'chr',
90 'classmethod',
91 'compile',
92 'complex',
93 'delattr',
94 'dict',
95 'dir',
96 'divmod',
97 'enumerate',
98 'eval',
99 'exec',
100 'filter',
101 'float',
102 'format',
103 'frozenset',
104 'getattr',
105 'globals',
106 'hasattr',
107 'hash',
108 'help',
109 'hex',
110 'id',
111 'input',
112 'int',
113 'isinstance',
114 'issubclass',
115 'iter',
116 'len',
117 'list',
118 'locals',
119 'map',
120 'max',
121 'memoryview',
122 'min',
123 'next',
124 'object',
125 'oct',
126 'open',
127 'ord',
128 'pow',
129 'print',
130 'property',
131 'range',
132 'repr',
133 'reversed',
134 'round',
135 'set',
136 'setattr',
137 'slice',
138 'sorted',
139 'staticmethod',
140 'str',
141 'sum',
142 'super',
143 'tuple',
144 'type',
145 'vars',
146 'zip'
147 ];
148
149 const LITERALS = [
150 '__debug__',
151 'Ellipsis',
152 'False',
153 'None',
154 'NotImplemented',
155 'True'
156 ];
157
158 // https://docs.python.org/3/library/typing.html
159 // TODO: Could these be supplemented by a CamelCase matcher in certain
160 // contexts, leaving these remaining only for relevance hinting?
161 const TYPES = [
162 "Any",
163 "Callable",
164 "Coroutine",
165 "Dict",
166 "List",
167 "Literal",
168 "Generic",
169 "Optional",
170 "Sequence",
171 "Set",
172 "Tuple",
173 "Type",
174 "Union"
175 ];
176
177 const KEYWORDS = {
178 $pattern: /[A-Za-z]\w+|__\w+__/,
179 keyword: RESERVED_WORDS,
180 built_in: BUILT_INS,
181 literal: LITERALS,
182 type: TYPES
183 };
184
185 const PROMPT = {
186 className: 'meta',
187 begin: /^(>>>|\.\.\.) /
188 };
189
190 const SUBST = {
191 className: 'subst',
192 begin: /\{/,
193 end: /\}/,
194 keywords: KEYWORDS,
195 illegal: /#/
196 };
197
198 const LITERAL_BRACKET = {
199 begin: /\{\{/,
200 relevance: 0
201 };
202
203 const STRING = {
204 className: 'string',
205 contains: [ hljs.BACKSLASH_ESCAPE ],
206 variants: [
207 {
208 begin: /([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,
209 end: /'''/,
210 contains: [
211 hljs.BACKSLASH_ESCAPE,
212 PROMPT
213 ],
214 relevance: 10
215 },
216 {
217 begin: /([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,
218 end: /"""/,
219 contains: [
220 hljs.BACKSLASH_ESCAPE,
221 PROMPT
222 ],
223 relevance: 10
224 },
225 {
226 begin: /([fF][rR]|[rR][fF]|[fF])'''/,
227 end: /'''/,
228 contains: [
229 hljs.BACKSLASH_ESCAPE,
230 PROMPT,
231 LITERAL_BRACKET,
232 SUBST
233 ]
234 },
235 {
236 begin: /([fF][rR]|[rR][fF]|[fF])"""/,
237 end: /"""/,
238 contains: [
239 hljs.BACKSLASH_ESCAPE,
240 PROMPT,
241 LITERAL_BRACKET,
242 SUBST
243 ]
244 },
245 {
246 begin: /([uU]|[rR])'/,
247 end: /'/,
248 relevance: 10
249 },
250 {
251 begin: /([uU]|[rR])"/,
252 end: /"/,
253 relevance: 10
254 },
255 {
256 begin: /([bB]|[bB][rR]|[rR][bB])'/,
257 end: /'/
258 },
259 {
260 begin: /([bB]|[bB][rR]|[rR][bB])"/,
261 end: /"/
262 },
263 {
264 begin: /([fF][rR]|[rR][fF]|[fF])'/,
265 end: /'/,
266 contains: [
267 hljs.BACKSLASH_ESCAPE,
268 LITERAL_BRACKET,
269 SUBST
270 ]
271 },
272 {
273 begin: /([fF][rR]|[rR][fF]|[fF])"/,
274 end: /"/,
275 contains: [
276 hljs.BACKSLASH_ESCAPE,
277 LITERAL_BRACKET,
278 SUBST
279 ]
280 },
281 hljs.APOS_STRING_MODE,
282 hljs.QUOTE_STRING_MODE
283 ]
284 };
285
286 // https://docs.python.org/3.9/reference/lexical_analysis.html#numeric-literals
287 const digitpart = '[0-9](_?[0-9])*';
288 const pointfloat = `(\\b(${digitpart}))?\\.(${digitpart})|\\b(${digitpart})\\.`;
289 const NUMBER = {
290 className: 'number',
291 relevance: 0,
292 variants: [
293 // exponentfloat, pointfloat
294 // https://docs.python.org/3.9/reference/lexical_analysis.html#floating-point-literals
295 // optionally imaginary
296 // https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals
297 // Note: no leading \b because floats can start with a decimal point
298 // and we don't want to mishandle e.g. `fn(.5)`,
299 // no trailing \b for pointfloat because it can end with a decimal point
300 // and we don't want to mishandle e.g. `0..hex()`; this should be safe
301 // because both MUST contain a decimal point and so cannot be confused with
302 // the interior part of an identifier
303 {
304 begin: `(\\b(${digitpart})|(${pointfloat}))[eE][+-]?(${digitpart})[jJ]?\\b`
305 },
306 {
307 begin: `(${pointfloat})[jJ]?`
308 },
309
310 // decinteger, bininteger, octinteger, hexinteger
311 // https://docs.python.org/3.9/reference/lexical_analysis.html#integer-literals
312 // optionally "long" in Python 2
313 // https://docs.python.org/2.7/reference/lexical_analysis.html#integer-and-long-integer-literals
314 // decinteger is optionally imaginary
315 // https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals
316 {
317 begin: '\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?\\b'
318 },
319 {
320 begin: '\\b0[bB](_?[01])+[lL]?\\b'
321 },
322 {
323 begin: '\\b0[oO](_?[0-7])+[lL]?\\b'
324 },
325 {
326 begin: '\\b0[xX](_?[0-9a-fA-F])+[lL]?\\b'
327 },
328
329 // imagnumber (digitpart-based)
330 // https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals
331 {
332 begin: `\\b(${digitpart})[jJ]\\b`
333 }
334 ]
335 };
336 const COMMENT_TYPE = {
337 className: "comment",
338 begin: lookahead(/# type:/),
339 end: /$/,
340 keywords: KEYWORDS,
341 contains: [
342 { // prevent keywords from coloring `type`
343 begin: /# type:/
344 },
345 // comment within a datatype comment includes no keywords
346 {
347 begin: /#/,
348 end: /\b\B/,
349 endsWithParent: true
350 }
351 ]
352 };
353 const PARAMS = {
354 className: 'params',
355 variants: [
356 // Exclude params in functions without params
357 {
358 className: "",
359 begin: /\(\s*\)/,
360 skip: true
361 },
362 {
363 begin: /\(/,
364 end: /\)/,
365 excludeBegin: true,
366 excludeEnd: true,
367 keywords: KEYWORDS,
368 contains: [
369 'self',
370 PROMPT,
371 NUMBER,
372 STRING,
373 hljs.HASH_COMMENT_MODE
374 ]
375 }
376 ]
377 };
378 SUBST.contains = [
379 STRING,
380 NUMBER,
381 PROMPT
382 ];
383
384 return {
385 name: 'Python',
386 aliases: [
387 'py',
388 'gyp',
389 'ipython'
390 ],
391 keywords: KEYWORDS,
392 illegal: /(<\/|->|\?)|=>/,
393 contains: [
394 PROMPT,
395 NUMBER,
396 {
397 // very common convention
398 begin: /\bself\b/
399 },
400 {
401 // eat "if" prior to string so that it won't accidentally be
402 // labeled as an f-string
403 beginKeywords: "if",
404 relevance: 0
405 },
406 STRING,
407 COMMENT_TYPE,
408 hljs.HASH_COMMENT_MODE,
409 {
410 variants: [
411 {
412 className: 'function',
413 beginKeywords: 'def'
414 },
415 {
416 className: 'class',
417 beginKeywords: 'class'
418 }
419 ],
420 end: /:/,
421 illegal: /[${=;\n,]/,
422 contains: [
423 hljs.UNDERSCORE_TITLE_MODE,
424 PARAMS,
425 {
426 begin: /->/,
427 endsWithParent: true,
428 keywords: KEYWORDS
429 }
430 ]
431 },
432 {
433 className: 'meta',
434 begin: /^[\t ]*@/,
435 end: /(?=#)|$/,
436 contains: [
437 NUMBER,
438 PARAMS,
439 STRING
440 ]
441 }
442 ]
443 };
444}
445
446module.exports = python;
Note: See TracBrowser for help on using the repository browser.