UNPKG

4.93 kBJavaScriptView Raw
1(function (Prism) {
2 /**
3 * Functions to construct regular expressions
4 * e.g. (interactive ... or (interactive)
5 *
6 * @param {string} name
7 * @returns {RegExp}
8 */
9 function simple_form(name) {
10 return RegExp(/(\()/.source + '(?:' + name + ')' + /(?=[\s\)])/.source);
11 }
12 /**
13 * booleans and numbers
14 *
15 * @param {string} pattern
16 * @returns {RegExp}
17 */
18 function primitive(pattern) {
19 return RegExp(/([\s([])/.source + '(?:' + pattern + ')' + /(?=[\s)])/.source);
20 }
21
22 // Patterns in regular expressions
23
24 // Symbol name. See https://www.gnu.org/software/emacs/manual/html_node/elisp/Symbol-Type.html
25 // & and : are excluded as they are usually used for special purposes
26 var symbol = /(?!\d)[-+*/~!@$%^=<>{}\w]+/.source;
27 // symbol starting with & used in function arguments
28 var marker = '&' + symbol;
29 // Open parenthesis for look-behind
30 var par = '(\\()';
31 var endpar = '(?=\\))';
32 // End the pattern with look-ahead space
33 var space = '(?=\\s)';
34 var nestedPar = /(?:[^()]|\((?:[^()]|\((?:[^()]|\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\))*\))*\))*/.source;
35
36 var language = {
37 // Three or four semicolons are considered a heading.
38 // See https://www.gnu.org/software/emacs/manual/html_node/elisp/Comment-Tips.html
39 heading: {
40 pattern: /;;;.*/,
41 alias: ['comment', 'title']
42 },
43 comment: /;.*/,
44 string: {
45 pattern: /"(?:[^"\\]|\\.)*"/,
46 greedy: true,
47 inside: {
48 argument: /[-A-Z]+(?=[.,\s])/,
49 symbol: RegExp('`' + symbol + "'")
50 }
51 },
52 'quoted-symbol': {
53 pattern: RegExp("#?'" + symbol),
54 alias: ['variable', 'symbol']
55 },
56 'lisp-property': {
57 pattern: RegExp(':' + symbol),
58 alias: 'property'
59 },
60 splice: {
61 pattern: RegExp(',@?' + symbol),
62 alias: ['symbol', 'variable']
63 },
64 keyword: [
65 {
66 pattern: RegExp(
67 par +
68 '(?:and|(?:cl-)?letf|cl-loop|cond|cons|error|if|(?:lexical-)?let\\*?|message|not|null|or|provide|require|setq|unless|use-package|when|while)' +
69 space
70 ),
71 lookbehind: true
72 },
73 {
74 pattern: RegExp(
75 par + '(?:append|by|collect|concat|do|finally|for|in|return)' + space
76 ),
77 lookbehind: true
78 },
79 ],
80 declare: {
81 pattern: simple_form(/declare/.source),
82 lookbehind: true,
83 alias: 'keyword'
84 },
85 interactive: {
86 pattern: simple_form(/interactive/.source),
87 lookbehind: true,
88 alias: 'keyword'
89 },
90 boolean: {
91 pattern: primitive(/nil|t/.source),
92 lookbehind: true
93 },
94 number: {
95 pattern: primitive(/[-+]?\d+(?:\.\d*)?/.source),
96 lookbehind: true
97 },
98 defvar: {
99 pattern: RegExp(par + 'def(?:const|custom|group|var)\\s+' + symbol),
100 lookbehind: true,
101 inside: {
102 keyword: /^def[a-z]+/,
103 variable: RegExp(symbol)
104 }
105 },
106 defun: {
107 pattern: RegExp(par + /(?:cl-)?(?:defmacro|defun\*?)\s+/.source + symbol + /\s+\(/.source + nestedPar + /\)/.source),
108 lookbehind: true,
109 greedy: true,
110 inside: {
111 keyword: /^(?:cl-)?def\S+/,
112 // See below, this property needs to be defined later so that it can
113 // reference the language object.
114 arguments: null,
115 function: {
116 pattern: RegExp('(^\\s)' + symbol),
117 lookbehind: true
118 },
119 punctuation: /[()]/
120 }
121 },
122 lambda: {
123 pattern: RegExp(par + 'lambda\\s+\\(\\s*(?:&?' + symbol + '(?:\\s+&?' + symbol + ')*\\s*)?\\)'),
124 lookbehind: true,
125 greedy: true,
126 inside: {
127 keyword: /^lambda/,
128 // See below, this property needs to be defined later so that it can
129 // reference the language object.
130 arguments: null,
131 punctuation: /[()]/
132 }
133 },
134 car: {
135 pattern: RegExp(par + symbol),
136 lookbehind: true
137 },
138 punctuation: [
139 // open paren, brackets, and close paren
140 /(?:['`,]?\(|[)\[\]])/,
141 // cons
142 {
143 pattern: /(\s)\.(?=\s)/,
144 lookbehind: true
145 },
146 ]
147 };
148
149 var arg = {
150 'lisp-marker': RegExp(marker),
151 'varform': {
152 pattern: RegExp(/\(/.source + symbol + /\s+(?=\S)/.source + nestedPar + /\)/.source),
153 inside: language
154 },
155 'argument': {
156 pattern: RegExp(/(^|[\s(])/.source + symbol),
157 lookbehind: true,
158 alias: 'variable'
159 },
160 rest: language
161 };
162
163 var forms = '\\S+(?:\\s+\\S+)*';
164
165 var arglist = {
166 pattern: RegExp(par + nestedPar + endpar),
167 lookbehind: true,
168 inside: {
169 'rest-vars': {
170 pattern: RegExp('&(?:body|rest)\\s+' + forms),
171 inside: arg
172 },
173 'other-marker-vars': {
174 pattern: RegExp('&(?:aux|optional)\\s+' + forms),
175 inside: arg
176 },
177 keys: {
178 pattern: RegExp('&key\\s+' + forms + '(?:\\s+&allow-other-keys)?'),
179 inside: arg
180 },
181 argument: {
182 pattern: RegExp(symbol),
183 alias: 'variable'
184 },
185 punctuation: /[()]/
186 }
187 };
188
189 language['lambda'].inside.arguments = arglist;
190 language['defun'].inside.arguments = Prism.util.clone(arglist);
191 language['defun'].inside.arguments.inside.sublist = arglist;
192
193 Prism.languages.lisp = language;
194 Prism.languages.elisp = language;
195 Prism.languages.emacs = language;
196 Prism.languages['emacs-lisp'] = language;
197}(Prism));