]> luflow.net public git repositories - flow-web.git/blob - static/highlight/es/languages/elixir.js
Initial commit.
[flow-web.git] / static / highlight / es / languages / elixir.js
1 /*! `elixir` grammar compiled for Highlight.js 11.11.1 */
2 var hljsGrammar = (function () {
3 'use strict';
4
5 /*
6 Language: Elixir
7 Author: Josh Adams <josh@isotope11.com>
8 Description: language definition for Elixir source code files (.ex and .exs). Based on ruby language support.
9 Category: functional
10 Website: https://elixir-lang.org
11 */
12
13 /** @type LanguageFn */
14 function elixir(hljs) {
15 const regex = hljs.regex;
16 const ELIXIR_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_.]*(!|\\?)?';
17 const ELIXIR_METHOD_RE = '[a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?';
18 const KEYWORDS = [
19 "after",
20 "alias",
21 "and",
22 "case",
23 "catch",
24 "cond",
25 "defstruct",
26 "defguard",
27 "do",
28 "else",
29 "end",
30 "fn",
31 "for",
32 "if",
33 "import",
34 "in",
35 "not",
36 "or",
37 "quote",
38 "raise",
39 "receive",
40 "require",
41 "reraise",
42 "rescue",
43 "try",
44 "unless",
45 "unquote",
46 "unquote_splicing",
47 "use",
48 "when",
49 "with|0"
50 ];
51 const LITERALS = [
52 "false",
53 "nil",
54 "true"
55 ];
56 const KWS = {
57 $pattern: ELIXIR_IDENT_RE,
58 keyword: KEYWORDS,
59 literal: LITERALS
60 };
61 const SUBST = {
62 className: 'subst',
63 begin: /#\{/,
64 end: /\}/,
65 keywords: KWS
66 };
67 const NUMBER = {
68 className: 'number',
69 begin: '(\\b0o[0-7_]+)|(\\b0b[01_]+)|(\\b0x[0-9a-fA-F_]+)|(-?\\b[0-9][0-9_]*(\\.[0-9_]+([eE][-+]?[0-9]+)?)?)',
70 relevance: 0
71 };
72 // TODO: could be tightened
73 // https://elixir-lang.readthedocs.io/en/latest/intro/18.html
74 // but you also need to include closing delemeters in the escape list per
75 // individual sigil mode from what I can tell,
76 // ie: \} might or might not be an escape depending on the sigil used
77 const ESCAPES_RE = /\\[\s\S]/;
78 // const ESCAPES_RE = /\\["'\\abdefnrstv0]/;
79 const BACKSLASH_ESCAPE = {
80 match: ESCAPES_RE,
81 scope: "char.escape",
82 relevance: 0
83 };
84 const SIGIL_DELIMITERS = '[/|([{<"\']';
85 const SIGIL_DELIMITER_MODES = [
86 {
87 begin: /"/,
88 end: /"/
89 },
90 {
91 begin: /'/,
92 end: /'/
93 },
94 {
95 begin: /\//,
96 end: /\//
97 },
98 {
99 begin: /\|/,
100 end: /\|/
101 },
102 {
103 begin: /\(/,
104 end: /\)/
105 },
106 {
107 begin: /\[/,
108 end: /\]/
109 },
110 {
111 begin: /\{/,
112 end: /\}/
113 },
114 {
115 begin: /</,
116 end: />/
117 }
118 ];
119 const escapeSigilEnd = (end) => {
120 return {
121 scope: "char.escape",
122 begin: regex.concat(/\\/, end),
123 relevance: 0
124 };
125 };
126 const LOWERCASE_SIGIL = {
127 className: 'string',
128 begin: '~[a-z]' + '(?=' + SIGIL_DELIMITERS + ')',
129 contains: SIGIL_DELIMITER_MODES.map(x => hljs.inherit(x,
130 { contains: [
131 escapeSigilEnd(x.end),
132 BACKSLASH_ESCAPE,
133 SUBST
134 ] }
135 ))
136 };
137
138 const UPCASE_SIGIL = {
139 className: 'string',
140 begin: '~[A-Z]' + '(?=' + SIGIL_DELIMITERS + ')',
141 contains: SIGIL_DELIMITER_MODES.map(x => hljs.inherit(x,
142 { contains: [ escapeSigilEnd(x.end) ] }
143 ))
144 };
145
146 const REGEX_SIGIL = {
147 className: 'regex',
148 variants: [
149 {
150 begin: '~r' + '(?=' + SIGIL_DELIMITERS + ')',
151 contains: SIGIL_DELIMITER_MODES.map(x => hljs.inherit(x,
152 {
153 end: regex.concat(x.end, /[uismxfU]{0,7}/),
154 contains: [
155 escapeSigilEnd(x.end),
156 BACKSLASH_ESCAPE,
157 SUBST
158 ]
159 }
160 ))
161 },
162 {
163 begin: '~R' + '(?=' + SIGIL_DELIMITERS + ')',
164 contains: SIGIL_DELIMITER_MODES.map(x => hljs.inherit(x,
165 {
166 end: regex.concat(x.end, /[uismxfU]{0,7}/),
167 contains: [ escapeSigilEnd(x.end) ]
168 })
169 )
170 }
171 ]
172 };
173
174 const STRING = {
175 className: 'string',
176 contains: [
177 hljs.BACKSLASH_ESCAPE,
178 SUBST
179 ],
180 variants: [
181 {
182 begin: /"""/,
183 end: /"""/
184 },
185 {
186 begin: /'''/,
187 end: /'''/
188 },
189 {
190 begin: /~S"""/,
191 end: /"""/,
192 contains: [] // override default
193 },
194 {
195 begin: /~S"/,
196 end: /"/,
197 contains: [] // override default
198 },
199 {
200 begin: /~S'''/,
201 end: /'''/,
202 contains: [] // override default
203 },
204 {
205 begin: /~S'/,
206 end: /'/,
207 contains: [] // override default
208 },
209 {
210 begin: /'/,
211 end: /'/
212 },
213 {
214 begin: /"/,
215 end: /"/
216 }
217 ]
218 };
219 const FUNCTION = {
220 className: 'function',
221 beginKeywords: 'def defp defmacro defmacrop',
222 end: /\B\b/, // the mode is ended by the title
223 contains: [
224 hljs.inherit(hljs.TITLE_MODE, {
225 begin: ELIXIR_IDENT_RE,
226 endsParent: true
227 })
228 ]
229 };
230 const CLASS = hljs.inherit(FUNCTION, {
231 className: 'class',
232 beginKeywords: 'defimpl defmodule defprotocol defrecord',
233 end: /\bdo\b|$|;/
234 });
235 const ELIXIR_DEFAULT_CONTAINS = [
236 STRING,
237 REGEX_SIGIL,
238 UPCASE_SIGIL,
239 LOWERCASE_SIGIL,
240 hljs.HASH_COMMENT_MODE,
241 CLASS,
242 FUNCTION,
243 { begin: '::' },
244 {
245 className: 'symbol',
246 begin: ':(?![\\s:])',
247 contains: [
248 STRING,
249 { begin: ELIXIR_METHOD_RE }
250 ],
251 relevance: 0
252 },
253 {
254 className: 'symbol',
255 begin: ELIXIR_IDENT_RE + ':(?!:)',
256 relevance: 0
257 },
258 { // Usage of a module, struct, etc.
259 className: 'title.class',
260 begin: /(\b[A-Z][a-zA-Z0-9_]+)/,
261 relevance: 0
262 },
263 NUMBER,
264 {
265 className: 'variable',
266 begin: '(\\$\\W)|((\\$|@@?)(\\w+))'
267 }
268 // -> has been removed, capnproto always uses this grammar construct
269 ];
270 SUBST.contains = ELIXIR_DEFAULT_CONTAINS;
271
272 return {
273 name: 'Elixir',
274 aliases: [
275 'ex',
276 'exs'
277 ],
278 keywords: KWS,
279 contains: ELIXIR_DEFAULT_CONTAINS
280 };
281 }
282
283 return elixir;
284
285 })();
286 ;
287 export default hljsGrammar;