;;; font-lock.el --- Electric font lock mode
-;; Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 1999, 2000, 2001, 02, 2003
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+;; 2000, 2001, 2002, 2003, 2004 2005 Free Software Foundation, Inc.
;; Author: jwz, then rms, then sm
;; Maintainer: FSF
(require 'syntax)
;; Define core `font-lock' group.
-(defgroup font-lock nil
+(defgroup font-lock '((jit-lock custom-group))
"Font Lock mode text highlighting package."
:link '(custom-manual "(emacs)Font Lock")
:link '(custom-manual "(elisp)Font Lock Mode")
;; Define support mode groups here to impose `font-lock' group order.
(defgroup fast-lock nil
"Font Lock support mode to cache fontification."
- :link '(custom-manual "(emacs)Support Modes")
:load 'fast-lock
:group 'font-lock)
(defgroup lazy-lock nil
"Font Lock support mode to fontify lazily."
- :link '(custom-manual "(emacs)Support Modes")
:load 'lazy-lock
:group 'font-lock)
-
-(defgroup jit-lock nil
- "Font Lock support mode to fontify just-in-time."
- :link '(custom-manual "(emacs)Support Modes")
- :version "21.1"
- :load 'jit-lock
- :group 'font-lock)
\f
;; User variables.
(defvar font-lock-keywords nil
"A list of the keywords to highlight.
-Each element should have one of these forms:
+There are two kinds of values: user-level, and compiled.
+
+A user-level keywords list is what a major mode or the user would
+set up. Normally the list would come from `font-lock-defaults'.
+through selection of a fontification level and evaluation of any
+contained expressions. You can also alter it by calling
+`font-lock-add-keywords' or `font-lock-remove-keywords' with MODE = nil.
+
+Each element in a user-level keywords list should have one of these forms:
MATCHER
(MATCHER . MATCH)
(eval . FORM)
where MATCHER can be either the regexp to search for, or the function name to
-call to make the search (called with one argument, the limit of the search) and
-return non-nil if it succeeds (and set `match-data' appropriately).
+call to make the search (called with one argument, the limit of the search;
+it should return non-nil, move point, and set `match-data' appropriately iff
+it succeeds; like `re-search-forward' would).
MATCHER regexps can be generated via the function `regexp-opt'.
FORM is an expression, whose value should be a keyword element, evaluated when
This variable is set by major modes via the variable `font-lock-defaults'.
Be careful when composing regexps for this list; a poorly written pattern can
-dramatically slow things down!")
+dramatically slow things down!
+
+A compiled keywords list starts with t. It is produced internal
+by `font-lock-compile-keywords' from a user-level keywords list.
+Its second element is the user-level keywords list that was
+compiled. The remaining elements have the same form as
+user-level keywords, but normally their values have been
+optimized.")
(defvar font-lock-keywords-alist nil
"*Alist of `font-lock-keywords' local to a `major-mode'.
(font-lock-update-removed-keyword-alist mode keywords append))
(t
;; Otherwise set or add the keywords now.
+ ;; This is a no-op if it has been done already in this buffer.
(font-lock-set-defaults)
- (if (eq append 'set)
- (setq font-lock-keywords keywords)
- (font-lock-remove-keywords nil keywords) ;to avoid duplicates
- (let ((old (if (eq (car-safe font-lock-keywords) t)
- (cdr font-lock-keywords)
- font-lock-keywords)))
- (setq font-lock-keywords (if append
- (append old keywords)
- (append keywords old))))))))
+ (let ((was-compiled (eq (car font-lock-keywords) t)))
+ ;; Bring back the user-level (uncompiled) keywords.
+ (if was-compiled
+ (setq font-lock-keywords (cadr font-lock-keywords)))
+ ;; Now modify or replace them.
+ (if (eq append 'set)
+ (setq font-lock-keywords keywords)
+ (font-lock-remove-keywords nil keywords) ;to avoid duplicates
+ (let ((old (if (eq (car-safe font-lock-keywords) t)
+ (cdr font-lock-keywords)
+ font-lock-keywords)))
+ (setq font-lock-keywords (if append
+ (append old keywords)
+ (append keywords old)))))
+ ;; If the keywords were compiled before, compile them again.
+ (if was-compiled
+ (set (make-local-variable 'font-lock-keywords)
+ (font-lock-compile-keywords font-lock-keywords t)))))))
(defun font-lock-update-removed-keyword-alist (mode keywords append)
;; Update `font-lock-removed-keywords-alist' when adding new
(t
;; Otherwise remove it immediately.
(font-lock-set-defaults)
- (setq font-lock-keywords (copy-sequence font-lock-keywords))
- (dolist (keyword keywords)
- (setq font-lock-keywords
- (delete keyword
- ;; The keywords might be compiled.
- (delete (font-lock-compile-keyword keyword)
- font-lock-keywords)))))))
+ (let ((was-compiled (eq (car font-lock-keywords) t)))
+ ;; Bring back the user-level (uncompiled) keywords.
+ (if was-compiled
+ (setq font-lock-keywords (cadr font-lock-keywords)))
+
+ ;; Edit them.
+ (setq font-lock-keywords (copy-sequence font-lock-keywords))
+ (dolist (keyword keywords)
+ (setq font-lock-keywords
+ (delete keyword font-lock-keywords)))
+
+ ;; If the keywords were compiled before, compile them again.
+ (if was-compiled
+ (set (make-local-variable 'font-lock-keywords)
+ (font-lock-compile-keywords font-lock-keywords t)))))))
\f
;;; Font Lock Support mode.
(funcall font-lock-fontify-region-function beg end loudly))
(defun font-lock-unfontify-region (beg end)
- (funcall font-lock-unfontify-region-function beg end))
+ (save-buffer-state nil
+ (funcall font-lock-unfontify-region-function beg end)))
(defun font-lock-default-fontify-buffer ()
(let ((verbose (if (numberp font-lock-verbose)
what properties to clear before refontifying a region.")
(defun font-lock-default-unfontify-region (beg end)
- (save-buffer-state nil
- (remove-list-of-text-properties
- beg end (append
- font-lock-extra-managed-props
- (if font-lock-syntactic-keywords
- '(syntax-table face font-lock-multiline)
- '(face font-lock-multiline))))))
+ (remove-list-of-text-properties
+ beg end (append
+ font-lock-extra-managed-props
+ (if font-lock-syntactic-keywords
+ '(syntax-table face font-lock-multiline)
+ '(face font-lock-multiline)))))
;; Called when any modification is made to buffer text.
(defun font-lock-after-change-function (beg end old-len)
- (let ((inhibit-point-motion-hooks t))
+ (let ((inhibit-point-motion-hooks t)
+ (inhibit-quit t))
(save-excursion
(save-match-data
;; Rescan between start of lines enclosing the region.
font-lock-syntactic-keywords)))
;; Get down to business.
(let ((case-fold-search font-lock-keywords-case-fold-search)
- (keywords (cdr font-lock-syntactic-keywords))
+ (keywords (cddr font-lock-syntactic-keywords))
keyword matcher highlights)
(while keywords
;; Find an occurrence of `matcher' from `start' to `end'.
(if loudly (message "Fontifying %s... (syntactically...)" (buffer-name)))
(goto-char start)
;;
- ;; Find the state at the `beginning-of-line' before `start'.
+ ;; Find the `start' state.
(setq state (or ppss (syntax-ppss start)))
;;
;; Find each interesting place between here and `end'.
(setq state (parse-partial-sexp (point) end nil nil state
'syntax-table))
(when face (put-text-property beg (point) 'face face)))
- (setq state (parse-partial-sexp (point) end nil nil state
- 'syntax-table))
- (< (point) end)))))
+ (< (point) end))
+ (setq state (parse-partial-sexp (point) end nil nil state
+ 'syntax-table)))))
;;; End of Syntactic fontification functions.
\f
(add-text-properties start end (cddr val))
(setq val (cadr val)))
(cond
+ ((not (or val (eq override t)))
+ ;; If `val' is nil, don't do anything. It is important to do it
+ ;; explicitly, because when adding nil via things like
+ ;; font-lock-append-text-property, the property is actually
+ ;; changed from <face> to (<face>) which is undesirable. --Stef
+ nil)
((not override)
;; Cannot override existing fontification.
(or (text-property-not-all start end 'face nil)
(setq font-lock-keywords
(font-lock-compile-keywords font-lock-keywords t)))
(let ((case-fold-search font-lock-keywords-case-fold-search)
- (keywords (cdr font-lock-keywords))
+ (keywords (cddr font-lock-keywords))
(bufname (buffer-name)) (count 0)
keyword matcher highlights)
;;
(while highlights
(if (numberp (car (car highlights)))
(font-lock-apply-highlight (car highlights))
- (font-lock-fontify-anchored-keywords (car highlights) end))
+ (let ((pos (point)))
+ (font-lock-fontify-anchored-keywords (car highlights) end)
+ ;; Ensure forward progress.
+ (if (< (point) pos) (goto-char pos))))
(setq highlights (cdr highlights))))
(setq keywords (cdr keywords)))))
;; Various functions.
(defun font-lock-compile-keywords (keywords &optional regexp)
- "Compile KEYWORDS into the form (t KEYWORD ...).
-Here KEYWORD is of the form (MATCHER HIGHLIGHT ...) as shown in the
+ "Compile KEYWORDS into the form (t KEYWORDS COMPILED...)
+Here each COMPILED is of the form (MATCHER HIGHLIGHT ...) as shown in the
`font-lock-keywords' doc string.
If REGEXP is non-nil, it means these keywords are used for
`font-lock-keywords' rather than for `font-lock-syntactic-keywords'."
(if (eq (car-safe keywords) t)
keywords
- (setq keywords (cons t (mapcar 'font-lock-compile-keyword keywords)))
+ (setq keywords
+ (cons t (cons keywords
+ (mapcar 'font-lock-compile-keyword keywords))))
(if (and regexp
(eq (or syntax-begin-function
font-lock-beginning-of-syntax-function)
(concat "^\\(?:" defun-prompt-regexp "\\)?\\s(")
"^\\s(")
(0
- (if (memq (get-text-property (1- (point)) 'face)
+ (if (memq (get-text-property (match-beginning 0) 'face)
'(font-lock-string-face font-lock-doc-face
font-lock-comment-face))
font-lock-warning-face)
(make-local-variable 'font-lock-fontified)
(make-local-variable 'font-lock-multiline)
(let* ((defaults (or font-lock-defaults
- (cdr (assq major-mode font-lock-defaults-alist))))
+ (cdr (assq major-mode
+ (with-no-warnings
+ font-lock-defaults-alist)))))
(keywords
(font-lock-choose-keywords (nth 0 defaults)
(font-lock-value-in-major-mode font-lock-maximum-decoration)))
;; Variable alist?
(dolist (x (nthcdr 5 defaults))
(set (make-local-variable (car x)) (cdr x)))
- ;; Setup `font-lock-keywords' last because its value might depend
+ ;; Set up `font-lock-keywords' last because its value might depend
;; on other settings (e.g. font-lock-compile-keywords uses
;; font-lock-beginning-of-syntax-function).
(set (make-local-variable 'font-lock-keywords)
- (font-lock-compile-keywords (font-lock-eval-keywords keywords) t))
+ (font-lock-eval-keywords keywords))
;; Local fontification?
(while local
(font-lock-add-keywords nil (car (car local)) (cdr (car local)))
(setq local (cdr local)))
(when removed-keywords
- (font-lock-remove-keywords nil removed-keywords)))))
+ (font-lock-remove-keywords nil removed-keywords))
+ ;; Now compile the keywords.
+ (unless (eq (car font-lock-keywords) t)
+ (set (make-local-variable 'font-lock-keywords)
+ (font-lock-compile-keywords font-lock-keywords t))))))
\f
;;; Colour etc. support.
;; But now we do it the custom way. Note that `defface' will not overwrite any
;; faces declared above via `custom-declare-face'.
(defface font-lock-comment-face
- '((((type tty pc) (class color) (background light)) (:foreground "red"))
- (((type tty pc) (class color) (background dark)) (:foreground "red1"))
- (((class grayscale) (background light))
+ '((((class grayscale) (background light))
(:foreground "DimGray" :weight bold :slant italic))
(((class grayscale) (background dark))
(:foreground "LightGray" :weight bold :slant italic))
- (((class color) (background light)) (:foreground "Firebrick"))
- (((class color) (background dark)) (:foreground "chocolate1"))
+ (((class color) (min-colors 88) (background light))
+ (:foreground "Firebrick"))
+ (((class color) (min-colors 88) (background dark))
+ (:foreground "chocolate1"))
+ (((class color) (min-colors 16) (background light))
+ (:foreground "red"))
+ (((class color) (min-colors 16) (background dark))
+ (:foreground "red1"))
+ (((class color) (min-colors 8) (background light))
+ (:foreground "red"))
+ (((class color) (min-colors 8) (background dark))
+ (:foreground "red1"))
(t (:weight bold :slant italic)))
"Font Lock mode face used to highlight comments."
:group 'font-lock-highlighting-faces)
(defface font-lock-string-face
- '((((type tty) (class color)) (:foreground "green"))
- (((class grayscale) (background light)) (:foreground "DimGray" :slant italic))
+ '((((class grayscale) (background light)) (:foreground "DimGray" :slant italic))
(((class grayscale) (background dark)) (:foreground "LightGray" :slant italic))
- (((class color) (background light)) (:foreground "RosyBrown"))
- (((class color) (background dark)) (:foreground "LightSalmon"))
+ (((class color) (min-colors 88) (background light)) (:foreground "RosyBrown"))
+ (((class color) (min-colors 88) (background dark)) (:foreground "LightSalmon"))
+ (((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
+ (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
+ (((class color) (min-colors 8)) (:foreground "green"))
(t (:slant italic)))
"Font Lock mode face used to highlight strings."
:group 'font-lock-highlighting-faces)
:group 'font-lock-highlighting-faces)
(defface font-lock-keyword-face
- '((((type tty) (class color)) (:foreground "cyan" :weight bold))
- (((class grayscale) (background light)) (:foreground "LightGray" :weight bold))
+ '((((class grayscale) (background light)) (:foreground "LightGray" :weight bold))
(((class grayscale) (background dark)) (:foreground "DimGray" :weight bold))
- (((class color) (background light)) (:foreground "Purple"))
- (((class color) (background dark)) (:foreground "Cyan"))
+ (((class color) (min-colors 88) (background light)) (:foreground "Purple"))
+ (((class color) (min-colors 88) (background dark)) (:foreground "Cyan"))
+ (((class color) (min-colors 16) (background light)) (:foreground "Purple"))
+ (((class color) (min-colors 16) (background dark)) (:foreground "Cyan"))
+ (((class color) (min-colors 8)) (:foreground "cyan" :weight bold))
(t (:weight bold)))
"Font Lock mode face used to highlight keywords."
:group 'font-lock-highlighting-faces)
(defface font-lock-builtin-face
- '((((type tty) (class color)) (:foreground "blue" :weight light))
- (((class grayscale) (background light)) (:foreground "LightGray" :weight bold))
+ '((((class grayscale) (background light)) (:foreground "LightGray" :weight bold))
(((class grayscale) (background dark)) (:foreground "DimGray" :weight bold))
- (((class color) (background light)) (:foreground "Orchid"))
- (((class color) (background dark)) (:foreground "LightSteelBlue"))
+ (((class color) (min-colors 88) (background light)) (:foreground "Orchid"))
+ (((class color) (min-colors 88) (background dark)) (:foreground "LightSteelBlue"))
+ (((class color) (min-colors 16) (background light)) (:foreground "Orchid"))
+ (((class color) (min-colors 16) (background dark)) (:foreground "LightSteelBlue"))
+ (((class color) (min-colors 8)) (:foreground "blue" :weight bold))
(t (:weight bold)))
"Font Lock mode face used to highlight builtins."
:group 'font-lock-highlighting-faces)
(defface font-lock-function-name-face
- '((((type tty) (class color)) (:foreground "blue" :weight bold))
- (((class color) (background light)) (:foreground "Blue"))
- (((class color) (background dark)) (:foreground "LightSkyBlue"))
+ '((((class color) (min-colors 88) (background light)) (:foreground "Blue"))
+ (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
+ (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
+ (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
+ (((class color) (min-colors 8)) (:foreground "blue" :weight bold))
(t (:inverse-video t :weight bold)))
"Font Lock mode face used to highlight function names."
:group 'font-lock-highlighting-faces)
(defface font-lock-variable-name-face
- '((((type tty) (class color)) (:foreground "yellow" :weight light))
- (((class grayscale) (background light))
+ '((((class grayscale) (background light))
(:foreground "Gray90" :weight bold :slant italic))
(((class grayscale) (background dark))
(:foreground "DimGray" :weight bold :slant italic))
- (((class color) (background light)) (:foreground "DarkGoldenrod"))
- (((class color) (background dark)) (:foreground "LightGoldenrod"))
+ (((class color) (min-colors 88) (background light)) (:foreground "DarkGoldenrod"))
+ (((class color) (min-colors 88) (background dark)) (:foreground "LightGoldenrod"))
+ (((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
+ (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
+ (((class color) (min-colors 8)) (:foreground "yellow" :weight light))
(t (:weight bold :slant italic)))
"Font Lock mode face used to highlight variable names."
:group 'font-lock-highlighting-faces)
(defface font-lock-type-face
- '((((type tty) (class color)) (:foreground "green"))
- (((class grayscale) (background light)) (:foreground "Gray90" :weight bold))
+ '((((class grayscale) (background light)) (:foreground "Gray90" :weight bold))
(((class grayscale) (background dark)) (:foreground "DimGray" :weight bold))
- (((class color) (background light)) (:foreground "ForestGreen"))
- (((class color) (background dark)) (:foreground "PaleGreen"))
+ (((class color) (min-colors 88) (background light)) (:foreground "ForestGreen"))
+ (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen"))
+ (((class color) (min-colors 16) (background light)) (:foreground "ForestGreen"))
+ (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen"))
+ (((class color) (min-colors 8)) (:foreground "green"))
(t (:weight bold :underline t)))
"Font Lock mode face used to highlight type and classes."
:group 'font-lock-highlighting-faces)
(defface font-lock-constant-face
- '((((type tty) (class color)) (:foreground "magenta"))
- (((class grayscale) (background light))
+ '((((class grayscale) (background light))
(:foreground "LightGray" :weight bold :underline t))
(((class grayscale) (background dark))
(:foreground "Gray50" :weight bold :underline t))
- (((class color) (background light)) (:foreground "CadetBlue"))
- (((class color) (background dark)) (:foreground "Aquamarine"))
+ (((class color) (min-colors 88) (background light)) (:foreground "CadetBlue"))
+ (((class color) (min-colors 88) (background dark)) (:foreground "Aquamarine"))
+ (((class color) (min-colors 16) (background light)) (:foreground "CadetBlue"))
+ (((class color) (min-colors 16) (background dark)) (:foreground "Aquamarine"))
+ (((class color) (min-colors 8)) (:foreground "magenta"))
(t (:weight bold :underline t)))
"Font Lock mode face used to highlight constants and labels."
:group 'font-lock-highlighting-faces)
(defface font-lock-warning-face
- '((((type tty) (class color)) (:foreground "red"))
- (((class color) (background light)) (:foreground "Red" :weight bold))
- (((class color) (background dark)) (:foreground "Pink" :weight bold))
+ '((((class color) (min-colors 88) (background light)) (:foreground "Red" :weight bold))
+ (((class color) (min-colors 88) (background dark)) (:foreground "Pink" :weight bold))
+ (((class color) (min-colors 16) (background light)) (:foreground "Red" :weight bold))
+ (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :weight bold))
+ (((class color) (min-colors 8)) (:foreground "red"))
(t (:inverse-video t :weight bold)))
"Font Lock mode face used to highlight warnings."
:group 'font-lock-highlighting-faces)
(defface font-lock-preprocessor-face
- '((t :inherit 'font-lock-builtin-face))
+ '((t :inherit font-lock-builtin-face))
"Font Lock mode face used to highlight preprocessor directives."
:group 'font-lock-highlighting-faces)
"condition-case" "track-mouse"
"eval-after-load" "eval-and-compile" "eval-when-compile"
"eval-when"
+ "with-category-table"
"with-current-buffer" "with-electric-help"
+ "with-local-quit" "with-no-warnings"
"with-output-to-string" "with-output-to-temp-buffer"
+ "with-selected-window" "with-syntax-table"
"with-temp-buffer" "with-temp-file" "with-temp-message"
- "with-timeout") t)
+ "with-timeout" "with-timeout-handler") t)
"\\>")
1)
;;
'("when" "unless" "case" "ecase" "typecase" "etypecase"
"ccase" "ctypecase" "handler-case" "handler-bind"
"restart-bind" "restart-case" "in-package"
- "cerror" "break" "ignore-errors"
+ "break" "ignore-errors"
"loop" "do" "do*" "dotimes" "dolist" "the" "locally"
"proclaim" "declaim" "declare" "symbol-macrolet"
"lexical-let" "lexical-let*" "flet" "labels" "compiler-let"
- "destructuring-bind" "macrolet" "tagbody" "block"
- "return" "return-from") t)
+ "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)
;;
'(2 font-lock-constant-face nil t))
;;
;; Erroneous structures.
- '("(\\(abort\\|assert\\|error\\|signal\\)\\>" 1 font-lock-warning-face)
+ '("(\\(abort\\|assert\\|warn\\|check-type\\|cerror\\|error\\|signal\\)\\>" 1 font-lock-warning-face)
;;
;; Words inside \\[] tend to be for `substitute-command-keys'.
'("\\\\\\\\\\[\\(\\sw+\\)]" 1 font-lock-constant-face prepend)
;; ELisp and CLisp `&' keywords as types.
'("\\&\\sw+\\>" . font-lock-type-face)
;;
- ;; CL `with-' and `do-' constructs
- '("(\\(\\(do-\\|with-\\)\\(\\s_\\|\\w\\)*\\)" 1 font-lock-keyword-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.")
\f
(provide 'font-lock)
-(when (eq font-lock-support-mode 'jit-lock-mode)
- (require 'jit-lock))
-
-;;; arch-tag: 682327e4-64d8-4057-b20b-1fbb9f1fc54c
+;; arch-tag: 682327e4-64d8-4057-b20b-1fbb9f1fc54c
;;; font-lock.el ends here