You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
259 lines
5.3 KiB
259 lines
5.3 KiB
/* |
|
Language: Elixir |
|
Author: Josh Adams <josh@isotope11.com> |
|
Description: language definition for Elixir source code files (.ex and .exs). Based on ruby language support. |
|
Category: functional |
|
Website: https://elixir-lang.org |
|
*/ |
|
|
|
/** @type LanguageFn */ |
|
function elixir(hljs) { |
|
const ELIXIR_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_.]*(!|\\?)?'; |
|
const ELIXIR_METHOD_RE = '[a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?'; |
|
const ELIXIR_KEYWORDS = { |
|
$pattern: ELIXIR_IDENT_RE, |
|
keyword: 'and false then defined module in return redo retry end for true self when ' + |
|
'next until do begin unless nil break not case cond alias while ensure or ' + |
|
'include use alias fn quote require import with|0' |
|
}; |
|
const SUBST = { |
|
className: 'subst', |
|
begin: /#\{/, |
|
end: /\}/, |
|
keywords: ELIXIR_KEYWORDS |
|
}; |
|
const NUMBER = { |
|
className: 'number', |
|
begin: '(\\b0o[0-7_]+)|(\\b0b[01_]+)|(\\b0x[0-9a-fA-F_]+)|(-?\\b[1-9][0-9_]*(\\.[0-9_]+([eE][-+]?[0-9]+)?)?)', |
|
relevance: 0 |
|
}; |
|
const SIGIL_DELIMITERS = '[/|([{<"\']'; |
|
const LOWERCASE_SIGIL = { |
|
className: 'string', |
|
begin: '~[a-z]' + '(?=' + SIGIL_DELIMITERS + ')', |
|
contains: [ |
|
{ |
|
endsParent: true, |
|
contains: [ |
|
{ |
|
contains: [ |
|
hljs.BACKSLASH_ESCAPE, |
|
SUBST |
|
], |
|
variants: [ |
|
{ |
|
begin: /"/, |
|
end: /"/ |
|
}, |
|
{ |
|
begin: /'/, |
|
end: /'/ |
|
}, |
|
{ |
|
begin: /\//, |
|
end: /\// |
|
}, |
|
{ |
|
begin: /\|/, |
|
end: /\|/ |
|
}, |
|
{ |
|
begin: /\(/, |
|
end: /\)/ |
|
}, |
|
{ |
|
begin: /\[/, |
|
end: /\]/ |
|
}, |
|
{ |
|
begin: /\{/, |
|
end: /\}/ |
|
}, |
|
{ |
|
begin: /</, |
|
end: />/ |
|
} |
|
] |
|
} |
|
] |
|
} |
|
] |
|
}; |
|
|
|
const UPCASE_SIGIL = { |
|
className: 'string', |
|
begin: '~[A-Z]' + '(?=' + SIGIL_DELIMITERS + ')', |
|
contains: [ |
|
{ |
|
begin: /"/, |
|
end: /"/ |
|
}, |
|
{ |
|
begin: /'/, |
|
end: /'/ |
|
}, |
|
{ |
|
begin: /\//, |
|
end: /\// |
|
}, |
|
{ |
|
begin: /\|/, |
|
end: /\|/ |
|
}, |
|
{ |
|
begin: /\(/, |
|
end: /\)/ |
|
}, |
|
{ |
|
begin: /\[/, |
|
end: /\]/ |
|
}, |
|
{ |
|
begin: /\{/, |
|
end: /\}/ |
|
}, |
|
{ |
|
begin: /</, |
|
end: />/ |
|
} |
|
] |
|
}; |
|
|
|
const STRING = { |
|
className: 'string', |
|
contains: [ |
|
hljs.BACKSLASH_ESCAPE, |
|
SUBST |
|
], |
|
variants: [ |
|
{ |
|
begin: /"""/, |
|
end: /"""/ |
|
}, |
|
{ |
|
begin: /'''/, |
|
end: /'''/ |
|
}, |
|
{ |
|
begin: /~S"""/, |
|
end: /"""/, |
|
contains: [] // override default |
|
}, |
|
{ |
|
begin: /~S"/, |
|
end: /"/, |
|
contains: [] // override default |
|
}, |
|
{ |
|
begin: /~S'''/, |
|
end: /'''/, |
|
contains: [] // override default |
|
}, |
|
{ |
|
begin: /~S'/, |
|
end: /'/, |
|
contains: [] // override default |
|
}, |
|
{ |
|
begin: /'/, |
|
end: /'/ |
|
}, |
|
{ |
|
begin: /"/, |
|
end: /"/ |
|
} |
|
] |
|
}; |
|
const FUNCTION = { |
|
className: 'function', |
|
beginKeywords: 'def defp defmacro', |
|
end: /\B\b/, // the mode is ended by the title |
|
contains: [ |
|
hljs.inherit(hljs.TITLE_MODE, { |
|
begin: ELIXIR_IDENT_RE, |
|
endsParent: true |
|
}) |
|
] |
|
}; |
|
const CLASS = hljs.inherit(FUNCTION, { |
|
className: 'class', |
|
beginKeywords: 'defimpl defmodule defprotocol defrecord', |
|
end: /\bdo\b|$|;/ |
|
}); |
|
const ELIXIR_DEFAULT_CONTAINS = [ |
|
STRING, |
|
UPCASE_SIGIL, |
|
LOWERCASE_SIGIL, |
|
hljs.HASH_COMMENT_MODE, |
|
CLASS, |
|
FUNCTION, |
|
{ |
|
begin: '::' |
|
}, |
|
{ |
|
className: 'symbol', |
|
begin: ':(?![\\s:])', |
|
contains: [ |
|
STRING, |
|
{ |
|
begin: ELIXIR_METHOD_RE |
|
} |
|
], |
|
relevance: 0 |
|
}, |
|
{ |
|
className: 'symbol', |
|
begin: ELIXIR_IDENT_RE + ':(?!:)', |
|
relevance: 0 |
|
}, |
|
NUMBER, |
|
{ |
|
className: 'variable', |
|
begin: '(\\$\\W)|((\\$|@@?)(\\w+))' |
|
}, |
|
{ |
|
begin: '->' |
|
}, |
|
{ // regexp container |
|
begin: '(' + hljs.RE_STARTERS_RE + ')\\s*', |
|
contains: [ |
|
hljs.HASH_COMMENT_MODE, |
|
{ |
|
// to prevent false regex triggers for the division function: |
|
// /: |
|
begin: /\/: (?=\d+\s*[,\]])/, |
|
relevance: 0, |
|
contains: [NUMBER] |
|
}, |
|
{ |
|
className: 'regexp', |
|
illegal: '\\n', |
|
contains: [ |
|
hljs.BACKSLASH_ESCAPE, |
|
SUBST |
|
], |
|
variants: [ |
|
{ |
|
begin: '/', |
|
end: '/[a-z]*' |
|
}, |
|
{ |
|
begin: '%r\\[', |
|
end: '\\][a-z]*' |
|
} |
|
] |
|
} |
|
], |
|
relevance: 0 |
|
} |
|
]; |
|
SUBST.contains = ELIXIR_DEFAULT_CONTAINS; |
|
|
|
return { |
|
name: 'Elixir', |
|
keywords: ELIXIR_KEYWORDS, |
|
contains: ELIXIR_DEFAULT_CONTAINS |
|
}; |
|
} |
|
|
|
module.exports = elixir;
|
|
|