(function (Prism) { /** * Functions to construct regular expressions * e.g. (interactive ... or (interactive) * * @param {string} name * @returns {RegExp} */ function simple_form(name) { return RegExp(/(\()/.source + '(?:' + name + ')' + /(?=[\s\)])/.source); } /** * booleans and numbers * * @param {string} pattern * @returns {RegExp} */ function primitive(pattern) { return RegExp(/([\s([])/.source + '(?:' + pattern + ')' + /(?=[\s)])/.source); } // Patterns in regular expressions // Symbol name. See https://www.gnu.org/software/emacs/manual/html_node/elisp/Symbol-Type.html // & and : are excluded as they are usually used for special purposes var symbol = /(?!\d)[-+*/~!@$%^=<>{}\w]+/.source; // symbol starting with & used in function arguments var marker = '&' + symbol; // Open parenthesis for look-behind var par = '(\\()'; var endpar = '(?=\\))'; // End the pattern with look-ahead space var space = '(?=\\s)'; var nestedPar = /(?:[^()]|\((?:[^()]|\((?:[^()]|\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\))*\))*\))*/.source; var language = { // Three or four semicolons are considered a heading. // See https://www.gnu.org/software/emacs/manual/html_node/elisp/Comment-Tips.html heading: { pattern: /;;;.*/, alias: ['comment', 'title'] }, comment: /;.*/, string: { pattern: /"(?:[^"\\]|\\.)*"/, greedy: true, inside: { argument: /[-A-Z]+(?=[.,\s])/, symbol: RegExp('`' + symbol + "'") } }, 'quoted-symbol': { pattern: RegExp("#?'" + symbol), alias: ['variable', 'symbol'] }, 'lisp-property': { pattern: RegExp(':' + symbol), alias: 'property' }, splice: { pattern: RegExp(',@?' + symbol), alias: ['symbol', 'variable'] }, keyword: [ { pattern: RegExp( par + '(?:and|(?:cl-)?letf|cl-loop|cond|cons|error|if|(?:lexical-)?let\\*?|message|not|null|or|provide|require|setq|unless|use-package|when|while)' + space ), lookbehind: true }, { pattern: RegExp( par + '(?:append|by|collect|concat|do|finally|for|in|return)' + space ), lookbehind: true }, ], declare: { pattern: simple_form(/declare/.source), lookbehind: true, alias: 'keyword' }, interactive: { pattern: simple_form(/interactive/.source), lookbehind: true, alias: 'keyword' }, boolean: { pattern: primitive(/nil|t/.source), lookbehind: true }, number: { pattern: primitive(/[-+]?\d+(?:\.\d*)?/.source), lookbehind: true }, defvar: { pattern: RegExp(par + 'def(?:const|custom|group|var)\\s+' + symbol), lookbehind: true, inside: { keyword: /^def[a-z]+/, variable: RegExp(symbol) } }, defun: { pattern: RegExp(par + /(?:cl-)?(?:defmacro|defun\*?)\s+/.source + symbol + /\s+\(/.source + nestedPar + /\)/.source), lookbehind: true, greedy: true, inside: { keyword: /^(?:cl-)?def\S+/, // See below, this property needs to be defined later so that it can // reference the language object. arguments: null, function: { pattern: RegExp('(^\\s)' + symbol), lookbehind: true }, punctuation: /[()]/ } }, lambda: { pattern: RegExp(par + 'lambda\\s+\\(\\s*(?:&?' + symbol + '(?:\\s+&?' + symbol + ')*\\s*)?\\)'), lookbehind: true, greedy: true, inside: { keyword: /^lambda/, // See below, this property needs to be defined later so that it can // reference the language object. arguments: null, punctuation: /[()]/ } }, car: { pattern: RegExp(par + symbol), lookbehind: true }, punctuation: [ // open paren, brackets, and close paren /(?:['`,]?\(|[)\[\]])/, // cons { pattern: /(\s)\.(?=\s)/, lookbehind: true }, ] }; var arg = { 'lisp-marker': RegExp(marker), 'varform': { pattern: RegExp(/\(/.source + symbol + /\s+(?=\S)/.source + nestedPar + /\)/.source), inside: language }, 'argument': { pattern: RegExp(/(^|[\s(])/.source + symbol), lookbehind: true, alias: 'variable' }, rest: language }; var forms = '\\S+(?:\\s+\\S+)*'; var arglist = { pattern: RegExp(par + nestedPar + endpar), lookbehind: true, inside: { 'rest-vars': { pattern: RegExp('&(?:body|rest)\\s+' + forms), inside: arg }, 'other-marker-vars': { pattern: RegExp('&(?:aux|optional)\\s+' + forms), inside: arg }, keys: { pattern: RegExp('&key\\s+' + forms + '(?:\\s+&allow-other-keys)?'), inside: arg }, argument: { pattern: RegExp(symbol), alias: 'variable' }, punctuation: /[()]/ } }; language['lambda'].inside.arguments = arglist; language['defun'].inside.arguments = Prism.util.clone(arglist); language['defun'].inside.arguments.inside.sublist = arglist; Prism.languages.lisp = language; Prism.languages.elisp = language; Prism.languages.emacs = language; Prism.languages['emacs-lisp'] = language; }(Prism));