elixir.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. Language: Elixir
  3. Author: Josh Adams <josh@isotope11.com>
  4. Description: language definition for Elixir source code files (.ex and .exs). Based on ruby language support.
  5. Category: functional
  6. Website: https://elixir-lang.org
  7. */
  8. function elixir(hljs) {
  9. var ELIXIR_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_.]*(\\!|\\?)?';
  10. var ELIXIR_METHOD_RE = '[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?';
  11. var ELIXIR_KEYWORDS = {
  12. $pattern: ELIXIR_IDENT_RE,
  13. keyword: 'and false then defined module in return redo retry end for true self when ' +
  14. 'next until do begin unless nil break not case cond alias while ensure or ' +
  15. 'include use alias fn quote require import with|0'
  16. };
  17. var SUBST = {
  18. className: 'subst',
  19. begin: '#\\{', end: '}',
  20. keywords: ELIXIR_KEYWORDS
  21. };
  22. var NUMBER = {
  23. className: 'number',
  24. begin: '(\\b0o[0-7_]+)|(\\b0b[01_]+)|(\\b0x[0-9a-fA-F_]+)|(-?\\b[1-9][0-9_]*(.[0-9_]+([eE][-+]?[0-9]+)?)?)',
  25. relevance: 0
  26. };
  27. var SIGIL_DELIMITERS = '[/|([{<"\']';
  28. var LOWERCASE_SIGIL = {
  29. className: 'string',
  30. begin: '~[a-z]' + '(?=' + SIGIL_DELIMITERS + ')',
  31. contains: [
  32. {
  33. endsParent:true,
  34. contains: [{
  35. contains: [hljs.BACKSLASH_ESCAPE, SUBST],
  36. variants: [
  37. { begin: /"/, end: /"/ },
  38. { begin: /'/, end: /'/ },
  39. { begin: /\//, end: /\// },
  40. { begin: /\|/, end: /\|/ },
  41. { begin: /\(/, end: /\)/ },
  42. { begin: /\[/, end: /\]/ },
  43. { begin: /\{/, end: /\}/ },
  44. { begin: /</, end: />/ }
  45. ]
  46. }]
  47. },
  48. ],
  49. };
  50. var UPCASE_SIGIL = {
  51. className: 'string',
  52. begin: '~[A-Z]' + '(?=' + SIGIL_DELIMITERS + ')',
  53. contains: [
  54. { begin: /"/, end: /"/ },
  55. { begin: /'/, end: /'/ },
  56. { begin: /\//, end: /\// },
  57. { begin: /\|/, end: /\|/ },
  58. { begin: /\(/, end: /\)/ },
  59. { begin: /\[/, end: /\]/ },
  60. { begin: /\{/, end: /\}/ },
  61. { begin: /\</, end: /\>/ }
  62. ]
  63. };
  64. var STRING = {
  65. className: 'string',
  66. contains: [hljs.BACKSLASH_ESCAPE, SUBST],
  67. variants: [
  68. {
  69. begin: /"""/, end: /"""/,
  70. },
  71. {
  72. begin: /'''/, end: /'''/,
  73. },
  74. {
  75. begin: /~S"""/, end: /"""/,
  76. contains: []
  77. },
  78. {
  79. begin: /~S"/, end: /"/,
  80. contains: []
  81. },
  82. {
  83. begin: /~S'''/, end: /'''/,
  84. contains: []
  85. },
  86. {
  87. begin: /~S'/, end: /'/,
  88. contains: []
  89. },
  90. {
  91. begin: /'/, end: /'/
  92. },
  93. {
  94. begin: /"/, end: /"/
  95. },
  96. ]
  97. };
  98. var FUNCTION = {
  99. className: 'function',
  100. beginKeywords: 'def defp defmacro', end: /\B\b/, // the mode is ended by the title
  101. contains: [
  102. hljs.inherit(hljs.TITLE_MODE, {
  103. begin: ELIXIR_IDENT_RE,
  104. endsParent: true
  105. })
  106. ]
  107. };
  108. var CLASS = hljs.inherit(FUNCTION, {
  109. className: 'class',
  110. beginKeywords: 'defimpl defmodule defprotocol defrecord', end: /\bdo\b|$|;/
  111. });
  112. var ELIXIR_DEFAULT_CONTAINS = [
  113. STRING,
  114. UPCASE_SIGIL,
  115. LOWERCASE_SIGIL,
  116. hljs.HASH_COMMENT_MODE,
  117. CLASS,
  118. FUNCTION,
  119. {
  120. begin: '::'
  121. },
  122. {
  123. className: 'symbol',
  124. begin: ':(?![\\s:])',
  125. contains: [STRING, {begin: ELIXIR_METHOD_RE}],
  126. relevance: 0
  127. },
  128. {
  129. className: 'symbol',
  130. begin: ELIXIR_IDENT_RE + ':(?!:)',
  131. relevance: 0
  132. },
  133. NUMBER,
  134. {
  135. className: 'variable',
  136. begin: '(\\$\\W)|((\\$|\\@\\@?)(\\w+))'
  137. },
  138. {
  139. begin: '->'
  140. },
  141. { // regexp container
  142. begin: '(' + hljs.RE_STARTERS_RE + ')\\s*',
  143. contains: [
  144. hljs.HASH_COMMENT_MODE,
  145. {
  146. // to prevent false regex triggers for the division function:
  147. // /:
  148. begin: /\/: (?=\d+\s*[,\]])/,
  149. relevance: 0,
  150. contains: [
  151. NUMBER
  152. ]
  153. },
  154. {
  155. className: 'regexp',
  156. illegal: '\\n',
  157. contains: [hljs.BACKSLASH_ESCAPE, SUBST],
  158. variants: [
  159. {
  160. begin: '/', end: '/[a-z]*'
  161. },
  162. {
  163. begin: '%r\\[', end: '\\][a-z]*'
  164. }
  165. ]
  166. }
  167. ],
  168. relevance: 0
  169. }
  170. ];
  171. SUBST.contains = ELIXIR_DEFAULT_CONTAINS;
  172. return {
  173. name: 'Elixir',
  174. keywords: ELIXIR_KEYWORDS,
  175. contains: ELIXIR_DEFAULT_CONTAINS
  176. };
  177. }
  178. module.exports = elixir;