123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /*
- 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;
|