]> code.delx.au - gnu-emacs/blob - lisp/font-lock.el
* font-lock.el: To make font-lock.el dumpable: (font-lock-display-type,
[gnu-emacs] / lisp / font-lock.el
1 ;; Electric Font Lock Mode
2 ;; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
3
4 ;; Author: jwz, then rms and sm (simon.marshall@mail.esrin.esa.it)
5 ;; Maintainer: FSF
6 ;; Keywords: languages, faces
7
8 ;; This file is part of GNU Emacs.
9
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)
13 ;; any later version.
14
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.
19
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.
23
24
25 ;;; Commentary:
26
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.
29 ;;
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.
33 ;;
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.
37 ;;
38 ;; To turn Font Lock mode on automatically, add this to your .emacs file:
39 ;;
40 ;; (add-hook 'emacs-lisp-mode-hook 'turn-on-font-lock)
41 ;;
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
48 ;; to be as hairy.
49 ;;
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':
53 ;;
54 ;; (add-hook 'foo-mode-hook
55 ;; '(lambda () (make-local-variable 'font-lock-defaults)
56 ;; (setq font-lock-defaults '(foo-font-lock-keywords t))))
57 ;;
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.
62 \f
63 ;;; Code:
64
65 (defvar font-lock-comment-face 'font-lock-comment-face
66 "Face to use for comments.")
67
68 (defvar font-lock-string-face 'font-lock-string-face
69 "Face to use for strings.")
70
71 (defvar font-lock-function-name-face 'font-lock-function-name-face
72 "Face to use for function names.")
73
74 (defvar font-lock-variable-name-face 'font-lock-variable-name-face
75 "Face to use for variable names.")
76
77 (defvar font-lock-keyword-face 'font-lock-keyword-face
78 "Face to use for keywords.")
79
80 (defvar font-lock-type-face 'font-lock-type-face
81 "Face to use for data types.")
82
83 (defvar font-lock-reference-face 'font-lock-reference-face
84 "Face to use for references.")
85
86 (defvar font-lock-no-comments nil
87 "Non-nil means Font Lock should not fontify comments or strings.")
88
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:
93
94 REGEXP
95 (REGEXP . MATCH)
96 (REGEXP . FACENAME)
97 (REGEXP . HIGHLIGHT)
98 (REGEXP HIGHLIGHT ...)
99
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'.
104
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.
108
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.
112
113 Be careful composing regexps for this list;
114 the wrong pattern can dramatically slow things down!")
115
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'.")
119
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.")
139
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.")
144
145 (defvar font-lock-keywords-case-fold-search nil
146 "*Non-nil means the patterns in `font-lock-keywords' are case-insensitive.")
147
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.")
151
152 (defvar font-lock-verbose t
153 "*Non-nil means `font-lock-fontify-buffer' should print status messages.")
154
155 ;;;###autoload
156 (defvar font-lock-mode-hook nil
157 "Function or functions to run on entry to Font Lock mode.")
158 \f
159 ;; Colour etc. support.
160
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'.")
167
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
173 `~/.Xdefaults'.
174 See also `font-lock-display-type' and `font-lock-face-attributes'.")
175
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
179
180 (FACE FOREGROUND BACKGROUND BOLD-P ITALIC-P UNDERLINE-P)
181
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'.
188
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).
193
194 Emacs uses default attributes based on display type and background brightness.
195 See variables `font-lock-display-type' and `font-lock-background-mode'.
196
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'.")
200
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"
210 "DisplayType")))
211 (cond (display-resource (intern (downcase display-resource)))
212 ((x-display-color-p) 'color)
213 ((x-display-grayscale-p) 'grayscale)
214 (t 'mono)))))
215 (if (null font-lock-background-mode)
216 (setq font-lock-background-mode
217 (let ((bg-resource (x-get-resource ".backgroundMode"
218 "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)))))
225 'dark)
226 (t 'light)))))
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)
240 (list
241 'font-lock-function-name-face
242 (cdr (assq 'background-color (frame-parameters)))
243 (cdr (assq 'foreground-color (frame-parameters)))
244 t nil nil)
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))
250 (list
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)))
260 t nil nil)
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))
282
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"))))))))
296 (make-face face)
297 ;; Set attributes not set from X resources (and therefore `make-face').
298 (or (funcall set-p face-name "Foreground")
299 (condition-case nil
300 (set-face-foreground face (nth 1 face-attributes))
301 (error nil)))
302 (or (funcall set-p face-name "Background")
303 (condition-case nil
304 (set-face-background face (nth 2 face-attributes))
305 (error nil)))
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)))
314 (set face face)))
315 \f
316 ;; Fontification.
317
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
320 ;; faster.
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)
325
326 (defun font-lock-fontify-region (start end &optional loudly)
327 "Put proper face on each string and comment between START and END."
328 (save-excursion
329 (save-restriction
330 (widen)
331 (goto-char start)
332 (beginning-of-line)
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)
338 "\\s\""))
339 (cend (if comment-end
340 (concat "\\s>\\|" (regexp-quote comment-end))
341 "\\s>"))
342 (startline (point))
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.
348 (beginning-of-defun)
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.
357 (if (nth 3 state)
358 (let ((beg (point)))
359 (while (and (re-search-forward "\\s\"" end 'move)
360 (nth 3 (parse-partial-sexp beg (point) nil nil
361 state))))
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))
366 (let ((beg (point)))
367 (while (and (re-search-forward cend end 'move)
368 (nth 3 (parse-partial-sexp beg (point) nil nil
369 state))))
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)
376 (progn
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
382 state))))
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)))
387 (goto-char beg)
388 (save-restriction
389 (narrow-to-region (point-min) end)
390 (condition-case nil
391 (progn
392 (forward-comment 1)
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)))
399 (if (nth 3 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
403 state))))
404 (put-text-property beg (point) 'face font-lock-string-face)
405 (setq state (parse-partial-sexp here (point) nil nil
406 state))))))
407 ;; Make sure PREV is non-nil after the loop
408 ;; only if it was set on the very last iteration.
409 (setq prev nil))
410 (and prev
411 (remove-text-properties prev end '(face nil)))
412 (and (buffer-modified-p)
413 (not modified)
414 (set-buffer-modified-p nil))))))
415
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)) ?\")
421 ;; (save-excursion
422 ;; (nth 3 (parse-partial-sexp prev (1- (point))
423 ;; nil nil prevstate))))
424 ;; ;; We found the end of a string.
425 ;; (save-excursion
426 ;; (setq foo2 (point))
427 ;; (let ((ept (point)))
428 ;; (forward-sexp -1)
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)))))
437
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)))
443
444 ;; Called when any modification is made to buffer text.
445 (defun font-lock-after-change-function (beg end old-len)
446 (save-excursion
447 (save-match-data
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'.
453 (goto-char beg)
454 (beginning-of-line)
455 (setq beg (point))
456 (goto-char end)
457 (forward-line 1)
458 (setq end (point))
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))))
467 \f
468 ;;; Fontifying arbitrary patterns
469
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)
474 (count 0)
475 (buffer-read-only nil)
476 (modified (buffer-modified-p))
477 (old-syntax (syntax-table))
478 (bufname (buffer-name)))
479 (unwind-protect
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))
483 (while keywords
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)))
495 (t
496 (cdr keyword))))
497 (goto-char start)
498 (while (re-search-forward regexp end t)
499 (setq hs highlights)
500 (while hs
501 (setq h (car hs) match (nth 0 h)
502 s (match-beginning match) e (match-end match)
503 hs (cdr hs))
504 (cond ((not s)
505 ;; No match but we might not signal an error
506 (or (nth 3 h)
507 (error "No subexpression %d in expression %d"
508 match (1+ count))))
509 ((and (not (nth 2 h))
510 (text-property-not-all s e 'face nil))
511 ;; Can't override and already fontified
512 nil)
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))))
516 (t
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))))
521 (while p
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:
526 ; (save-excursion
527 ; (goto-char s)
528 ; (while (< (point) e)
529 ; (let ((next (next-single-property-change (point) 'face
530 ; nil e)))
531 ; (if (or (null next) (> next e))
532 ; (setq next e))
533 ; (if (not (get-text-property (point) 'face))
534 ; (put-text-property (point) next 'face face))
535 ; (goto-char next))))
536
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)
541 (not modified)
542 (set-buffer-modified-p nil))))
543 \f
544 ;; The user level functions
545
546 (defvar font-lock-mode nil) ; for modeline
547
548 (defvar font-lock-fontified nil) ; whether we have hacked this buffer
549 (put 'font-lock-fontified 'permanent-local t)
550
551 ;;;###autoload
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.
555
556 When Font Lock mode is enabled, text is fontified as you type it:
557
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'.
562
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:
565
566 (add-hook 'c-mode-hook 'turn-on-font-lock)
567
568 Or for any visited file with the following in your ~/.emacs:
569
570 (add-hook 'find-file-hooks 'turn-on-font-lock)
571
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'.
575
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]."
580 (interactive "P")
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...
583 (setq on-p nil))
584 (if (not on-p)
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)
589 (cond (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
598 nil)
599 ((or (null font-lock-maximum-size)
600 (> font-lock-maximum-size (buffer-size)))
601 (font-lock-fontify-buffer))
602 (font-lock-verbose
603 (message "Fontifying %s... buffer too big." (buffer-name)))))
604 (font-lock-fontified
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)))
610
611 ;;;###autoload
612 (defun turn-on-font-lock ()
613 "Unconditionally turn on Font Lock mode."
614 (font-lock-mode 1))
615
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))
619
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 ()
624 (and font-lock-mode
625 (not font-lock-fontified)
626 (font-lock-mode 1)))
627
628 ;;;###autoload
629 (defun font-lock-fontify-buffer ()
630 "Fontify the current buffer the way `font-lock-mode' would."
631 (interactive)
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))
639 (condition-case nil
640 (save-excursion
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)
651 (not modified)
652 (set-buffer-modified-p nil))))
653
654 \f
655 ;;; Various information shared by several modes.
656 ;;; Information specific to a single mode should go in its load library.
657
658 (defconst lisp-font-lock-keywords-1
659 (list
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))
669 ;;
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)
674 )
675 "For consideration as a value of `lisp-font-lock-keywords'.
676 This does fairly subdued highlighting.")
677
678 (defconst lisp-font-lock-keywords-2
679 (append
680 lisp-font-lock-keywords-1
681 (list
682 ;;
683 ;; Control structures.
684 ;; ELisp:
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")
689 (cons
690 (concat "(\\("
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"
694 "\\)[ \t\n]") 1)
695 ;; CLisp:
696 ; ("when" "unless" "do" "flet" "labels" "return" "return-from")
697 '("(\\(do\\|flet\\|labels\\|return\\(\\|-from\\)\\|unless\\|when\\)[ \t\n]"
698 . 1)
699 ;;
700 ;; Fontify CLisp keywords.
701 '("\\s :\\([-a-zA-Z0-9]+\\)\\>" . 1)
702 ;;
703 ;; Function names in emacs-lisp docstrings (in the syntax that
704 ;; substitute-command-keys understands.)
705 '("\\\\\\\\\\[\\([^]\\\n]+\\)]" 1 font-lock-reference-face t)
706 ;;
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))
711 ;;
712 ;; & keywords as types
713 '("\\&\\(optional\\|rest\\)\\>" . font-lock-type-face)
714 ))
715 "For consideration as a value of `lisp-font-lock-keywords'.
716 This does a lot more highlighting.")
717
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.")
723
724
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.")
728
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.")
732
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.")
736
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.")
740
741 (let ((c-keywords
742 ; ("break" "continue" "do" "else" "for" "if" "return" "switch" "while")
743 "break\\|continue\\|do\\|else\\|for\\|if\\|return\\|switch\\|while")
744 (c-type-types
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.
752 (c++-keywords
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"))
760 (c++-type-types
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
773 (list
774 ;;
775 ;; Fontify filenames in #include <...> preprocessor directives.
776 '("^#[ \t]*include[ \t]+\\(<[^>\"\n]+>\\)" 1 font-lock-string-face)
777 ;;
778 ;; Fontify function macro names.
779 '("^#[ \t]*define[ \t]+\\(\\(\\sw+\\)(\\)" 2 font-lock-function-name-face)
780 ;;
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))
784 ;;
785 ;; Fontify function name definitions (without type on line).
786 (list (concat "^\\(" ctoken "\\)[ \t]*(") 1 'font-lock-function-name-face)
787 ))
788
789 (setq c-font-lock-keywords-2
790 (append c-font-lock-keywords-1
791 (list
792 ;;
793 ;; Fontify all storage classes and type specifiers (before declarations).
794 (cons (concat "\\<\\(" c-type-types "\\)\\>") 'font-lock-type-face)
795 ;;
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]*\\((\\)?")
801 9
802 '(if (match-beginning 10)
803 font-lock-function-name-face
804 font-lock-variable-name-face))
805 ;;
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]*\\((\\)?")
811 2
812 '(if (match-beginning 3)
813 font-lock-function-name-face
814 font-lock-variable-name-face))
815 ;;
816 ;; Fontify variable names declared with structures, or typedef names.
817 '("}[ \t*]*\\(\\sw+\\)[ \t]*[;,[]" 1 font-lock-variable-name-face)
818 ;;
819 ;; Fontify all builtin keywords (except case, default and goto; see below).
820 (concat "\\<\\(" c-keywords "\\)\\>")
821 ;;
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)
826 )))
827
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
831 (list
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]*\\((\\)?")
838 14
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]*\\((\\)?")
845 2
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))))
854 )
855
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.")
859
860 (defvar c++-font-lock-keywords c++-font-lock-keywords-1
861 "Additional expressions to highlight in C++ mode.")
862
863 (defvar tex-font-lock-keywords
864 (list
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)
873 )
874 "Additional expressions to highlight in TeX mode.")
875
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.")
886
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)))))
894 ;; Keywords?
895 (setq font-lock-keywords (eval (nth 0 defaults)))
896 ;; Syntactic?
897 (if (nth 1 defaults)
898 (set (make-local-variable 'font-lock-no-comments) t))
899 ;; Case fold?
900 (if (nth 2 defaults)
901 (set (make-local-variable 'font-lock-keywords-case-fold-search) t))
902 ;; Syntax table?
903 (if (nth 3 defaults)
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)))
907 (while slist
908 (modify-syntax-entry (car (car slist)) (cdr (car slist))
909 font-lock-syntax-table)
910 (setq slist (cdr slist))))))))
911
912 ;; Install ourselves:
913
914 (if noninteractive
915 (add-hook 'after-init-hook 'font-lock-make-faces)
916 (font-lock-make-faces))
917
918 (or (assq 'font-lock-mode minor-mode-alist)
919 (setq minor-mode-alist (cons '(font-lock-mode " Font") minor-mode-alist)))
920
921 ;; Provide ourselves:
922
923 (provide 'font-lock)
924
925 ;;; font-lock.el ends here