prism-lisp.js 4.8 KB

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