From 06286513730d013c2033d1dae892349e5eec98d9 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Tue, 8 Oct 2013 10:57:18 -0400 Subject: [PATCH] * lisp/emacs-lisp/lisp-mode.el: Font-lock cl-lib constructs. (lisp-el-font-lock-keywords, lisp-el-font-lock-keywords-1) (lisp-el-font-lock-keywords-2, lisp-cl-font-lock-keywords) (lisp-cl-font-lock-keywords-1, lisp-cl-font-lock-keywords-2): New constants. (lisp-mode-variables): New `elisp' argument. (emacs-lisp-mode): Use it. * lisp/font-lock.el (lisp-font-lock-keywords, lisp-font-lock-keywords-1) (lisp-font-lock-keywords-2): Move to lisp-mode.el. --- lisp/ChangeLog | 10 ++ lisp/emacs-lisp/lisp-mode.el | 250 ++++++++++++++++++++++++++++++++++- lisp/font-lock.el | 125 ------------------ 3 files changed, 255 insertions(+), 130 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index f9161dc29d..74ca0a23c9 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,5 +1,15 @@ 2013-10-08 Stefan Monnier + * emacs-lisp/lisp-mode.el: Font-lock cl-lib constructs. + (lisp-el-font-lock-keywords, lisp-el-font-lock-keywords-1) + (lisp-el-font-lock-keywords-2, lisp-cl-font-lock-keywords) + (lisp-cl-font-lock-keywords-1, lisp-cl-font-lock-keywords-2): + New constants. + (lisp-mode-variables): New `elisp' argument. + (emacs-lisp-mode): Use it. + * font-lock.el (lisp-font-lock-keywords, lisp-font-lock-keywords-1) + (lisp-font-lock-keywords-2): Move to lisp-mode.el. + * indent.el: Use lexical-binding. (indent-region): Add progress reporter. (tab-stop-list): Make it implicitly extend to infinity by repeating the diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index f1705cbc9e..0b82efab12 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -153,6 +153,242 @@ It has `lisp-mode-abbrev-table' as its parent." (defvar lisp-doc-string-elt-property 'doc-string-elt "The symbol property that holds the docstring position info.") + +;;;; Font-lock support. + +(pcase-let + ((`(,vdefs ,tdefs + ,el-defs-re ,cl-defs-re + ,el-kws-re ,cl-kws-re + ,el-errs-re ,cl-errs-re) + (eval-when-compile + (let ((lisp-fdefs '("defmacro" "defsubst" "defun")) + (lisp-vdefs '("defvar")) + (lisp-kw '("cond" "if" "while" "let" "let*" "progn" "prog1" + "prog2" "lambda" "unwind-protect" "condition-case" + "when" "unless" "with-output-to-string" + "ignore-errors" "dotimes" "dolist" "declare")) + (lisp-errs '("warn" "error" "signal")) + ;; Elisp constructs. FIXME: update dynamically from obarray. + (el-fdefs '("defadvice" "defalias" + "define-derived-mode" "define-minor-mode" + "define-generic-mode" "define-global-minor-mode" + "define-globalized-minor-mode" "define-skeleton" + "define-widget")) + (el-vdefs '("defconst" "defcustom" "defvaralias" "defvar-local" + "defface")) + (el-tdefs '("defgroup" "deftheme")) + (el-kw '("while-no-input" "letrec" "pcase" "pcase-let" + "pcase-let*" "save-restriction" "save-excursion" + "save-selected-window" + ;; "eval-after-load" "eval-next-after-load" + "save-window-excursion" "save-current-buffer" + "save-match-data" "combine-after-change-calls" + "condition-case-unless-debug" "track-mouse" + "eval-and-compile" "eval-when-compile" "with-case-table" + "with-category-table" "with-coding-priority" + "with-current-buffer" "with-demoted-errors" + "with-electric-help" "with-eval-after-load" + "with-local-quit" "with-no-warnings" + "with-output-to-temp-buffer" "with-selected-window" + "with-selected-frame" "with-silent-modifications" + "with-syntax-table" "with-temp-buffer" "with-temp-file" + "with-temp-message" "with-timeout" + "with-timeout-handler")) + (el-errs '("user-error")) + ;; Common-Lisp constructs supported by EIEIO. FIXME: namespace. + (eieio-fdefs '("defgeneric" "defmethod")) + (eieio-tdefs '("defclass")) + (eieio-kw '("with-slots")) + ;; Common-Lisp constructs supported by cl-lib. + (cl-lib-fdefs '("defmacro" "defsubst" "defun")) + (cl-lib-tdefs '("defstruct" "deftype")) + (cl-lib-kw '("progv" "eval-when" "case" "ecase" "typecase" + "etypecase" "ccase" "ctypecase" "loop" "do" "do*" + "the" "locally" "proclaim" "declaim" "letf" "go" + ;; "lexical-let" "lexical-let*" + "symbol-macrolet" "flet" "destructuring-bind" + "labels" "macrolet" "tagbody" "multiple-value-bind" + "block" "return" "return-from")) + (cl-lib-errs '("assert" "check-type")) + ;; Common-Lisp constructs not supported by cl-lib. + (cl-fdefs '("defsetf" "define-method-combination" + "define-condition" "define-setf-expander" + ;; "define-function"?? + "define-compiler-macro" "define-modify-macro")) + (cl-vdefs '("define-symbol-macro" "defconstant" "defparameter")) + (cl-tdefs '("defpackage" "defstruct" "deftype")) + (cl-kw '("prog" "prog*" "handler-case" "handler-bind" + "in-package" "restart-case" ;; "inline" + "restart-bind" "break" "multiple-value-prog1" + "compiler-let" "with-accessors" "with-compilation-unit" + "with-condition-restarts" "with-hash-table-iterator" + "with-input-from-string" "with-open-file" + "with-open-stream" "with-package-iterator" + "with-simple-restart" "with-standard-io-syntax")) + (cl-errs '("abort" "cerror"))) + + (list (append lisp-vdefs el-vdefs cl-vdefs) + (append el-tdefs eieio-tdefs cl-tdefs cl-lib-tdefs + (mapcar (lambda (s) (concat "cl-" s)) cl-lib-tdefs)) + + ;; Elisp and Common Lisp definers. + (regexp-opt (append lisp-fdefs lisp-vdefs + el-fdefs el-vdefs el-tdefs + (mapcar (lambda (s) (concat "cl-" s)) + (append cl-lib-fdefs cl-lib-tdefs)) + eieio-fdefs eieio-tdefs) + t) + (regexp-opt (append lisp-fdefs lisp-vdefs + cl-lib-fdefs cl-lib-tdefs + eieio-fdefs eieio-tdefs + cl-fdefs cl-vdefs cl-tdefs) + t) + + ;; Elisp and Common Lisp keywords. + (regexp-opt (append + lisp-kw el-kw eieio-kw + (cons "go" (mapcar (lambda (s) (concat "cl-" s)) + (remove "go" cl-lib-kw)))) + t) + (regexp-opt (append lisp-kw el-kw eieio-kw + (cons "go" (mapcar (lambda (s) (concat "cl-" s)) + (remove "go" cl-kw)))) + t) + + ;; Elisp and Common Lisp "errors". + (regexp-opt (append (mapcar (lambda (s) (concat "cl-" s)) + cl-lib-errs) + lisp-errs el-errs) + t) + (regexp-opt (append lisp-errs cl-lib-errs cl-errs) t)))))) + + (dolist (v vdefs) + (put (intern v) 'lisp-define-type 'var)) + (dolist (v tdefs) + (put (intern v) 'lisp-define-type 'type)) + + (define-obsolete-variable-alias 'lisp-font-lock-keywords-1 + 'lisp-el-font-lock-keywords-1 "24.4") + (defconst lisp-el-font-lock-keywords-1 + `( ;; Definitions. + (,(concat "(" el-defs-re "\\_>" + ;; Any whitespace and defined object. + "[ \t'\(]*" + "\\(\\(?:\\sw\\|\\s_\\)+\\)?") + (1 font-lock-keyword-face) + (2 (let ((type (get (intern-soft (match-string 1)) 'lisp-define-type))) + (cond ((eq type 'var) font-lock-variable-name-face) + ((eq type 'type) font-lock-type-face) + (t font-lock-function-name-face))) + nil t)) + ;; Emacs Lisp autoload cookies. Supports the slightly different + ;; forms used by mh-e, calendar, etc. + ("^;;;###\\([-a-z]*autoload\\)" 1 font-lock-warning-face prepend)) + "Subdued level highlighting for Emacs Lisp mode.") + + (defconst lisp-cl-font-lock-keywords-1 + `( ;; Definitions. + (,(concat "(" cl-defs-re "\\_>" + ;; Any whitespace and defined object. + "[ \t'\(]*" + "\\(setf[ \t]+\\(?:\\sw\\|\\s_\\)+\\|\\(?:\\sw\\|\\s_\\)+\\)?") + (1 font-lock-keyword-face) + (2 (let ((type (get (intern-soft (match-string 1)) 'lisp-define-type))) + (cond ((eq type 'var) font-lock-variable-name-face) + ((eq type 'type) font-lock-type-face) + (t font-lock-function-name-face))) + nil t))) + "Subdued level highlighting for Lisp modes.") + + (define-obsolete-variable-alias 'lisp-font-lock-keywords-2 + 'lisp-el-font-lock-keywords-2 "24.4") + (defconst lisp-el-font-lock-keywords-2 + (append + lisp-el-font-lock-keywords-1 + `( ;; Regexp negated char group. + ("\\[\\(\\^\\)" 1 font-lock-negation-char-face prepend) + ;; Control structures. Common Lisp forms. + (,(concat "(" el-kws-re "\\_>") . 1) + ;; Exit/Feature symbols as constants. + (,(concat "(\\(catch\\|throw\\|featurep\\|provide\\|require\\)\\_>" + "[ \t']*\\(\\(?:\\sw\\|\\s_\\)+\\)?") + (1 font-lock-keyword-face) + (2 font-lock-constant-face nil t)) + ;; Erroneous structures. + (,(concat "(" el-errs-re "\\_>") + (1 font-lock-warning-face)) + ;; Words inside \\[] tend to be for `substitute-command-keys'. + ("\\\\\\\\\\[\\(\\(?:\\sw\\|\\s_\\)+\\)\\]" + (1 font-lock-constant-face prepend)) + ;; Words inside `' tend to be symbol names. + ("`\\(\\(?:\\sw\\|\\s_\\)\\(?:\\sw\\|\\s_\\)+\\)'" + (1 font-lock-constant-face prepend)) + ;; Constant values. + ("\\_<:\\(?:\\sw\\|\\s_\\)+\\_>" 0 font-lock-builtin-face) + ;; ELisp and CLisp `&' keywords as types. + ("\\_<\\&\\(?:\\sw\\|\\s_\\)+\\_>" . font-lock-type-face) + ;; ELisp regexp grouping constructs + (,(lambda (bound) + (catch 'found + ;; The following loop is needed to continue searching after matches + ;; that do not occur in strings. The associated regexp matches one + ;; of `\\\\' `\\(' `\\(?:' `\\|' `\\)'. `\\\\' has been included to + ;; avoid highlighting, for example, `\\(' in `\\\\('. + (while (re-search-forward "\\(\\\\\\\\\\)\\(?:\\(\\\\\\\\\\)\\|\\((\\(?:\\?[0-9]*:\\)?\\|[|)]\\)\\)" bound t) + (unless (match-beginning 2) + (let ((face (get-text-property (1- (point)) 'face))) + (when (or (and (listp face) + (memq 'font-lock-string-face face)) + (eq 'font-lock-string-face face)) + (throw 'found t))))))) + (1 'font-lock-regexp-grouping-backslash prepend) + (3 'font-lock-regexp-grouping-construct prepend)) + ;; This is too general -- rms. + ;; A user complained that he has functions whose names start with `do' + ;; and that they get the wrong color. + ;; ;; CL `with-' and `do-' constructs + ;;("(\\(\\(do-\\|with-\\)\\(\\s_\\|\\w\\)*\\)" 1 font-lock-keyword-face) + )) + "Gaudy level highlighting for Emacs Lisp mode.") + + (defconst lisp-cl-font-lock-keywords-2 + (append + lisp-cl-font-lock-keywords-1 + `( ;; Regexp negated char group. + ("\\[\\(\\^\\)" 1 font-lock-negation-char-face prepend) + ;; Control structures. Common Lisp forms. + (,(concat "(" cl-kws-re "\\_>") . 1) + ;; Exit/Feature symbols as constants. + (,(concat "(\\(catch\\|throw\\|featurep\\|provide\\|require\\)\\_>" + "[ \t']*\\(\\(?:\\sw\\|\\s_\\)+\\)?") + (1 font-lock-keyword-face) + (2 font-lock-constant-face nil t)) + ;; Erroneous structures. + (,(concat "(" cl-errs-re "\\_>") + (1 font-lock-warning-face)) + ;; Words inside `' tend to be symbol names. + ("`\\(\\(?:\\sw\\|\\s_\\)\\(?:\\sw\\|\\s_\\)+\\)'" + (1 font-lock-constant-face prepend)) + ;; Constant values. + ("\\_<:\\(?:\\sw\\|\\s_\\)+\\_>" 0 font-lock-builtin-face) + ;; ELisp and CLisp `&' keywords as types. + ("\\_<\\&\\(?:\\sw\\|\\s_\\)+\\_>" . font-lock-type-face) + ;; This is too general -- rms. + ;; A user complained that he has functions whose names start with `do' + ;; and that they get the wrong color. + ;; ;; CL `with-' and `do-' constructs + ;;("(\\(\\(do-\\|with-\\)\\(\\s_\\|\\w\\)*\\)" 1 font-lock-keyword-face) + )) + "Gaudy level highlighting for Lisp modes.")) + +(define-obsolete-variable-alias 'lisp-font-lock-keywords + 'lisp-el-font-lock-keywords "24.4") +(defvar lisp-el-font-lock-keywords lisp-el-font-lock-keywords-1 + "Default expressions to highlight in Emacs Lisp mode.") +(defvar lisp-cl-font-lock-keywords lisp-cl-font-lock-keywords-1 + "Default expressions to highlight in Lisp modes.") + (defun lisp-font-lock-syntactic-face-function (state) (if (nth 3 state) ;; This might be a (doc)string or a |...| symbol. @@ -190,7 +426,8 @@ It has `lisp-mode-abbrev-table' as its parent." font-lock-string-face)))) font-lock-comment-face)) -(defun lisp-mode-variables (&optional lisp-syntax keywords-case-insensitive) +(defun lisp-mode-variables (&optional lisp-syntax keywords-case-insensitive + elisp) "Common initialization routine for lisp modes. The LISP-SYNTAX argument is used by code in inf-lisp.el and is \(uselessly) passed from pp.el, chistory.el, gnus-kill.el and @@ -227,9 +464,12 @@ font-lock keywords will not be case sensitive." (setq-local multibyte-syntax-as-symbol t) (setq-local syntax-begin-function 'beginning-of-defun) (setq font-lock-defaults - `((lisp-font-lock-keywords - lisp-font-lock-keywords-1 - lisp-font-lock-keywords-2) + `(,(if elisp '(lisp-el-font-lock-keywords + lisp-el-font-lock-keywords-1 + lisp-el-font-lock-keywords-2) + '(lisp-cl-font-lock-keywords + lisp-cl-font-lock-keywords-1 + lisp-cl-font-lock-keywords-2)) nil ,keywords-case-insensitive nil nil (font-lock-mark-block-function . mark-defun) (font-lock-syntactic-face-function @@ -466,7 +706,7 @@ Blank lines separate paragraphs. Semicolons start comments. Entry to this mode calls the value of `emacs-lisp-mode-hook' if that value is non-nil." :group 'lisp - (lisp-mode-variables) + (lisp-mode-variables nil nil 'elisp) (setq imenu-case-fold-search nil) (add-hook 'completion-at-point-functions 'lisp-completion-at-point nil 'local)) diff --git a/lisp/font-lock.el b/lisp/font-lock.el index 70ed73eb5a..18699be1c0 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el @@ -2240,131 +2240,6 @@ Used in `cpp-font-lock-keywords'.") for C preprocessor directives. This definition is for the other modes in which C preprocessor directives are used. e.g. `asm-mode' and `ld-script-mode'.") - - -;; Lisp. - -(defconst lisp-font-lock-keywords-1 - (eval-when-compile - `(;; Definitions. - (,(concat "(\\(def\\(" - ;; Function declarations. - "\\(advice\\|alias\\|generic\\|macro\\*?\\|method\\|" - "setf\\|subst\\*?\\|un\\*?\\|" - "ine-\\(condition\\|" - "\\(?:derived\\|\\(?:global\\(?:ized\\)?-\\)?minor\\|generic\\)-mode\\|" - "method-combination\\|setf-expander\\|skeleton\\|widget\\|" - "function\\|\\(compiler\\|modify\\|symbol\\)-macro\\)\\)\\|" - ;; Variable declarations. - "\\(const\\(ant\\)?\\|custom\\|varalias\\|face\\|parameter\\|var\\(?:-local\\)?\\)\\|" - ;; Structure declarations. - "\\(class\\|group\\|theme\\|package\\|struct\\|type\\)" - "\\)\\)\\_>" - ;; Any whitespace and defined object. - "[ \t'\(]*" - "\\(setf[ \t]+\\(?:\\sw\\|\\s_\\)+\\|\\(?:\\sw\\|\\s_\\)+\\)?") - (1 font-lock-keyword-face) - (9 (cond ((match-beginning 3) font-lock-function-name-face) - ((match-beginning 6) font-lock-variable-name-face) - (t font-lock-type-face)) - nil t)) - ;; Emacs Lisp autoload cookies. Supports the slightly different - ;; forms used by mh-e, calendar, etc. - ("^;;;###\\([-a-z]*autoload\\)" 1 font-lock-warning-face prepend) - ;; Regexp negated char group. - ("\\[\\(\\^\\)" 1 font-lock-negation-char-face prepend))) - "Subdued level highlighting for Lisp modes.") - -(defconst lisp-font-lock-keywords-2 - (append lisp-font-lock-keywords-1 - (eval-when-compile - `(;; Control structures. Emacs Lisp forms. - (,(concat - "(" (regexp-opt - '("cond" "if" "while" "while-no-input" "let" "let*" "letrec" - "pcase" "pcase-let" "pcase-let*" "prog" "progn" "progv" - "prog1" "prog2" "prog*" "inline" "lambda" - "save-restriction" "save-excursion" "save-selected-window" - "save-window-excursion" "save-match-data" "save-current-buffer" - "combine-after-change-calls" "unwind-protect" - "condition-case" "condition-case-unless-debug" - "track-mouse" "eval-after-load" "eval-and-compile" - "eval-when-compile" "eval-when" "eval-next-after-load" - "with-case-table" "with-category-table" "with-coding-priority" - "with-current-buffer" "with-demoted-errors" - "with-electric-help" "with-eval-after-load" - "with-local-quit" "with-no-warnings" - "with-output-to-string" "with-output-to-temp-buffer" - "with-selected-window" "with-selected-frame" - "with-silent-modifications" "with-syntax-table" - "with-temp-buffer" "with-temp-file" "with-temp-message" - "with-timeout" "with-timeout-handler") t) - "\\_>") - . 1) - ;; Control structures. Common Lisp forms. - (,(concat - "(" (regexp-opt - '("when" "unless" "case" "ecase" "typecase" "etypecase" - "ccase" "ctypecase" "handler-case" "handler-bind" - "restart-bind" "restart-case" "in-package" - "break" "ignore-errors" - "loop" "do" "do*" "dotimes" "dolist" "the" "locally" - "proclaim" "declaim" "declare" "symbol-macrolet" "letf" - "lexical-let" "lexical-let*" "flet" "labels" "compiler-let" - "destructuring-bind" "macrolet" "tagbody" "block" "go" - "multiple-value-bind" "multiple-value-prog1" - "return" "return-from" - "with-accessors" "with-compilation-unit" - "with-condition-restarts" "with-hash-table-iterator" - "with-input-from-string" "with-open-file" - "with-open-stream" "with-output-to-string" - "with-package-iterator" "with-simple-restart" - "with-slots" "with-standard-io-syntax") t) - "\\_>") - . 1) - ;; Exit/Feature symbols as constants. - (,(concat "(\\(catch\\|throw\\|featurep\\|provide\\|require\\)\\_>" - "[ \t']*\\(\\(?:\\sw\\|\\s_\\)+\\)?") - (1 font-lock-keyword-face) - (2 font-lock-constant-face nil t)) - ;; Erroneous structures. - ("(\\(abort\\|assert\\|warn\\|check-type\\|cerror\\|\\(?:user-\\)?error\\|signal\\)\\_>" 1 font-lock-warning-face) - ;; Words inside \\[] tend to be for `substitute-command-keys'. - ("\\\\\\\\\\[\\(\\(?:\\sw\\|\\s_\\)+\\)\\]" - (1 font-lock-constant-face prepend)) - ;; Words inside `' tend to be symbol names. - ("`\\(\\(?:\\sw\\|\\s_\\)\\(?:\\sw\\|\\s_\\)+\\)'" - (1 font-lock-constant-face prepend)) - ;; Constant values. - ("\\_<:\\(?:\\sw\\|\\s_\\)+\\_>" 0 font-lock-builtin-face) - ;; ELisp and CLisp `&' keywords as types. - ("\\_<\\&\\(?:\\sw\\|\\s_\\)+\\_>" . font-lock-type-face) - ;; ELisp regexp grouping constructs - ((lambda (bound) - (catch 'found - ;; The following loop is needed to continue searching after matches - ;; that do not occur in strings. The associated regexp matches one - ;; of `\\\\' `\\(' `\\(?:' `\\|' `\\)'. `\\\\' has been included to - ;; avoid highlighting, for example, `\\(' in `\\\\('. - (while (re-search-forward "\\(\\\\\\\\\\)\\(?:\\(\\\\\\\\\\)\\|\\((\\(?:\\?[0-9]*:\\)?\\|[|)]\\)\\)" bound t) - (unless (match-beginning 2) - (let ((face (get-text-property (1- (point)) 'face))) - (when (or (and (listp face) - (memq 'font-lock-string-face face)) - (eq 'font-lock-string-face face)) - (throw 'found t))))))) - (1 'font-lock-regexp-grouping-backslash prepend) - (3 'font-lock-regexp-grouping-construct prepend)) - ;; This is too general -- rms. - ;; A user complained that he has functions whose names start with `do' - ;; and that they get the wrong color. - ;; ;; CL `with-' and `do-' constructs - ;;("(\\(\\(do-\\|with-\\)\\(\\s_\\|\\w\\)*\\)" 1 font-lock-keyword-face) - ))) - "Gaudy level highlighting for Lisp modes.") - -(defvar lisp-font-lock-keywords lisp-font-lock-keywords-1 - "Default expressions to highlight in Lisp modes.") (provide 'font-lock) -- 2.20.1