1 ;; Electric Font Lock Mode
2 ;; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
4 ;; Author: jwz, then rms and sm (simon.marshall@mail.esrin.esa.it)
6 ;; Keywords: languages, faces
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27 ;; Font Lock mode is a minor mode that causes your comments to be displayed in
28 ;; one face, strings in another, reserved words in another, and so on.
30 ;; Comments will be displayed in `font-lock-comment-face'.
31 ;; Strings will be displayed in `font-lock-string-face'.
32 ;; Regexps are used to display selected patterns in other faces.
34 ;; To make the text you type be fontified, use M-x font-lock-mode.
35 ;; When this minor mode is on, the faces of the current line are
36 ;; updated with every insertion or deletion.
38 ;; To turn Font Lock mode on automatically, add this to your .emacs file:
40 ;; (add-hook 'emacs-lisp-mode-hook 'turn-on-font-lock)
42 ;; On a Sparc2, `font-lock-fontify-buffer' takes about 10 seconds for a 120k
43 ;; file of C code using the default configuration, and about 25 seconds using
44 ;; the more extensive configuration, though times also depend on file contents.
45 ;; You can speed this up substantially by removing some of the patterns that
46 ;; are highlighted by default. Fontifying Lisp code is significantly faster,
47 ;; because Lisp has a more regular syntax than C, so the expressions don't have
50 ;; If you add patterns for a new mode, say foo.el's `foo-mode', say in which
51 ;; you don't want syntactic fontification to occur, you can make Font Lock mode
52 ;; use your regexps when turning on Font Lock by adding to `foo-mode-hook':
54 ;; (add-hook 'foo-mode-hook
55 ;; '(lambda () (make-local-variable 'font-lock-defaults)
56 ;; (setq font-lock-defaults '(foo-font-lock-keywords t))))
58 ;; Nasty regexps of the form "bar\\(\\|lo\\)\\|f\\(oo\\|u\\(\\|bar\\)\\)\\|lo"
59 ;; are made thusly: (make-regexp '("foo" "fu" "fubar" "bar" "barlo" "lo")) for
60 ;; efficiency. See /pub/gnu/emacs/elisp-archive/functions/make-regexp.el.Z on
61 ;; archive.cis.ohio-state.edu for this and other functions.
65 (defvar font-lock-comment-face 'font-lock-comment-face
66 "Face to use for comments.")
68 (defvar font-lock-string-face 'font-lock-string-face
69 "Face to use for strings.")
71 (defvar font-lock-function-name-face 'font-lock-function-name-face
72 "Face to use for function names.")
74 (defvar font-lock-variable-name-face 'font-lock-variable-name-face
75 "Face to use for variable names.")
77 (defvar font-lock-keyword-face 'font-lock-keyword-face
78 "Face to use for keywords.")
80 (defvar font-lock-type-face 'font-lock-type-face
81 "Face to use for data types.")
83 (defvar font-lock-reference-face 'font-lock-reference-face
84 "Face to use for references.")
86 (defvar font-lock-no-comments nil
87 "Non-nil means Font Lock should not fontify comments or strings.")
89 (make-variable-buffer-local 'font-lock-keywords)
90 (defvar font-lock-keywords nil
91 "*The keywords to highlight.
92 Elements should be of the form:
98 (REGEXP HIGHLIGHT ...)
100 where HIGHLIGHT should be of the form (MATCH FACENAME OVERRIDE LAXMATCH).
101 REGEXP is the regexp to search for, MATCH is the subexpression of REGEXP to be
102 highlighted, FACENAME is an expression whose value is the face name to use.
103 FACENAME's default attributes may be defined in `font-lock-face-attributes'.
105 OVERRIDE and LAXMATCH are flags. If OVERRIDE is t, existing fontification may
106 be overriden. If `keep', only parts not already fontified are highlighted.
107 If LAXMATCH is non-nil, no error is signalled if there is no MATCH in REGEXP.
109 These regular expressions should not match text which spans lines. While
110 \\[font-lock-fontify-buffer] handles multi-line patterns correctly, updating
111 when you edit the buffer does not, since it considers text one line at a time.
113 Be careful composing regexps for this list;
114 the wrong pattern can dramatically slow things down!")
116 (defvar font-lock-defaults nil
117 "If set by a major mode, should be the defaults for Font Lock mode.
118 The value should look like the `cdr' of an item in `font-lock-defaults-alist'.")
120 (defvar font-lock-defaults-alist
121 '((bibtex-mode . (tex-font-lock-keywords))
122 (c++-c-mode . (c-font-lock-keywords nil nil ((?\_ . "w"))))
123 (c++-mode . (c++-font-lock-keywords nil nil ((?\_ . "w"))))
124 (c-mode . (c-font-lock-keywords nil nil ((?\_ . "w"))))
125 (emacs-lisp-mode . (lisp-font-lock-keywords))
126 (latex-mode . (tex-font-lock-keywords))
127 (lisp-mode . (lisp-font-lock-keywords))
128 (plain-tex-mode . (tex-font-lock-keywords))
129 (slitex-mode . (tex-font-lock-keywords))
130 (tex-mode . (tex-font-lock-keywords)))
131 "*Alist of default major mode and Font Lock defaults.
132 Each item should be a list of the form:
133 (MAJOR-MODE . (FONT-LOCK-KEYWORDS KEYWORDS-ONLY CASE-FOLD FONT-LOCK-SYNTAX))
134 where both MAJOR-MODE and FONT-LOCK-KEYWORDS are symbols. If KEYWORDS-ONLY is
135 non-nil, syntactic fontification (strings and comments) is not performed.
136 If CASE-FOLD is non-nil, the case of the keywords is ignored when fontifying.
137 FONT-LOCK-SYNTAX should be a list of cons pairs of the form (CHAR . STRING), it
138 is used to set the local Font Lock syntax table for keyword fontification.")
140 (defvar font-lock-maximum-size (* 100 1024)
141 "*If non-nil, the maximum size for buffers.
142 Only buffers less than are fontified when Font Lock mode is turned on.
143 If nil, means size is irrelevant.")
145 (defvar font-lock-keywords-case-fold-search nil
146 "*Non-nil means the patterns in `font-lock-keywords' are case-insensitive.")
148 (defvar font-lock-syntax-table nil
149 "*Non-nil means use this syntax table for fontifying.
150 If this is nil, the major mode's syntax table is used.")
152 (defvar font-lock-verbose t
153 "*Non-nil means `font-lock-fontify-buffer' should print status messages.")
156 (defvar font-lock-mode-hook nil
157 "Function or functions to run on entry to Font Lock mode.")
159 ;; Colour etc. support.
161 (defvar font-lock-display-type nil
162 "A symbol indicating the display Emacs is running under.
163 The symbol should be one of `color', `grayscale' or `mono'.
164 If Emacs guesses this display attribute wrongly, either set this variable in
165 your `~/.emacs' or set the resource `Emacs.displayType' in your `~/.Xdefaults'.
166 See also `font-lock-background-mode' and `font-lock-face-attributes'.")
168 (defvar font-lock-background-mode nil
169 "A symbol indicating the Emacs background brightness.
170 The symbol should be one of `light' or `dark'.
171 If Emacs guesses this frame attribute wrongly, either set this variable in
172 your `~/.emacs' or set the resource `Emacs.backgroundMode' in your
174 See also `font-lock-display-type' and `font-lock-face-attributes'.")
176 (defvar font-lock-face-attributes nil
177 "A list of default attributes to use for face attributes.
178 Each element of the list should be of the form
180 (FACE FOREGROUND BACKGROUND BOLD-P ITALIC-P UNDERLINE-P)
182 where FACE should be one of the face symbols `font-lock-comment-face',
183 `font-lock-string-face', `font-lock-keyword-face', `font-lock-type-face',
184 `font-lock-function-name-face', `font-lock-variable-name-face', and
185 `font-lock-reference-face'. A form for each of these face symbols should be
186 provided in the list, but other face symbols and attributes may be given and
187 used in highlighting. See `font-lock-keywords'.
189 Subsequent element items should be the attributes for the corresponding
190 Font Lock mode faces. Attributes FOREGROUND and BACKGROUND should be strings
191 \(default if nil), while BOLD-P, ITALIC-P, and UNDERLINE-P should specify the
192 corresponding face attributes (yes if non-nil).
194 Emacs uses default attributes based on display type and background brightness.
195 See variables `font-lock-display-type' and `font-lock-background-mode'.
197 Resources can be used to over-ride these face attributes. For example, the
198 resource `Emacs.font-lock-comment-face.attributeUnderline' can be used to
199 specify the UNDERLINE-P attribute for face `font-lock-comment-face'.")
201 (defun font-lock-make-faces ()
202 "Make faces from `font-lock-face-attributes'.
203 A default list is used if this is nil.
204 See `font-lock-make-face' and `list-faces-display'."
205 ;; We don't need to `setq' any of these variables, but the user can see what
206 ;; is being used if we do.
207 (if (null font-lock-display-type)
208 (setq font-lock-display-type
209 (let ((display-resource (x-get-resource ".displayType"
211 (cond (display-resource (intern (downcase display-resource)))
212 ((x-display-color-p) 'color)
213 ((x-display-grayscale-p) 'grayscale)
215 (if (null font-lock-background-mode)
216 (setq font-lock-background-mode
217 (let ((bg-resource (x-get-resource ".backgroundMode"
219 (params (frame-parameters)))
220 (cond (bg-resource (intern (downcase bg-resource)))
221 ((or (string-equal "white"
222 (downcase (cdr (assq 'foreground-color params))))
223 (string-equal "black"
224 (downcase (cdr (assq 'background-color params)))))
227 (if (null font-lock-face-attributes)
228 (setq font-lock-face-attributes
229 (let ((light-bg (eq font-lock-background-mode 'light)))
230 (cond ((memq font-lock-display-type '(mono monochrome))
231 ;; Emacs 19.25's font-lock defaults:
232 ;;'((font-lock-comment-face nil nil nil t nil)
233 ;; (font-lock-string-face nil nil nil nil t)
234 ;; (font-lock-keyword-face nil nil t nil nil)
235 ;; (font-lock-function-name-face nil nil t t nil)
236 ;; (font-lock-type-face nil nil nil t nil))
237 (list '(font-lock-comment-face nil nil t t nil)
238 '(font-lock-string-face nil nil nil t nil)
239 '(font-lock-keyword-face nil nil t nil nil)
241 'font-lock-function-name-face
242 (cdr (assq 'background-color (frame-parameters)))
243 (cdr (assq 'foreground-color (frame-parameters)))
245 '(font-lock-variable-name-face nil nil t t nil)
246 '(font-lock-type-face nil nil t nil t)
247 '(font-lock-reference-face nil nil t nil t)))
248 ((memq font-lock-display-type '(grayscale greyscale
249 grayshade greyshade))
251 (list 'font-lock-comment-face
252 (if light-bg "DimGray" "Gray80") nil t t nil)
253 (list 'font-lock-string-face
254 (if light-bg "Gray50" "LightGray") nil nil t nil)
255 (list 'font-lock-keyword-face
256 (if light-bg "DimGray" "Gray90") nil t nil nil)
257 (list 'font-lock-function-name-face
258 (cdr (assq 'background-color (frame-parameters)))
259 (cdr (assq 'foreground-color (frame-parameters)))
261 (list 'font-lock-variable-name-face
262 (if light-bg "DimGray" "Gray90") nil t t nil)
263 (list 'font-lock-type-face
264 (if light-bg "DimGray" "Gray80") nil t nil t)))
265 (light-bg ; light colour background
266 '((font-lock-comment-face "Firebrick")
267 (font-lock-string-face "RosyBrown")
268 (font-lock-keyword-face "Purple")
269 (font-lock-function-name-face "Blue")
270 (font-lock-variable-name-face "DarkGoldenrod")
271 (font-lock-type-face "DarkOliveGreen")
272 (font-lock-reference-face "CadetBlue")))
273 (t ; dark colour background
274 '((font-lock-comment-face "OrangeRed")
275 (font-lock-string-face "LightSalmon")
276 (font-lock-keyword-face "LightSteelBlue")
277 (font-lock-function-name-face "LightSkyBlue")
278 (font-lock-variable-name-face "LightGoldenrod")
279 (font-lock-type-face "PaleGreen")
280 (font-lock-reference-face "Aquamarine")))))))
281 (mapcar 'font-lock-make-face font-lock-face-attributes))
283 (defun font-lock-make-face (face-attributes)
284 "Make a face from FACE-ATTRIBUTES.
285 FACE-ATTRIBUTES should be like an element `font-lock-face-attributes', so that
286 the face name is the first item in the list. A variable with the same name as
287 the face is also set; its value is the face name."
288 (let* ((face (nth 0 face-attributes))
289 (face-name (symbol-name face))
290 (set-p (function (lambda (face-name resource)
291 (x-get-resource (concat face-name ".attribute" resource)
292 (concat "Face.Attribute" resource)))))
293 (on-p (function (lambda (face-name resource)
294 (let ((set (funcall set-p face-name resource)))
295 (and set (member (downcase set) '("on" "true"))))))))
297 ;; Set attributes not set from X resources (and therefore `make-face').
298 (or (funcall set-p face-name "Foreground")
300 (set-face-foreground face (nth 1 face-attributes))
302 (or (funcall set-p face-name "Background")
304 (set-face-background face (nth 2 face-attributes))
306 (if (funcall set-p face-name "Bold")
307 (and (funcall on-p face-name "Bold") (make-face-bold face nil t))
308 (and (nth 3 face-attributes) (make-face-bold face nil t)))
309 (if (funcall set-p face-name "Italic")
310 (and (funcall on-p face-name "Italic") (make-face-italic face nil t))
311 (and (nth 4 face-attributes) (make-face-italic face nil t)))
312 (or (funcall set-p face-name "Underline")
313 (set-face-underline-p face (nth 5 face-attributes)))
318 ;; These variables record, for each buffer, the parse state at a particular
319 ;; position, always the start of a line. Used to make font-lock-fontify-region
321 (defvar font-lock-cache-position nil)
322 (defvar font-lock-cache-state nil)
323 (make-variable-buffer-local 'font-lock-cache-position)
324 (make-variable-buffer-local 'font-lock-cache-state)
326 (defun font-lock-fontify-region (start end &optional loudly)
327 "Put proper face on each string and comment between START and END."
333 (if loudly (message "Fontifying %s... (syntactically...)" (buffer-name)))
334 (let ((buffer-read-only nil)
335 (modified (buffer-modified-p))
336 (cstart (if comment-start-skip
337 (concat "\\s\"\\|" comment-start-skip)
339 (cend (if comment-end
340 (concat "\\s>\\|" (regexp-quote comment-end))
343 state prev prevstate)
344 ;; Find the state at the line-beginning before START.
345 (if (eq startline font-lock-cache-position)
346 (setq state font-lock-cache-state)
347 ;; Find outermost containing sexp.
349 ;; Find the state at STARTLINE.
350 (while (< (point) startline)
351 (setq state (parse-partial-sexp (point) startline 0)))
352 (setq font-lock-cache-state state
353 font-lock-cache-position (point)))
354 ;; Now find the state precisely at START.
355 (setq state (parse-partial-sexp (point) start nil nil state))
356 ;; If the region starts inside a string, show the extent of it.
359 (while (and (re-search-forward "\\s\"" end 'move)
360 (nth 3 (parse-partial-sexp beg (point) nil nil
362 (put-text-property beg (point) 'face font-lock-string-face)
363 (setq state (parse-partial-sexp beg (point) nil nil state))))
364 ;; Likewise for a comment.
365 (if (or (nth 4 state) (nth 7 state))
367 (while (and (re-search-forward cend end 'move)
368 (nth 3 (parse-partial-sexp beg (point) nil nil
370 (put-text-property beg (point) 'face font-lock-comment-face)
371 (setq state (parse-partial-sexp beg (point) nil nil state))))
372 ;; Find each interesting place between here and END.
373 (while (and (< (point) end)
374 (setq prev (point) prevstate state)
375 (re-search-forward cstart end t)
377 ;; Clear out the fonts of what we skip over.
378 (remove-text-properties prev (point) '(face nil))
379 ;; Verify the state at that place
380 ;; so we don't get fooled by \" or \;.
381 (setq state (parse-partial-sexp prev (point) nil nil
383 (let ((here (point)))
384 (if (or (nth 4 state) (nth 7 state))
385 ;; We found a real comment start.
386 (let ((beg (match-beginning 0)))
389 (narrow-to-region (point-min) end)
393 ;; forward-comment skips all whitespace,
394 ;; so go back to the real end of the comment.
395 (skip-chars-backward " \t"))
396 (error (goto-char end))))
397 (put-text-property beg (point) 'face font-lock-comment-face)
398 (setq state (parse-partial-sexp here (point) nil nil state)))
400 (let ((beg (match-beginning 0)))
401 (while (and (re-search-forward "\\s\"" end 'move)
402 (nth 3 (parse-partial-sexp here (point) nil nil
404 (put-text-property beg (point) 'face font-lock-string-face)
405 (setq state (parse-partial-sexp here (point) nil nil
407 ;; Make sure PREV is non-nil after the loop
408 ;; only if it was set on the very last iteration.
411 (remove-text-properties prev end '(face nil)))
412 (and (buffer-modified-p)
414 (set-buffer-modified-p nil))))))
416 ;; This code used to be used to show a string on reaching the end of it.
417 ;; It is probably not needed due to later changes to handle strings
418 ;; starting before the region in question.
419 ;; (if (and (null (nth 3 state))
420 ;; (eq (char-syntax (preceding-char)) ?\")
422 ;; (nth 3 (parse-partial-sexp prev (1- (point))
423 ;; nil nil prevstate))))
424 ;; ;; We found the end of a string.
426 ;; (setq foo2 (point))
427 ;; (let ((ept (point)))
429 ;; ;; Highlight the string when we see the end.
430 ;; ;; Doing it at the start leads to trouble:
431 ;; ;; either it fails to handle multiline strings
432 ;; ;; or it can run away when an unmatched " is inserted.
433 ;; (put-text-property (point) ept 'face
434 ;; (if (= (car state) 1)
435 ;; font-lock-doc-string-face
436 ;; font-lock-string-face)))))
438 (defun font-lock-unfontify-region (beg end)
439 (let ((modified (buffer-modified-p))
440 (buffer-read-only nil))
441 (remove-text-properties beg end '(face nil))
442 (set-buffer-modified-p modified)))
444 ;; Called when any modification is made to buffer text.
445 (defun font-lock-after-change-function (beg end old-len)
448 ;; Discard the cache info if text before it has changed.
449 (and font-lock-cache-position
450 (> font-lock-cache-position beg)
451 (setq font-lock-cache-position nil))
452 ;; Rescan between start of line from `beg' and start of line after `end'.
459 ;; First scan for strings and comments.
460 ;; Must scan from line start in case of
461 ;; inserting space into `intfoo () {}', and after widened.
462 (if font-lock-no-comments
463 (remove-text-properties beg end '(face nil))
464 (font-lock-fontify-region beg end))
465 ;; Now scan for keywords.
466 (font-lock-hack-keywords beg end))))
468 ;;; Fontifying arbitrary patterns
470 (defun font-lock-hack-keywords (start end &optional loudly)
471 "Fontify according to `font-lock-keywords' between START and END."
472 (let ((case-fold-search font-lock-keywords-case-fold-search)
473 (keywords font-lock-keywords)
475 (buffer-read-only nil)
476 (modified (buffer-modified-p))
477 (old-syntax (syntax-table))
478 (bufname (buffer-name)))
480 (let (keyword regexp match highlights hs h s e)
481 (if loudly (message "Fontifying %s... (regexps...)" bufname))
482 (if font-lock-syntax-table (set-syntax-table font-lock-syntax-table))
484 (setq keyword (car keywords) keywords (cdr keywords)
485 regexp (if (stringp keyword) keyword (car keyword))
486 highlights (cond ((stringp keyword)
487 '((0 font-lock-keyword-face)))
488 ((numberp (cdr keyword))
489 (list (list (cdr keyword)
490 'font-lock-keyword-face)))
491 ((symbolp (cdr keyword))
492 (list (list 0 (cdr keyword))))
493 ((nlistp (nth 1 keyword))
494 (list (cdr keyword)))
498 (while (re-search-forward regexp end t)
501 (setq h (car hs) match (nth 0 h)
502 s (match-beginning match) e (match-end match)
505 ;; No match but we might not signal an error
507 (error "No subexpression %d in expression %d"
509 ((and (not (nth 2 h))
510 (text-property-not-all s e 'face nil))
511 ;; Can't override and already fontified
513 ((not (eq (nth 2 h) 'keep))
514 ;; Can override but need not keep existing fontification
515 (put-text-property s e 'face (eval (nth 1 h))))
517 ;; Can override but must keep existing fontification
518 ;; (Does anyone use this? sm.)
519 (let ((p (text-property-any s e 'face nil)) n
520 (face (eval (nth 1 h))))
522 (setq n (next-single-property-change p 'face nil e))
523 (put-text-property p n 'face face)
524 (setq p (text-property-any n e 'face nil))))))))
525 ;; the above form was:
528 ; (while (< (point) e)
529 ; (let ((next (next-single-property-change (point) 'face
531 ; (if (or (null next) (> next e))
533 ; (if (not (get-text-property (point) 'face))
534 ; (put-text-property (point) next 'face face))
535 ; (goto-char next))))
537 (if loudly (message "Fontifying %s... (regexps...%s)" bufname
538 (make-string (setq count (1+ count)) ?.)))))
539 (set-syntax-table old-syntax))
540 (and (buffer-modified-p)
542 (set-buffer-modified-p nil))))
544 ;; The user level functions
546 (defvar font-lock-mode nil) ; for modeline
548 (defvar font-lock-fontified nil) ; whether we have hacked this buffer
549 (put 'font-lock-fontified 'permanent-local t)
552 (defun font-lock-mode (&optional arg)
553 "Toggle Font Lock mode.
554 With arg, turn Font Lock mode on if and only if arg is positive.
556 When Font Lock mode is enabled, text is fontified as you type it:
558 - Comments are displayed in `font-lock-comment-face';
559 - Strings are displayed in `font-lock-string-face';
560 - Certain other expressions are displayed in other faces according to the
561 value of the variable `font-lock-keywords'.
563 You can enable Font Lock mode in any major mode automatically by turning on in
564 the major mode's hook. For example, put in your ~/.emacs:
566 (add-hook 'c-mode-hook 'turn-on-font-lock)
568 Or for any visited file with the following in your ~/.emacs:
570 (add-hook 'find-file-hooks 'turn-on-font-lock)
572 The default Font Lock mode faces and their attributes are defined in the
573 variable `font-lock-face-attributes', and Font Lock mode default settings in
574 the variable `font-lock-defaults-alist'.
576 When you turn Font Lock mode on/off the buffer is fontified/defontified, though
577 fontification occurs only if the buffer is less than `font-lock-maximum-size'.
578 To fontify a buffer without turning on Font Lock mode, and regardless of buffer
579 size, you can use \\[font-lock-fontify-buffer]."
581 (let ((on-p (if arg (> (prefix-numeric-value arg) 0) (not font-lock-mode))))
582 (if (equal (buffer-name) " *Compiler Input*") ; hack for bytecomp...
585 (remove-hook 'after-change-functions 'font-lock-after-change-function)
586 (make-local-variable 'after-change-functions)
587 (add-hook 'after-change-functions 'font-lock-after-change-function))
588 (set (make-local-variable 'font-lock-mode) on-p)
590 (font-lock-set-defaults)
591 (make-local-variable 'before-revert-hook)
592 (make-local-variable 'after-revert-hook)
593 ;; If buffer is reverted, must clean up the state.
594 (add-hook 'before-revert-hook 'font-lock-revert-setup)
595 (add-hook 'after-revert-hook 'font-lock-revert-cleanup)
596 (run-hooks 'font-lock-mode-hook)
597 (cond (font-lock-fontified
599 ((or (null font-lock-maximum-size)
600 (> font-lock-maximum-size (buffer-size)))
601 (font-lock-fontify-buffer))
603 (message "Fontifying %s... buffer too big." (buffer-name)))))
605 (setq font-lock-fontified nil)
606 (remove-hook 'before-revert-hook 'font-lock-revert-setup)
607 (remove-hook 'after-revert-hook 'font-lock-revert-cleanup)
608 (font-lock-unfontify-region (point-min) (point-max))))
609 (force-mode-line-update)))
612 (defun turn-on-font-lock ()
613 "Unconditionally turn on Font Lock mode."
616 ;; If the buffer is about to be reverted, it won't be fontified.
617 (defun font-lock-revert-setup ()
618 (setq font-lock-fontified nil))
620 ;; If the buffer has just been reverted, we might not even be in font-lock
621 ;; mode anymore, and if we are, the buffer may or may not have already been
622 ;; refontified. Refontify here if it looks like we need to.
623 (defun font-lock-revert-cleanup ()
625 (not font-lock-fontified)
629 (defun font-lock-fontify-buffer ()
630 "Fontify the current buffer the way `font-lock-mode' would."
632 (let ((was-on font-lock-mode)
633 (verbose (or font-lock-verbose (interactive-p)))
634 (modified (buffer-modified-p)))
635 (set (make-local-variable 'font-lock-fontified) nil)
636 (if verbose (message "Fontifying %s..." (buffer-name)))
637 ;; Turn it on to run hooks and get the right `font-lock-keywords' etc.
638 (or was-on (font-lock-set-defaults))
641 (font-lock-unfontify-region (point-min) (point-max))
642 (if (not font-lock-no-comments)
643 (font-lock-fontify-region (point-min) (point-max) verbose))
644 (font-lock-hack-keywords (point-min) (point-max) verbose)
645 (setq font-lock-fontified t))
646 ;; We don't restore the old fontification, so it's best to unfontify.
647 (quit (font-lock-unfontify-region (point-min) (point-max))))
648 (if verbose (message "Fontifying %s... %s." (buffer-name)
649 (if font-lock-fontified "done" "aborted")))
650 (and (buffer-modified-p)
652 (set-buffer-modified-p nil))))
655 ;;; Various information shared by several modes.
656 ;;; Information specific to a single mode should go in its load library.
658 (defconst lisp-font-lock-keywords-1
660 ;; highlight defining forms. This doesn't work too nicely for
661 ;; (defun (setf foo) ...) but it does work for (defvar foo) which
662 ;; is more important.
663 (list (concat "^(\\(def\\(const\\|ine-key\\(\\|-after\\)\\|var\\)\\)\\>"
664 "\\s *\\([^ \t\n\)]+\\)?")
665 '(1 font-lock-keyword-face) '(4 font-lock-variable-name-face nil t))
666 (list (concat "^(\\(def\\(a\\(dvice\\|lias\\)\\|macro\\|subst\\|un\\)\\)\\>"
667 "\\s *\\([^ \t\n\)]+\\)?")
668 '(1 font-lock-keyword-face) '(4 font-lock-function-name-face nil t))
670 ;; this is highlights things like (def* (setf foo) (bar baz)), but may
671 ;; be slower (I haven't really thought about it)
672 ; ("^(def[-a-z]+\\s +\\(\\s(\\S)*\\s)\\|\\S(\\S *\\)"
673 ; 1 font-lock-function-name-face)
675 "For consideration as a value of `lisp-font-lock-keywords'.
676 This does fairly subdued highlighting.")
678 (defconst lisp-font-lock-keywords-2
680 lisp-font-lock-keywords-1
683 ;; Control structures.
685 ; ("cond" "if" "while" "let\\*?" "prog[nv12*]?" "catch" "throw"
686 ; "save-restriction" "save-excursion"
687 ; "save-window-excursion" "save-match-data" "unwind-protect"
688 ; "condition-case" "track-mouse")
691 "c\\(atch\\|ond\\(\\|ition-case\\)\\)\\|if\\|let\\*?\\|prog[nv12*]?\\|"
692 "save-\\(excursion\\|match-data\\|restriction\\|window-excursion\\)\\|"
693 "t\\(hrow\\|rack-mouse\\)\\|unwind-protect\\|while"
696 ; ("when" "unless" "do" "flet" "labels" "return" "return-from")
697 '("(\\(do\\|flet\\|labels\\|return\\(\\|-from\\)\\|unless\\|when\\)[ \t\n]"
700 ;; Fontify CLisp keywords.
701 '("\\s :\\([-a-zA-Z0-9]+\\)\\>" . 1)
703 ;; Function names in emacs-lisp docstrings (in the syntax that
704 ;; substitute-command-keys understands.)
705 '("\\\\\\\\\\[\\([^]\\\n]+\\)]" 1 font-lock-reference-face t)
707 ;; Words inside `' which tend to be function names
708 (let ((word-char "[-+a-zA-Z0-9_.*]"))
709 (list (concat "`\\(" word-char word-char "+\\)'")
710 1 'font-lock-reference-face t))
712 ;; & keywords as types
713 '("\\&\\(optional\\|rest\\)\\>" . font-lock-type-face)
715 "For consideration as a value of `lisp-font-lock-keywords'.
716 This does a lot more highlighting.")
718 ;; default to the gaudier variety?
719 ;(defvar lisp-font-lock-keywords lisp-font-lock-keywords-2
720 ; "Additional expressions to highlight in Lisp modes.")
721 (defvar lisp-font-lock-keywords lisp-font-lock-keywords-1
722 "Additional expressions to highlight in Lisp modes.")
725 (defconst c-font-lock-keywords-1 nil
726 "For consideration as a value of `c-font-lock-keywords'.
727 This does fairly subdued highlighting.")
729 (defconst c-font-lock-keywords-2 nil
730 "For consideration as a value of `c-font-lock-keywords'.
731 This does a lot more highlighting.")
733 (defconst c++-font-lock-keywords-1 nil
734 "For consideration as a value of `c++-font-lock-keywords'.
735 This does fairly subdued highlighting.")
737 (defconst c++-font-lock-keywords-2 nil
738 "For consideration as a value of `c++-font-lock-keywords'.
739 This does a lot more highlighting.")
742 ; ("break" "continue" "do" "else" "for" "if" "return" "switch" "while")
743 "break\\|continue\\|do\\|else\\|for\\|if\\|return\\|switch\\|while")
745 ; ("auto" "extern" "register" "static" "typedef" "struct" "union" "enum"
746 ; "signed" "unsigned" "short" "long" "int" "char" "float" "double"
747 ; "void" "volatile" "const")
748 (concat "auto\\|c\\(har\\|onst\\)\\|double\\|e\\(num\\|xtern\\)\\|"
749 "float\\|int\\|long\\|register\\|"
750 "s\\(hort\\|igned\\|t\\(atic\\|ruct\\)\\)\\|typedef\\|"
751 "un\\(ion\\|signed\\)\\|vo\\(id\\|latile\\)")) ; 6 ()s deep.
753 ; ("break" "continue" "do" "else" "for" "if" "return" "switch" "while"
754 ; "asm" "catch" "delete" "new" "operator" "sizeof" "this" "throw" "try"
755 ; "protected" "private" "public")
756 (concat "asm\\|break\\|c\\(atch\\|ontinue\\)\\|d\\(elete\\|o\\)\\|"
757 "else\\|for\\|if\\|new\\|operator\\|"
758 "p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|return\\|"
759 "s\\(izeof\\|witch\\)\\|t\\(h\\(is\\|row\\)\\|ry\\)\\|while"))
761 ; ("auto" "extern" "register" "static" "typedef" "struct" "union" "enum"
762 ; "signed" "unsigned" "short" "long" "int" "char" "float" "double"
763 ; "void" "volatile" "const" "class" "inline" "friend" "bool"
764 ; "virtual" "complex" "template")
765 (concat "auto\\|bool\\|c\\(har\\|lass\\|o\\(mplex\\|nst\\)\\)\\|"
766 "double\\|e\\(num\\|xtern\\)\\|f\\(loat\\|riend\\)\\|"
767 "in\\(line\\|t\\)\\|long\\|register\\|"
768 "s\\(hort\\|igned\\|t\\(atic\\|ruct\\)\\)\\|"
769 "t\\(emplate\\|ypedef\\)\\|un\\(ion\\|signed\\)\\|"
770 "v\\(irtual\\|o\\(id\\|latile\\)\\)")) ; 11 ()s deep.
771 (ctoken "[a-zA-Z0-9_:~]+"))
772 (setq c-font-lock-keywords-1
775 ;; Fontify filenames in #include <...> preprocessor directives.
776 '("^#[ \t]*include[ \t]+\\(<[^>\"\n]+>\\)" 1 font-lock-string-face)
778 ;; Fontify function macro names.
779 '("^#[ \t]*define[ \t]+\\(\\(\\sw+\\)(\\)" 2 font-lock-function-name-face)
781 ;; Fontify otherwise as symbol names, and the preprocessor directive names.
782 '("^\\(#[ \t]*[a-z]+\\)\\>[ \t]*\\(\\sw+\\)?"
783 (1 font-lock-reference-face) (2 font-lock-variable-name-face nil t))
785 ;; Fontify function name definitions (without type on line).
786 (list (concat "^\\(" ctoken "\\)[ \t]*(") 1 'font-lock-function-name-face)
789 (setq c-font-lock-keywords-2
790 (append c-font-lock-keywords-1
793 ;; Fontify all storage classes and type specifiers (before declarations).
794 (cons (concat "\\<\\(" c-type-types "\\)\\>") 'font-lock-type-face)
796 ;; Fontify variable/structure name declarations and definitions, or
797 ;; function name declarations (plus definitions with type on same line).
798 (list (concat "\\<\\(" c-type-types "\\)[ \t*]+"
799 "\\(" ctoken "[ \t*]+\\)*"
800 "\\(" ctoken "\\)[ \t]*\\((\\)?")
802 '(if (match-beginning 10)
803 font-lock-function-name-face
804 font-lock-variable-name-face))
806 ;; Fontify function/variable name declarations at the start of the line.
807 ;; (Not everyone follows the GNU convention of function name at the start.)
808 (list (concat "^" ctoken "[ \t*]+"
809 "\\(" ctoken "[ \t*]+\\)*"
810 "\\(" ctoken "\\)[ \t]*\\((\\)?")
812 '(if (match-beginning 3)
813 font-lock-function-name-face
814 font-lock-variable-name-face))
816 ;; Fontify variable names declared with structures, or typedef names.
817 '("}[ \t*]*\\(\\sw+\\)[ \t]*[;,[]" 1 font-lock-variable-name-face)
819 ;; Fontify all builtin keywords (except case, default and goto; see below).
820 (concat "\\<\\(" c-keywords "\\)\\>")
822 ;; Fontify case/goto keywords and targets, and goto tags (incl "default:").
823 '("\\<\\(case\\|goto\\)\\>[ \t]*\\([^ \t\n:;]+\\)?"
824 (1 font-lock-keyword-face) (2 font-lock-reference-face nil t))
825 '("^[ \t]*\\(\\sw+\\)[ \t]*:" 1 font-lock-reference-face)
828 (setq c++-font-lock-keywords-1 c-font-lock-keywords-1)
829 (setq c++-font-lock-keywords-2
830 (append c++-font-lock-keywords-1
832 ;; We don't just add to the C keywords for subtle differences and speed.
833 ;; See the above comments for `c-font-lock-keywords-2'.
834 (cons (concat "\\<\\(" c++-type-types "\\)\\>") 'font-lock-type-face)
835 (list (concat "\\<\\(" c++-type-types "\\)[ \t*&]+"
836 "\\(" ctoken "[ \t*&]+\\)*"
837 "\\(" ctoken "\\)[ \t]*\\((\\)?")
839 '(if (match-beginning 15)
840 font-lock-function-name-face
841 font-lock-variable-name-face))
842 (list (concat "^" ctoken "[ \t*]+"
843 "\\(" ctoken "[ \t*]+\\)*"
844 "\\(" ctoken "\\)[ \t]*\\((\\)?")
846 '(if (match-beginning 3)
847 font-lock-function-name-face
848 font-lock-variable-name-face))
849 '("}[ \t*]*\\(\\sw+\\)[ \t]*[;,[]" 1 font-lock-variable-name-face)
850 (concat "\\<\\(" c++-keywords "\\)\\>")
851 '("\\<\\(case\\|goto\\)\\>[ \t]*\\([^ \t\n:;]+\\)?"
852 (1 font-lock-keyword-face) (2 font-lock-reference-face nil t))
853 '("^[ \t]*\\(\\sw+\\)[ \t]*:[^:]" 1 font-lock-reference-face))))
856 ; default to the gaudier variety?
857 (defvar c-font-lock-keywords c-font-lock-keywords-1
858 "Additional expressions to highlight in C mode.")
860 (defvar c++-font-lock-keywords c++-font-lock-keywords-1
861 "Additional expressions to highlight in C++ mode.")
863 (defvar tex-font-lock-keywords
865 '("\\(\\\\\\([a-zA-Z@]+\\|.\\)\\)" 1 font-lock-keyword-face t)
866 '("{\\\\em\\([^}]+\\)}" 1 font-lock-comment-face t)
867 '("{\\\\bf\\([^}]+\\)}" 1 font-lock-keyword-face t)
868 '("^[ \t\n]*\\\\def[\\\\@]\\(\\w+\\)" 1 font-lock-function-name-face t)
869 '("\\\\\\(begin\\|end\\){\\([a-zA-Z0-9\\*]+\\)}"
870 2 font-lock-function-name-face t)
871 '("[^\\\\]\\$\\([^$]*\\)\\$" 1 font-lock-string-face t)
872 ; '("\\$\\([^$]*\\)\\$" 1 font-lock-string-face t)
874 "Additional expressions to highlight in TeX mode.")
876 ;; There is no html-mode.el shipped with Emacs; `font-lock-defaults' entry
877 ; would be: (html-font-lock-keywords nil t)
878 ;(defconst html-font-lock-keywords
879 ; '(("<!--[^>]*>" 0 font-lock-comment-face t) ; Comment.
880 ; ("</?\\sw+" . font-lock-type-face) ; Normal tag start.
881 ; (">" . font-lock-type-face) ; Normal tag end.
882 ; ("<\\(/?\\(a\\|form\\|img\\|input\\)\\)\\>" ; Special tag name.
883 ; 1 font-lock-function-name-face t)
884 ; ("\\<\\(\\sw+\\)[>=]" 1 font-lock-keyword-face)) ; Tag attribute.
885 ; "Additional expressions to highlight in HTML mode.")
887 (defun font-lock-set-defaults ()
888 "Set fontification defaults appropriately for this mode.
889 Sets `font-lock-keywords', `font-lock-no-comments', `font-lock-syntax-table'
890 and `font-lock-keywords-case-fold-search' using `font-lock-defaults-alist'."
891 (or font-lock-keywords ; if not already set.
892 (let ((defaults (or font-lock-defaults
893 (cdr (assq major-mode font-lock-defaults-alist)))))
895 (setq font-lock-keywords (eval (nth 0 defaults)))
898 (set (make-local-variable 'font-lock-no-comments) t))
901 (set (make-local-variable 'font-lock-keywords-case-fold-search) t))
904 (let ((slist (nth 3 defaults)))
905 (make-local-variable 'font-lock-syntax-table)
906 (setq font-lock-syntax-table (copy-syntax-table (syntax-table)))
908 (modify-syntax-entry (car (car slist)) (cdr (car slist))
909 font-lock-syntax-table)
910 (setq slist (cdr slist))))))))
912 ;; Install ourselves:
915 (add-hook 'after-init-hook 'font-lock-make-faces)
916 (font-lock-make-faces))
918 (or (assq 'font-lock-mode minor-mode-alist)
919 (setq minor-mode-alist (cons '(font-lock-mode " Font") minor-mode-alist)))
921 ;; Provide ourselves:
925 ;;; font-lock.el ends here