]> code.delx.au - gnu-emacs/commitdiff
Improve dynamic elisp keyword font-locking
authorTassilo Horn <tsdh@gnu.org>
Mon, 16 Mar 2015 09:25:14 +0000 (10:25 +0100)
committerTassilo Horn <tsdh@gnu.org>
Wed, 18 Mar 2015 06:44:01 +0000 (07:44 +0100)
* emacs-lisp/byte-run.el (macro-declarations-alist): New
declaration no-font-lock-keyword.
(defmacro): Flush font-lock in existing elisp buffers.

* emacs-lisp/lisp-mode.el (lisp--el-update-after-load)
(lisp--el-update-macro-regexp, lisp--el-macro-regexp): Delete
functions and defconst.
(lisp--el-match-keyword): Rename from lisp--el-match-macro.
(lisp--el-font-lock-flush-elisp-buffers): New function.
(lisp-mode-variables): Remove code for updating
lisp--el-macro-regexp, and add
lisp--el-font-lock-flush-elisp-buffers to after-load-functions.

lisp/ChangeLog
lisp/emacs-lisp/byte-run.el
lisp/emacs-lisp/lisp-mode.el

index 25571bab9c56939795963476d33912dcdaad764d..e365346c972b3c64c5f64808114302867e1f65d0 100644 (file)
@@ -1,3 +1,18 @@
+2015-03-17  Tassilo Horn  <tsdh@gnu.org>
+
+       * emacs-lisp/byte-run.el (macro-declarations-alist): New
+       declaration no-font-lock-keyword.
+       (defmacro): Flush font-lock in existing elisp buffers.
+
+       * emacs-lisp/lisp-mode.el (lisp--el-update-after-load)
+       (lisp--el-update-macro-regexp, lisp--el-macro-regexp): Delete
+       functions and defconst.
+       (lisp--el-match-keyword): Rename from lisp--el-match-macro.
+       (lisp--el-font-lock-flush-elisp-buffers): New function.
+       (lisp-mode-variables): Remove code for updating
+       lisp--el-macro-regexp, and add
+       lisp--el-font-lock-flush-elisp-buffers to after-load-functions.
+
 2015-03-17  Simen Heggestøyl  <simenheg@gmail.com>
 
        * textmodes/css-mode.el (css--font-lock-keywords): Discriminate
index caa7e3dad33d2f4cd2c1214fa20b1e7f1417b070..e0d6c3e782974cd3aa0d64265b380b4595080475 100644 (file)
@@ -147,11 +147,16 @@ This is used by `declare'.")
 (defvar macro-declarations-alist
   (cons
    (list 'debug
-         #'(lambda (name _args spec)
-             (list 'progn :autoload-end
-                   (list 'put (list 'quote name)
-                         ''edebug-form-spec (list 'quote spec)))))
-   defun-declarations-alist)
+        #'(lambda (name _args spec)
+            (list 'progn :autoload-end
+                  (list 'put (list 'quote name)
+                        ''edebug-form-spec (list 'quote spec)))))
+   (cons
+    (list 'no-font-lock-keyword
+         #'(lambda (name _args val)
+             (list 'function-put (list 'quote name)
+                   ''no-font-lock-keyword (list 'quote val))))
+    defun-declarations-alist))
   "List associating properties of macros to their macro expansion.
 Each element of the list takes the form (PROP FUN) where FUN is a function.
 For each (PROP . VALUES) in a macro's declaration, the FUN corresponding
@@ -201,6 +206,19 @@ The return value is undefined.
                          (message "Warning: Unknown macro property %S in %S"
                                   (car x) name))))
                  decls)))
+          ;; Refresh font-lock if this is a new macro, or it is an
+          ;; existing macro whose 'no-font-lock-keyword declaration
+          ;; has changed.
+          (if (and
+               ;; If lisp-mode hasn't been loaded, there's no reason
+               ;; to flush.
+               (fboundp 'lisp--el-font-lock-flush-elisp-buffers)
+               (or (not (fboundp name)) ;; new macro
+                   (and (fboundp name)  ;; existing macro
+                        (member `(function-put ',name 'no-font-lock-keyword
+                                               ',(get name 'no-font-lock-keyword))
+                                declarations))))
+              (lisp--el-font-lock-flush-elisp-buffers))
           (if declarations
               (cons 'prog1 (cons def declarations))
             def))))))
