prism-lisp.js 4.6 KB

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