comparison lisp/font-lock.el @ 26920:e510f839bc63

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.
author Gerd Moellmann <gerd@gnu.org>
date Thu, 16 Dec 1999 15:03:34 +0000
parents 11fddded9ceb
children d30c57a6b35c
comparison
equal deleted inserted replaced
26919:4335b1ee34bb 26920:e510f839bc63
504 where MAJOR-MODE is a symbol and FONT-LOCK-DEFAULTS is a list of default 504 where MAJOR-MODE is a symbol and FONT-LOCK-DEFAULTS is a list of default
505 settings. See the variable `font-lock-defaults', which takes precedence.") 505 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.
513 This is normally set via `font-lock-defaults'.") 519 This is normally set via `font-lock-defaults'.")
514 520
752 (cond (mode 758 (cond (mode
753 ;; If MODE is non-nil, add the KEYWORDS and APPEND spec to 759 ;; If MODE is non-nil, add the KEYWORDS and APPEND spec to
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)))
767 (setq font-lock-keywords (if append 778 (setq font-lock-keywords (if append
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." 829
775 (setq font-lock-keywords (copy-list font-lock-keywords)) 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."
776 (dolist (keyword keywords) 832 (dolist (keyword keywords)
777 (setq font-lock-keywords 833 ;; Remove one keyword at the time.
778 (delete keyword 834 (cond (major-mode
779 (delete (font-lock-compile-keyword keyword) 835 (let ((top-cell (assq major-mode font-lock-keywords-alist)))
780 font-lock-keywords))))) 836 ;; If MAJOR-MODE is non-nil, remove the KEYWORD from
781 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
785 ;; A few people have hassled in the past for a way to make it easier to turn on 877 ;; A few people have hassled in the past for a way to make it easier to turn on
786 ;; Font Lock mode, without the user needing to know for which modes s/he has to 878 ;; Font Lock mode, without the user needing to know for which modes s/he has to
1607 (let* ((defaults (or font-lock-defaults 1699 (let* ((defaults (or font-lock-defaults
1608 (cdr (assq major-mode font-lock-defaults-alist)))) 1700 (cdr (assq major-mode font-lock-defaults-alist))))
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)))
1616 ;; Local fontification? 1710 ;; Local fontification?
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))
1623 ;; Case fold during regexp fontification? 1719 ;; Case fold during regexp fontification?
1624 (when (nth 2 defaults) 1720 (when (nth 2 defaults)
2352 "float" "double" "void" "complex")))) 2448 "float" "double" "void" "complex"))))
2353 c-font-lock-extra-types) 2449 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
2360 ;; 2463 ;;
2361 ;; These are all anchored at the beginning of line for speed. 2464 ;; These are all anchored at the beginning of line for speed.
2378 '("^#[ \t]*\\(elif\\|if\\)\\>" 2481 '("^#[ \t]*\\(elif\\|if\\)\\>"
2379 ("\\<\\(defined\\)\\>[ \t]*(?\\(\\sw+\\)?" nil nil 2482 ("\\<\\(defined\\)\\>[ \t]*(?\\(\\sw+\\)?" nil nil
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
2388 (append c-font-lock-keywords-1 2495 (append c-font-lock-keywords-1
2389 (list 2496 (list
2396 ;; 2503 ;;
2397 ;; Fontify all builtin keywords (except case, default and goto; see below). 2504 ;; Fontify all builtin keywords (except case, default and goto; see below).
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.
2406 '(":" ("^[ \t]*\\(\\sw+\\)[ \t]*:[ \t]*$" 2518 '(":" ("^[ \t]*\\(\\sw+\\)[ \t]*:[ \t]*$"
2407 (beginning-of-line) (end-of-line) 2519 (beginning-of-line) (end-of-line)
2508 ;; Move over any item value, etc., to the next item. 2620 ;; Move over any item value, etc., to the next item.
2509 (while (not (looking-at "[ \t]*\\(\\(,\\)\\|;\\|$\\)")) 2621 (while (not (looking-at "[ \t]*\\(\\(,\\)\\|;\\|$\\)"))
2510 (goto-char (or (scan-sexps (point) 1) (point-max)))) 2622 (goto-char (or (scan-sexps (point) 1) (point-max))))
2511 (goto-char (match-end 2))) 2623 (goto-char (match-end 2)))
2512 (error t))))) 2624 (error t)))))
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))
2513 2643
2514 (let* ((c++-keywords 2644 (let* ((c++-keywords
2515 (eval-when-compile 2645 (eval-when-compile
2516 (regexp-opt 2646 (regexp-opt
2517 '("break" "continue" "do" "else" "for" "if" "return" "switch" 2647 '("break" "continue" "do" "else" "for" "if" "return" "switch"
2597 (list (concat "\\<\\(operator\\)\\>[ \t]*\\(" c++-operators "\\)?") 2727 (list (concat "\\<\\(operator\\)\\>[ \t]*\\(" c++-operators "\\)?")
2598 '(1 font-lock-keyword-face) 2728 '(1 font-lock-keyword-face)
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)
2607 (1 font-lock-constant-face))) 2749 (1 font-lock-constant-face)))
2608 ;; 2750 ;;
2690 (t font-lock-variable-name-face))) 2832 (t font-lock-variable-name-face)))
2691 (3 font-lock-type-face nil t) 2833 (3 font-lock-type-face nil t)
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
2698 (defvar c++-font-lock-keywords c++-font-lock-keywords-1 2844 (defvar c++-font-lock-keywords c++-font-lock-keywords-1
2699 "Default expressions to highlight in C++ mode. 2845 "Default expressions to highlight in C++ mode.