index b4f87fdac66812a0b515637c82ac19fa07173558..6b3077302ed04f7d13922e592e2a96aa082544a0 100644 (file)
             nil)))
     res))
 
-(defconst lisp--el-macro-regexp nil
-  "A regular expression matching all loaded elisp macros.
-Can be updated using `lisp--el-update-macro-regexp' after new
-macros were defined.")
-
-(defun lisp--el-update-macro-regexp ()
-  "Update `lisp--el-update-macro-regexp' from `obarray'.
-Return non-nil only if the old and new value are different."
-  (let ((old-regex lisp--el-macro-regexp)
-       (elisp-macros nil))
-    (mapatoms (lambda (a)
-               (when (or (macrop a) (special-form-p a))
-                 (push (symbol-name a) elisp-macros))))
-    (setq lisp--el-macro-regexp
-         (concat "(" (regexp-opt elisp-macros t) "\\_>"))
-    (not (string= old-regex lisp--el-macro-regexp))))
-
-(defun lisp--el-update-after-load (_file)
-  "Update `lisp--el-macro-regexp' and adjust font-lock in existing buffers."
-  (when (lisp--el-update-macro-regexp)
+(defun lisp--el-match-keyword (limit)
+  (catch 'found
+    (while (re-search-forward "(\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>" limit t)
+      (let ((sym (intern-soft (match-string 1))))
+       (when (or (special-form-p sym)
+                 (and (macrop sym)
+                      (not (get sym 'no-font-lock-keyword))))
+         (throw 'found t))))))
+
+(defun lisp--el-font-lock-flush-elisp-buffers (&optional file)
+  ;; Don't flush during load unless called from after-load-functions.
+  ;; In that case, FILE is non-nil.  It's somehow strange that
+  ;; load-in-progress is t when an after-load-function is called since
+  ;; that should run *after* the load...
+  (when (or (not load-in-progress) file)
     (dolist (buf (buffer-list))
-      (when (derived-mode-p 'emacs-lisp-mode)
-       (font-lock-flush)))))
-
-(defun lisp--el-match-macro (limit)
-  (re-search-forward lisp--el-macro-regexp limit t))
+      (with-current-buffer buf
+       (when (derived-mode-p 'emacs-lisp-mode)
+         (font-lock-flush))))))
 
 (pcase-let
     ((`(,vdefs ,tdefs
@@ -362,7 +355,7 @@ Return non-nil only if the old and new value are different."
      `( ;; Regexp negated char group.
        ("\\[\\(\\^\\)" 1 font-lock-negation-char-face prepend)
        ;; Control structures.  Common Lisp forms.
-       (lisp--el-match-macro . 1)
+       (lisp--el-match-keyword . 1)
        ;; Exit/Feature symbols as constants.
        (,(concat "(\\(catch\\|throw\\|featurep\\|provide\\|require\\)\\_>"
                  "[ \t']*\\(\\(?:\\sw\\|\\s_\\)+\\)?")
@@ -543,9 +536,7 @@ font-lock keywords will not be case sensitive."
           . lisp-font-lock-syntactic-face-function)))
   (setq-local prettify-symbols-alist lisp--prettify-symbols-alist)
   (when elisp
-    (unless lisp--el-macro-regexp
-      (lisp--el-update-macro-regexp))
-    (add-hook 'after-load-functions #'lisp--el-update-after-load)
+    (add-hook 'after-load-functions #'lisp--el-font-lock-flush-elisp-buffers)
     (setq-local electric-pair-text-pairs
                 (cons '(?\` . ?\') electric-pair-text-pairs)))
   (setq-local electric-pair-skip-whitespace 'chomp)