(function (Prism) { // Functions to construct regular expressions // simple form // e.g. (interactive ... or (interactive) function simple_form(name) { return RegExp('(\\()' + name + '(?=[\\s\\)])'); } // booleans and numbers function primitive(pattern) { return RegExp('([\\s([])' + pattern + '(?=[\\s)])'); } // 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 = '[-+*/_~!@$%^=<>{}\\w]+'; // 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 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 + '(?:(?:lexical-)?let\\*?|(?:cl-)?letf|if|when|while|unless|cons|cl-loop|and|or|not|cond|setq|error|message|null|require|provide|use-package)' + space ), lookbehind: true }, { pattern: RegExp( par + '(?:for|do|collect|return|finally|append|concat|in|by)' + space ), lookbehind: true }, ], declare: { pattern: simple_form('declare'), lookbehind: true, alias: 'keyword' }, interactive: { pattern: simple_form('interactive'), lookbehind: true, alias: 'keyword' }, boolean: { pattern: primitive('(?:t|nil)'), lookbehind: true }, number: { pattern: primitive('[-+]?\\d+(?:\\.\\d*)?'), lookbehind: true }, defvar: { pattern: RegExp(par + 'def(?:var|const|custom|group)\\s+' + symbol), lookbehind: true, inside: { keyword: /^def[a-z]+/, variable: RegExp(symbol) } }, defun: { pattern: RegExp( par + '(?:cl-)?(?:defun\\*?|defmacro)\\s+' + symbol + '\\s+\\([\\s\\S]*?\\)' ), lookbehind: 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+\\((?:&?' + symbol + '\\s*)*\\)'), lookbehind: 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), rest: { argument: { pattern: RegExp(symbol), alias: 'variable' }, varform: { pattern: RegExp(par + symbol + '\\s+\\S[\\s\\S]*' + endpar), lookbehind: true, inside: { string: language.string, boolean: language.boolean, number: language.number, symbol: language.symbol, punctuation: /[()]/ } } } }; var forms = '\\S+(?:\\s+\\S+)*'; var arglist = { pattern: RegExp(par + '[\\s\\S]*' + endpar), lookbehind: true, inside: { 'rest-vars': { pattern: RegExp('&(?:rest|body)\\s+' + forms), inside: arg }, 'other-marker-vars': { pattern: RegExp('&(?:optional|aux)\\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));