diff options
| author | Gerd Moellmann | 1999-12-16 15:05:06 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 1999-12-16 15:05:06 +0000 |
| commit | 76f5e2afd48a91c1a2740e4d10648acf9397d638 (patch) | |
| tree | d2ab7587fe99ffb6e803d995846b2d99eba4db2b | |
| parent | 031999fb8042b73f8fb6aab649c0356b860f7955 (diff) | |
| download | emacs-76f5e2afd48a91c1a2740e4d10648acf9397d638.tar.gz emacs-76f5e2afd48a91c1a2740e4d10648acf9397d638.zip | |
System for adding and removing keywords.
Both local (previously added keyword) and global keywords
can be removed.
(font-lock-remove-keywords): New user-level function.
(font-lock-update-removed-keyword-alist): New internal function.
(font-lock-removed-keywords-alist): New variable.
(font-lock-add-keywords): Updates `font-lock-removed-keywords-alist'.
Empty `font-lock-keywords-alist' when `append' is `set' to avoid
growing datastructures.
(font-lock-set-defaults): Removes keywords stored in
`font-lock-removed-keywords-alist' after local keywords added.
(c-keywords, c++-keywords): Better "case" support for
complex constant expressions, e.g. "case 1<<A_BIT_NO:".
(c-keywords): Only highlight preprocessor
directives when spelled correctly.
(font-lock-match-c++-structor-declaration,
c++-keywords): Fontify constructors and destructors with function
face inside C++ class declarations.
| -rw-r--r-- | lisp/ChangeLog | 26 | ||||
| -rw-r--r-- | lisp/font-lock.el | 186 |
2 files changed, 192 insertions, 20 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index b071b169886..9dcd3a6c359 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,29 @@ | |||
| 1 | 1999-11-16 Anders Lindgren <AndersL@andersl.com> | ||
| 2 | |||
| 3 | * font-lock.el: System for adding and removing keywords. | ||
| 4 | Both local (previously added keyword) and global keywords | ||
| 5 | can be removed. | ||
| 6 | (font-lock-remove-keywords): New user-level function. | ||
| 7 | (font-lock-update-removed-keyword-alist): New internal function. | ||
| 8 | (font-lock-removed-keywords-alist): New variable. | ||
| 9 | (font-lock-add-keywords): Updates `font-lock-removed-keywords-alist'. | ||
| 10 | Empty `font-lock-keywords-alist' when `append' is `set' to avoid | ||
| 11 | growing datastructures. | ||
| 12 | (font-lock-set-defaults): Removes keywords stored in | ||
| 13 | `font-lock-removed-keywords-alist' after local keywords added. | ||
| 14 | |||
| 15 | 1999-12-16 Anders Lindgren <andersl@andersl.com> | ||
| 16 | |||
| 17 | * font-lock.el (c-keywords, c++-keywords): Better "case" support for | ||
| 18 | complex constant expressions, e.g. "case 1<<A_BIT_NO:". | ||
| 19 | |||
| 20 | * font-lock.el (c-keywords): Only highlight preprocessor | ||
| 21 | directives when spelled correctly. | ||
| 22 | |||
| 23 | * font-lock.el (font-lock-match-c++-structor-declaration, | ||
| 24 | c++-keywords): Fontify constructors and destructors with function | ||
| 25 | face inside C++ class declarations. | ||
| 26 | |||
| 1 | 1999-12-16 Gerd Moellmann <gerd@gnu.org> | 27 | 1999-12-16 Gerd Moellmann <gerd@gnu.org> |
| 2 | 28 | ||
| 3 | * progmodes/sh-script.el (sh-mode): If there is no #!-line, use | 29 | * progmodes/sh-script.el (sh-mode): If there is no #!-line, use |
diff --git a/lisp/font-lock.el b/lisp/font-lock.el index cf612452105..c0dab76b0c8 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el | |||
| @@ -506,7 +506,13 @@ settings. See the variable `font-lock-defaults', which takes precedence.") | |||
| 506 | 506 | ||
| 507 | (defvar font-lock-keywords-alist nil | 507 | (defvar font-lock-keywords-alist nil |
| 508 | "*Alist of `font-lock-keywords' local to a `major-mode'. | 508 | "*Alist of `font-lock-keywords' local to a `major-mode'. |
| 509 | This is normally set via `font-lock-add-keywords'.") | 509 | This is normally set via `font-lock-add-keywords' and |
| 510 | `font-lock-remove-keywords'.") | ||
| 511 | |||
| 512 | (defvar font-lock-removed-keywords-alist nil | ||
| 513 | "*Alist of `font-lock-keywords' removed from `major-mode'. | ||
| 514 | This is normally set via `font-lock-add-keywords' and | ||
| 515 | `font-lock-remove-keywords'.") | ||
| 510 | 516 | ||
| 511 | (defvar font-lock-keywords-only nil | 517 | (defvar font-lock-keywords-only nil |
| 512 | "*Non-nil means Font Lock should not fontify comments or strings. | 518 | "*Non-nil means Font Lock should not fontify comments or strings. |
| @@ -754,13 +760,18 @@ see the variables `c-font-lock-extra-types', `c++-font-lock-extra-types', | |||
| 754 | ;; `font-lock-keywords-alist' so `font-lock-set-defaults' uses them. | 760 | ;; `font-lock-keywords-alist' so `font-lock-set-defaults' uses them. |
| 755 | (let ((spec (cons keywords append)) cell) | 761 | (let ((spec (cons keywords append)) cell) |
| 756 | (if (setq cell (assq mode font-lock-keywords-alist)) | 762 | (if (setq cell (assq mode font-lock-keywords-alist)) |
| 757 | (setcdr cell (append (cdr cell) (list spec))) | 763 | (if (eq append 'set) |
| 758 | (push (list mode spec) font-lock-keywords-alist)))) | 764 | (setcdr cell (list spec)) |
| 765 | (setcdr cell (append (cdr cell) (list spec)))) | ||
| 766 | (push (list mode spec) font-lock-keywords-alist))) | ||
| 767 | ;; Make sure that `font-lock-removed-keywords-alist' does not | ||
| 768 | ;; contain the new keywords. | ||
| 769 | (font-lock-update-removed-keyword-alist mode keywords append)) | ||
| 759 | (font-lock-mode | 770 | (font-lock-mode |
| 760 | ;; Otherwise if Font Lock mode is on, set or add the keywords now. | 771 | ;; Otherwise if Font Lock mode is on, set or add the keywords now. |
| 761 | (if (eq append 'set) | 772 | (if (eq append 'set) |
| 762 | (setq font-lock-keywords keywords) | 773 | (setq font-lock-keywords keywords) |
| 763 | (font-lock-remove-keywords nil keywords) | 774 | (font-lock-remove-keywords mode keywords) |
| 764 | (let ((old (if (eq (car-safe font-lock-keywords) t) | 775 | (let ((old (if (eq (car-safe font-lock-keywords) t) |
| 765 | (cdr font-lock-keywords) | 776 | (cdr font-lock-keywords) |
| 766 | font-lock-keywords))) | 777 | font-lock-keywords))) |
| @@ -768,17 +779,98 @@ see the variables `c-font-lock-extra-types', `c++-font-lock-extra-types', | |||
| 768 | (append old keywords) | 779 | (append old keywords) |
| 769 | (append keywords old)))))))) | 780 | (append keywords old)))))))) |
| 770 | 781 | ||
| 782 | (defun font-lock-update-removed-keyword-alist (major-mode keywords append) | ||
| 783 | ;; Update `font-lock-removed-keywords-alist' when adding new | ||
| 784 | ;; KEYWORDS to MAJOR-MODE. | ||
| 785 | ;; | ||
| 786 | ;; When font-lock is enabled first all keywords in the list | ||
| 787 | ;; `font-lock-keywords-alist' are added, then all keywords in the | ||
| 788 | ;; list `font-lock-removed-keywords-alist' are removed. If a | ||
| 789 | ;; keyword was once added, removed, and then added again it must be | ||
| 790 | ;; removed from the removed-keywords list. Otherwise the second add | ||
| 791 | ;; will not take effect. | ||
| 792 | (let ((cell (assq major-mode font-lock-removed-keywords-alist))) | ||
| 793 | (if cell | ||
| 794 | (if (eq append 'set) | ||
| 795 | ;; A new set of keywords is defined. Forget all about | ||
| 796 | ;; our old keywords that should be removed. | ||
| 797 | (setq font-lock-removed-keywords-alist | ||
| 798 | (delq cell font-lock-removed-keywords-alist)) | ||
| 799 | ;; Delete all previously removed keywords. | ||
| 800 | (dolist (kword keywords) | ||
| 801 | (setcdr cell (delete kword (cdr cell)))) | ||
| 802 | ;; Delete the major-mode cell if empty. | ||
| 803 | (if (null (cdr cell)) | ||
| 804 | (setq font-lock-removed-keywords-alist | ||
| 805 | (delq cell font-lock-removed-keywords-alist))))))) | ||
| 806 | |||
| 807 | ;; Written by Anders Lindgren <andersl@andersl.com>. | ||
| 808 | ;; | ||
| 809 | ;; Case study: | ||
| 810 | ;; (I) The keywords are removed from a major mode. | ||
| 811 | ;; In this case the keyword could be local (i.e. added earlier by | ||
| 812 | ;; `font-lock-add-keywords'), global, or both. | ||
| 813 | ;; | ||
| 814 | ;; (a) In the local case we remove the keywords from the variable | ||
| 815 | ;; `font-lock-keywords-alist'. | ||
| 816 | ;; | ||
| 817 | ;; (b) The actual global keywords are not known at this time. | ||
| 818 | ;; All keywords are added to `font-lock-removed-keywords-alist', | ||
| 819 | ;; when font-lock is enabled those keywords are removed. | ||
| 820 | ;; | ||
| 821 | ;; Note that added keywords are taken out of the list of removed | ||
| 822 | ;; keywords. This ensure correct operation when the same keyword | ||
| 823 | ;; is added and removed several times. | ||
| 824 | ;; | ||
| 825 | ;; (II) The keywords are removed from the current buffer. | ||
| 771 | ;;;###autoload | 826 | ;;;###autoload |
| 772 | (defun font-lock-remove-keywords (mode keywords) | 827 | (defun font-lock-remove-keywords (major-mode keywords) |
| 773 | "Remove highlighting KEYWORDS from the current buffer. | 828 | "Remove highlighting KEYWORDS for MAJOR-MODE. |
| 774 | A non-nil MODE is currently unsupported." | ||
| 775 | (setq font-lock-keywords (copy-list font-lock-keywords)) | ||
| 776 | (dolist (keyword keywords) | ||
| 777 | (setq font-lock-keywords | ||
| 778 | (delete keyword | ||
| 779 | (delete (font-lock-compile-keyword keyword) | ||
| 780 | font-lock-keywords))))) | ||
| 781 | 829 | ||
| 830 | MAJOR-MODE should be a symbol, the major mode command name, such as `c-mode' | ||
| 831 | or nil. If nil, highlighting keywords are removed for the current buffer." | ||
| 832 | (dolist (keyword keywords) | ||
| 833 | ;; Remove one keyword at the time. | ||
| 834 | (cond (major-mode | ||
| 835 | (let ((top-cell (assq major-mode font-lock-keywords-alist))) | ||
| 836 | ;; If MAJOR-MODE is non-nil, remove the KEYWORD from | ||
| 837 | ;; `font-lock-keywords-alist'. | ||
| 838 | (when top-cell | ||
| 839 | (dolist (keyword-list-append-pair (cdr top-cell)) | ||
| 840 | ;; `keywords-list-append-pair' is a cons with a list of | ||
| 841 | ;; keywords in the car top-cell and the original append | ||
| 842 | ;; argument in the cdr top-cell. | ||
| 843 | (setcar keyword-list-append-pair | ||
| 844 | (delete keyword (car keyword-list-append-pair)))) | ||
| 845 | ;; Remove keyword list/append pair when the keyword list | ||
| 846 | ;; is empty and append doesn't specify `set'. (If it | ||
| 847 | ;; should be deleted then previously deleted keywords | ||
| 848 | ;; would appear again.) | ||
| 849 | (let ((cell top-cell)) | ||
| 850 | (while (cdr cell) | ||
| 851 | (if (and (null (car (car (cdr cell)))) | ||
| 852 | (not (eq (cdr (car (cdr cell))) 'set))) | ||
| 853 | (setcdr cell (cdr (cdr cell))) | ||
| 854 | (setq cell (cdr cell))))) | ||
| 855 | ;; Final cleanup, remove major mode cell if last keyword | ||
| 856 | ;; was deleted. | ||
| 857 | (if (null (cdr top-cell)) | ||
| 858 | (setq font-lock-keywords-alist | ||
| 859 | (delq top-cell font-lock-keywords-alist)))) | ||
| 860 | ;; Remember the keyword in case it is not local. | ||
| 861 | (let ((cell (assq major-mode font-lock-removed-keywords-alist))) | ||
| 862 | (if cell | ||
| 863 | (unless (member keyword (cdr cell)) | ||
| 864 | (nconc cell (list keyword))) | ||
| 865 | (push (cons major-mode (list keyword)) | ||
| 866 | font-lock-removed-keywords-alist))))) | ||
| 867 | (font-lock-mode | ||
| 868 | ;; Otherwise if Font Lock mode is on, remove it immediately. | ||
| 869 | (setq font-lock-keywords (delete keyword font-lock-keywords)) | ||
| 870 | ;; The keywords might be compiled. | ||
| 871 | (setq font-lock-keywords | ||
| 872 | (delete (font-lock-compile-keyword keyword) | ||
| 873 | font-lock-keywords)))))) | ||
| 782 | 874 | ||
| 783 | ;;; Global Font Lock mode. | 875 | ;;; Global Font Lock mode. |
| 784 | 876 | ||
| @@ -1609,7 +1701,9 @@ Sets various variables using `font-lock-defaults' (or, if nil, using | |||
| 1609 | (keywords | 1701 | (keywords |
| 1610 | (font-lock-choose-keywords (nth 0 defaults) | 1702 | (font-lock-choose-keywords (nth 0 defaults) |
| 1611 | (font-lock-value-in-major-mode font-lock-maximum-decoration))) | 1703 | (font-lock-value-in-major-mode font-lock-maximum-decoration))) |
| 1612 | (local (cdr (assq major-mode font-lock-keywords-alist)))) | 1704 | (local (cdr (assq major-mode font-lock-keywords-alist))) |
| 1705 | (removed-keywords | ||
| 1706 | (cdr-safe (assq major-mode font-lock-removed-keywords-alist)))) | ||
| 1613 | ;; Regexp fontification? | 1707 | ;; Regexp fontification? |
| 1614 | (set (make-local-variable 'font-lock-keywords) | 1708 | (set (make-local-variable 'font-lock-keywords) |
| 1615 | (font-lock-compile-keywords (font-lock-eval-keywords keywords))) | 1709 | (font-lock-compile-keywords (font-lock-eval-keywords keywords))) |
| @@ -1617,6 +1711,8 @@ Sets various variables using `font-lock-defaults' (or, if nil, using | |||
| 1617 | (while local | 1711 | (while local |
| 1618 | (font-lock-add-keywords nil (car (car local)) (cdr (car local))) | 1712 | (font-lock-add-keywords nil (car (car local)) (cdr (car local))) |
| 1619 | (setq local (cdr local))) | 1713 | (setq local (cdr local))) |
| 1714 | (when removed-keywords | ||
| 1715 | (font-lock-remove-keywords nil removed-keywords)) | ||
| 1620 | ;; Syntactic fontification? | 1716 | ;; Syntactic fontification? |
| 1621 | (when (nth 1 defaults) | 1717 | (when (nth 1 defaults) |
| 1622 | (set (make-local-variable 'font-lock-keywords-only) t)) | 1718 | (set (make-local-variable 'font-lock-keywords-only) t)) |
| @@ -2354,6 +2450,13 @@ See also `c-font-lock-extra-types'.") | |||
| 2354 | "\\|")) | 2450 | "\\|")) |
| 2355 | (c-type-names-depth | 2451 | (c-type-names-depth |
| 2356 | `(regexp-opt-depth (,@ c-type-names))) | 2452 | `(regexp-opt-depth (,@ c-type-names))) |
| 2453 | (c-preprocessor-directives | ||
| 2454 | (eval-when-compile | ||
| 2455 | (regexp-opt | ||
| 2456 | '("define" "elif" "else" "endif" "error" "file" "if" "ifdef" | ||
| 2457 | "ifndef" "include" "line" "pragma" "undef")))) | ||
| 2458 | (c-preprocessor-directives-depth | ||
| 2459 | (regexp-opt-depth c-preprocessor-directives)) | ||
| 2357 | ) | 2460 | ) |
| 2358 | (setq c-font-lock-keywords-1 | 2461 | (setq c-font-lock-keywords-1 |
| 2359 | (list | 2462 | (list |
| @@ -2380,8 +2483,12 @@ See also `c-font-lock-extra-types'.") | |||
| 2380 | (1 font-lock-builtin-face) (2 font-lock-variable-name-face nil t))) | 2483 | (1 font-lock-builtin-face) (2 font-lock-variable-name-face nil t))) |
| 2381 | ;; | 2484 | ;; |
| 2382 | ;; Fontify otherwise as symbol names, and the preprocessor directive names. | 2485 | ;; Fontify otherwise as symbol names, and the preprocessor directive names. |
| 2383 | '("^#[ \t]*\\(\\sw+\\)\\>[ \t!]*\\(\\sw+\\)?" | 2486 | (list |
| 2384 | (1 font-lock-builtin-face) (2 font-lock-variable-name-face nil t)) | 2487 | (concat "^#[ \t]*\\(" c-preprocessor-directives |
| 2488 | "\\)\\>[ \t!]*\\(\\sw+\\)?") | ||
| 2489 | '(1 font-lock-builtin-face) | ||
| 2490 | (list (+ 2 c-preprocessor-directives-depth) | ||
| 2491 | 'font-lock-variable-name-face nil t)) | ||
| 2385 | )) | 2492 | )) |
| 2386 | 2493 | ||
| 2387 | (setq c-font-lock-keywords-2 | 2494 | (setq c-font-lock-keywords-2 |
| @@ -2398,8 +2505,13 @@ See also `c-font-lock-extra-types'.") | |||
| 2398 | (concat "\\<\\(" c-keywords "\\|" c-type-specs "\\)\\>") | 2505 | (concat "\\<\\(" c-keywords "\\|" c-type-specs "\\)\\>") |
| 2399 | ;; | 2506 | ;; |
| 2400 | ;; Fontify case/goto keywords and targets, and case default/goto tags. | 2507 | ;; Fontify case/goto keywords and targets, and case default/goto tags. |
| 2401 | '("\\<\\(case\\|goto\\)\\>[ \t]*\\(-?\\sw+\\)?" | 2508 | '("\\<\\(case\\|goto\\)\\>" |
| 2402 | (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) | 2509 | (1 font-lock-keyword-face) |
| 2510 | ("\\(-[0-9]+\\|\\sw+\\)" | ||
| 2511 | ;; Return limit of search. | ||
| 2512 | (save-excursion (skip-chars-forward "^:\n") (point)) | ||
| 2513 | nil | ||
| 2514 | (1 font-lock-constant-face nil t))) | ||
| 2403 | ;; Anders Lindgren <andersl@andersl.com> points out that it is quicker to | 2515 | ;; Anders Lindgren <andersl@andersl.com> points out that it is quicker to |
| 2404 | ;; use MATCH-ANCHORED to effectively anchor the regexp on the left. | 2516 | ;; use MATCH-ANCHORED to effectively anchor the regexp on the left. |
| 2405 | ;; This must come after the one for keywords and targets. | 2517 | ;; This must come after the one for keywords and targets. |
| @@ -2511,6 +2623,24 @@ See also `c++-font-lock-extra-types'.") | |||
| 2511 | (goto-char (match-end 2))) | 2623 | (goto-char (match-end 2))) |
| 2512 | (error t))))) | 2624 | (error t))))) |
| 2513 | 2625 | ||
| 2626 | (defun font-lock-match-c++-structor-declaration (limit) | ||
| 2627 | ;; Match C++ constructors and destructors inside class declarations. | ||
| 2628 | (let ((res nil) | ||
| 2629 | (regexp (concat "^\\s-+\\(\\(virtual\\|explicit\\)\\s-+\\)*~?\\(\\<" | ||
| 2630 | (mapconcat 'identity | ||
| 2631 | c++-font-lock-extra-types "\\|") | ||
| 2632 | "\\>\\)\\s-*(" | ||
| 2633 | ;; Don't match function pointer declarations, e.g.: | ||
| 2634 | ;; Foo (*fptr)(); | ||
| 2635 | "\\s-*[^*( \t]"))) | ||
| 2636 | (while (progn (setq res (re-search-forward regexp limit t)) | ||
| 2637 | (and res | ||
| 2638 | (save-excursion | ||
| 2639 | (beginning-of-line) | ||
| 2640 | (save-match-data | ||
| 2641 | (not (vectorp (c-at-toplevel-p)))))))) | ||
| 2642 | res)) | ||
| 2643 | |||
| 2514 | (let* ((c++-keywords | 2644 | (let* ((c++-keywords |
| 2515 | (eval-when-compile | 2645 | (eval-when-compile |
| 2516 | (regexp-opt | 2646 | (regexp-opt |
| @@ -2599,8 +2729,20 @@ See also `c++-font-lock-extra-types'.") | |||
| 2599 | '(2 font-lock-builtin-face nil t)) | 2729 | '(2 font-lock-builtin-face nil t)) |
| 2600 | ;; | 2730 | ;; |
| 2601 | ;; Fontify case/goto keywords and targets, and case default/goto tags. | 2731 | ;; Fontify case/goto keywords and targets, and case default/goto tags. |
| 2602 | '("\\<\\(case\\|goto\\)\\>[ \t]*\\(-?\\sw+\\)?" | 2732 | '("\\<\\(case\\|goto\\)\\>" |
| 2603 | (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) | 2733 | (1 font-lock-keyword-face) |
| 2734 | ("\\(-[0-9]+\\|\\sw+\\)[ \t]*\\(::\\)?" | ||
| 2735 | ;; Return limit of search. | ||
| 2736 | (save-excursion | ||
| 2737 | (while (progn | ||
| 2738 | (skip-chars-forward "^:\n") | ||
| 2739 | (looking-at "::")) | ||
| 2740 | (forward-char 2)) | ||
| 2741 | (point)) | ||
| 2742 | nil | ||
| 2743 | (1 (if (match-beginning 2) | ||
| 2744 | font-lock-type-face | ||
| 2745 | font-lock-constant-face) nil t))) | ||
| 2604 | ;; This must come after the one for keywords and targets. | 2746 | ;; This must come after the one for keywords and targets. |
| 2605 | '(":" ("^[ \t]*\\(\\sw+\\)[ \t]*:\\($\\|[^:]\\)" | 2747 | '(":" ("^[ \t]*\\(\\sw+\\)[ \t]*:\\($\\|[^:]\\)" |
| 2606 | (beginning-of-line) (end-of-line) | 2748 | (beginning-of-line) (end-of-line) |
| @@ -2692,6 +2834,10 @@ See also `c++-font-lock-extra-types'.") | |||
| 2692 | (5 (if (match-beginning 6) | 2834 | (5 (if (match-beginning 6) |
| 2693 | font-lock-function-name-face | 2835 | font-lock-function-name-face |
| 2694 | font-lock-variable-name-face) nil t))) | 2836 | font-lock-variable-name-face) nil t))) |
| 2837 | ;; | ||
| 2838 | ;; Fontify constructors and destructors inside class declarations. | ||
| 2839 | '(font-lock-match-c++-structor-declaration | ||
| 2840 | (3 font-lock-function-name-face t)) | ||
| 2695 | ))) | 2841 | ))) |
| 2696 | ) | 2842 | ) |
| 2697 | 2843 | ||