]> code.delx.au - gnu-emacs/blob - lisp/font-lock.el
(tex-display-shell): Pass nil as arg to
[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 (scheme-mode . (lisp-font-lock-keywords))
130 (slitex-mode . (tex-font-lock-keywords))
131 (tex-mode . (tex-font-lock-keywords)))
132 "*Alist of default major mode and Font Lock defaults.
133 Each item should be a list of the form:
134 (MAJOR-MODE . (FONT-LOCK-KEYWORDS KEYWORDS-ONLY CASE-FOLD FONT-LOCK-SYNTAX))
135 where both MAJOR-MODE and FONT-LOCK-KEYWORDS are symbols. If KEYWORDS-ONLY is
136 non-nil, syntactic fontification (strings and comments) is not performed.
137 If CASE-FOLD is non-nil, the case of the keywords is ignored when fontifying.
138 FONT-LOCK-SYNTAX should be a list of cons pairs of the form (CHAR . STRING), it
139 is used to set the local Font Lock syntax table for keyword fontification.")
140
141 (defvar font-lock-maximum-size (* 100 1024)
142 "*If non-nil, the maximum size for buffers.
143 Only buffers less than are fontified when Font Lock mode is turned on.
144 If nil, means size is irrelevant.")
145
146 (defvar font-lock-keywords-case-fold-search nil
147 "*Non-nil means the patterns in `font-lock-keywords' are case-insensitive.")
148
149 (defvar font-lock-syntax-table nil
150 "*Non-nil means use this syntax table for fontifying.
151 If this is nil, the major mode's syntax table is used.")
152
153 (defvar font-lock-verbose t
154 "*Non-nil means `font-lock-fontify-buffer' should print status messages.")
155
156 ;;;###autoload
157 (defvar font-lock-mode-hook nil
158 "Function or functions to run on entry to Font Lock mode.")
159 \f
160 ;; Colour etc. support.
161
162 (defvar font-lock-display-type nil
163 "A symbol indicating the display Emacs is running under.
164 The symbol should be one of `color', `grayscale' or `mono'.
165 If Emacs guesses this display attribute wrongly, either set this variable in
166 your `~/.emacs' or set the resource `Emacs.displayType' in your `~/.Xdefaults'.
167 See also `font-lock-background-mode' and `font-lock-face-attributes'.")
168
169 (defvar font-lock-background-mode nil
170 "A symbol indicating the Emacs background brightness.
171 The symbol should be one of `light' or `dark'.
172 If Emacs guesses this frame attribute wrongly, either set this variable in
173 your `~/.emacs' or set the resource `Emacs.backgroundMode' in your
174 `~/.Xdefaults'.
175 See also `font-lock-display-type' and `font-lock-face-attributes'.")
176
177 (defvar font-lock-face-attributes nil
178 "A list of default attributes to use for face attributes.
179 Each element of the list should be of the form
180
181 (FACE FOREGROUND BACKGROUND BOLD-P ITALIC-P UNDERLINE-P)
182
183 where FACE should be one of the face symbols `font-lock-comment-face',
184 `font-lock-string-face', `font-lock-keyword-face', `font-lock-type-face',
185 `font-lock-function-name-face', `font-lock-variable-name-face', and
186 `font-lock-reference-face'. A form for each of these face symbols should be
187 provided in the list, but other face symbols and attributes may be given and
188 used in highlighting. See `font-lock-keywords'.
189
190 Subsequent element items should be the attributes for the corresponding
191 Font Lock mode faces. Attributes FOREGROUND and BACKGROUND should be strings
192 \(default if nil), while BOLD-P, ITALIC-P, and UNDERLINE-P should specify the
193 corresponding face attributes (yes if non-nil).
194
195 Emacs uses default attributes based on display type and background brightness.
196 See variables `font-lock-display-type' and `font-lock-background-mode'.
197
198 Resources can be used to over-ride these face attributes. For example, the
199 resource `Emacs.font-lock-comment-face.attributeUnderline' can be used to
200 specify the UNDERLINE-P attribute for face `font-lock-comment-face'.")
201
202 (defun font-lock-make-faces ()
203 "Make faces from `font-lock-face-attributes'.
204 A default list is used if this is nil.
205 See `font-lock-make-face' and `list-faces-display'."
206 ;; We don't need to `setq' any of these variables, but the user can see what
207 ;; is being used if we do.
208 (if (null font-lock-display-type)
209 (setq font-lock-display-type
210 (let ((display-resource (x-get-resource ".displayType"
211 "DisplayType")))
212 (cond (display-resource (intern (downcase display-resource)))
213 ((x-display-color-p) 'color)
214 ((x-display-grayscale-p) 'grayscale)
215 (t 'mono)))))
216 (if (null font-lock-background-mode)
217 (setq font-lock-background-mode
218 (let ((bg-resource (x-get-resource ".backgroundMode"
219 "BackgroundMode"))
220 (params (frame-parameters)))
221 (cond (bg-resource (intern (downcase bg-resource)))
222 ((or (string-equal "white"
223 (downcase (cdr (assq 'foreground-color params))))
224 (string-equal "black"
225 (downcase (cdr (assq 'background-color params)))))
226 'dark)
227 (t 'light)))))
228 (if (null font-lock-face-attributes)
229 (setq font-lock-face-attributes
230 (let ((light-bg (eq font-lock-background-mode 'light)))
231 (cond ((memq font-lock-display-type '(mono monochrome))
232 ;; Emacs 19.25's font-lock defaults:
233 ;;'((font-lock-comment-face nil nil nil t nil)
234 ;; (font-lock-string-face nil nil nil nil t)
235 ;; (font-lock-keyword-face nil nil t nil nil)
236 ;; (font-lock-function-name-face nil nil t t nil)
237 ;; (font-lock-type-face nil nil nil t nil))
238 (list '(font-lock-comment-face nil nil t t nil)
239 '(font-lock-string-face nil nil nil t nil)
240 '(font-lock-keyword-face nil nil t nil nil)
241 (list
242 'font-lock-function-name-face
243 (cdr (assq 'background-color (frame-parameters)))
244 (cdr (assq 'foreground-color (frame-parameters)))
245 t nil nil)
246 '(font-lock-variable-name-face nil nil t t nil)
247 '(font-lock-type-face nil nil t nil t)
248 '(font-lock-reference-face nil nil t nil t)))
249 ((memq font-lock-display-type '(grayscale greyscale
250 grayshade greyshade))
251 (list
252 (list 'font-lock-comment-face
253 (if light-bg "DimGray" "Gray80") nil t t nil)
254 (list 'font-lock-string-face
255 (if light-bg "Gray50" "LightGray") nil nil t nil)
256 (list 'font-lock-keyword-face
257 (if light-bg "DimGray" "Gray90") nil t nil nil)
258 (list 'font-lock-function-name-face
259 (cdr (assq 'background-color (frame-parameters)))
260 (cdr (assq 'foreground-color (frame-parameters)))
261 t nil nil)
262 (list 'font-lock-variable-name-face
263 (if light-bg "DimGray" "Gray90") nil t t nil)
264 (list 'font-lock-type-face
265 (if light-bg "DimGray" "Gray80") nil t nil t)
266 (list 'font-lock-reference-face
267 (if light-bg "Gray50" "LightGray") nil t nil t)))
268 (light-bg ; light colour background
269 '((font-lock-comment-face "Firebrick")
270 (font-lock-string-face "RosyBrown")
271 (font-lock-keyword-face "Purple")
272 (font-lock-function-name-face "Blue")
273 (font-lock-variable-name-face "DarkGoldenrod")
274 (font-lock-type-face "DarkOliveGreen")
275 (font-lock-reference-face "CadetBlue")))
276 (t ; dark colour background
277 '((font-lock-comment-face "OrangeRed")
278 (font-lock-string-face "LightSalmon")
279 (font-lock-keyword-face "LightSteelBlue")
280 (font-lock-function-name-face "LightSkyBlue")
281 (font-lock-variable-name-face "LightGoldenrod")
282 (font-lock-type-face "PaleGreen")
283 (font-lock-reference-face "Aquamarine")))))))
284 (mapcar 'font-lock-make-face font-lock-face-attributes))
285
286 (defun font-lock-make-face (face-attributes)
287 "Make a face from FACE-ATTRIBUTES.
288 FACE-ATTRIBUTES should be like an element `font-lock-face-attributes', so that
289 the face name is the first item in the list. A variable with the same name as
290 the face is also set; its value is the face name."
291 (let* ((face (nth 0 face-attributes))
292 (face-name (symbol-name face))
293 (set-p (function (lambda (face-name resource)
294 (x-get-resource (concat face-name ".attribute" resource)
295 (concat "Face.Attribute" resource)))))
296 (on-p (function (lambda (face-name resource)
297 (let ((set (funcall set-p face-name resource)))
298 (and set (member (downcase set) '("on" "true"))))))))
299 (make-face face)
300 ;; Set attributes not set from X resources (and therefore `make-face').
301 (or (funcall set-p face-name "Foreground")
302 (condition-case nil
303 (set-face-foreground face (nth 1 face-attributes))
304 (error nil)))
305 (or (funcall set-p face-name "Background")
306 (condition-case nil
307 (set-face-background face (nth 2 face-attributes))
308 (error nil)))
309 (if (funcall set-p face-name "Bold")
310 (and (funcall on-p face-name "Bold") (make-face-bold face nil t))
311 (and (nth 3 face-attributes) (make-face-bold face nil t)))
312 (if (funcall set-p face-name "Italic")
313 (and (funcall on-p face-name "Italic") (make-face-italic face nil t))
314 (and (nth 4 face-attributes) (make-face-italic face nil t)))
315 (or (funcall set-p face-name "Underline")
316 (set-face-underline-p face (nth 5 face-attributes)))
317 (set face face)))
318 \f
319 ;; Fontification.
320
321 ;; These variables record, for each buffer, the parse state at a particular
322 ;; position, always the start of a line. Used to make font-lock-fontify-region
323 ;; faster.
324 (defvar font-lock-cache-position nil)
325 (defvar font-lock-cache-state nil)
326 (make-variable-buffer-local 'font-lock-cache-position)
327 (make-variable-buffer-local 'font-lock-cache-state)
328
329 (defun font-lock-fontify-region (start end &optional loudly)
330 "Put proper face on each string and comment between START and END."
331 (save-excursion
332 (save-restriction
333 (widen)
334 (goto-char start)
335 (beginning-of-line)
336 (if loudly (message "Fontifying %s... (syntactically...)" (buffer-name)))
337 (let ((inhibit-read-only t)
338 ;; Prevent warnings if the disk file has been altered.
339 (buffer-file-name)
340 ;; Suppress all undo activity.
341 (buffer-undo-list t)
342 (modified (buffer-modified-p))
343 (cstart (if comment-start-skip
344 (concat "\\s\"\\|" comment-start-skip)
345 "\\s\""))
346 (cend (if comment-end
347 (concat "\\s>\\|"
348 (regexp-quote
349 ;; Discard leading spaces from comment-end.
350 ;; In C mode, it is " */"
351 ;; and we don't want to fail to notice a */
352 ;; just because there's no space there.
353 (save-match-data
354 (if (string-match "^ +" comment-end)
355 (substring comment-end (match-end 0))
356 comment-end))))
357 "\\s>"))
358 (startline (point))
359 state prev prevstate)
360 ;; Find the state at the line-beginning before START.
361 (if (eq startline font-lock-cache-position)
362 (setq state font-lock-cache-state)
363 ;; Find outermost containing sexp.
364 (beginning-of-defun)
365 ;; Find the state at STARTLINE.
366 (while (< (point) startline)
367 (setq state (parse-partial-sexp (point) startline 0)))
368 (setq font-lock-cache-state state
369 font-lock-cache-position (point)))
370 ;; Now find the state precisely at START.
371 (setq state (parse-partial-sexp (point) start nil nil state))
372 ;; If the region starts inside a string, show the extent of it.
373 (if (nth 3 state)
374 (let ((beg (point)))
375 (while (and (re-search-forward "\\s\"" end 'move)
376 (nth 3 (parse-partial-sexp beg (point) nil nil
377 state))))
378 (put-text-property beg (point) 'face font-lock-string-face)
379 (setq state (parse-partial-sexp beg (point) nil nil state))))
380 ;; Likewise for a comment.
381 (if (or (nth 4 state) (nth 7 state))
382 (let ((beg (point)))
383 (while (and (re-search-forward cend end 'move)
384 (nth 3 (parse-partial-sexp beg (point) nil nil
385 state))))
386 (put-text-property beg (point) 'face font-lock-comment-face)
387 (setq state (parse-partial-sexp beg (point) nil nil state))))
388 ;; Find each interesting place between here and END.
389 (while (and (< (point) end)
390 (setq prev (point) prevstate state)
391 (re-search-forward cstart end t)
392 (progn
393 ;; Clear out the fonts of what we skip over.
394 (remove-text-properties prev (point) '(face nil))
395 ;; Verify the state at that place
396 ;; so we don't get fooled by \" or \;.
397 (setq state (parse-partial-sexp prev (point) nil nil
398 state))))
399 (let ((here (point)))
400 (if (or (nth 4 state) (nth 7 state))
401 ;; We found a real comment start.
402 (let ((beg (match-beginning 0)))
403 (goto-char beg)
404 (save-restriction
405 (narrow-to-region (point-min) end)
406 (condition-case nil
407 (progn
408 (forward-comment 1)
409 ;; forward-comment skips all whitespace,
410 ;; so go back to the real end of the comment.
411 (skip-chars-backward " \t"))
412 (error (goto-char end))))
413 (put-text-property beg (point) 'face font-lock-comment-face)
414 (setq state (parse-partial-sexp here (point) nil nil state)))
415 (if (nth 3 state)
416 (let ((beg (match-beginning 0)))
417 (while (and (re-search-forward "\\s\"" end 'move)
418 (nth 3 (parse-partial-sexp here (point) nil nil
419 state))))
420 (put-text-property beg (point) 'face font-lock-string-face)
421 (setq state (parse-partial-sexp here (point) nil nil
422 state))))))
423 ;; Make sure PREV is non-nil after the loop
424 ;; only if it was set on the very last iteration.
425 (setq prev nil))
426 (and prev
427 (remove-text-properties prev end '(face nil)))
428 (and (buffer-modified-p)
429 (not modified)
430 (set-buffer-modified-p nil))))))
431
432 ;; This code used to be used to show a string on reaching the end of it.
433 ;; It is probably not needed due to later changes to handle strings
434 ;; starting before the region in question.
435 ;; (if (and (null (nth 3 state))
436 ;; (eq (char-syntax (preceding-char)) ?\")
437 ;; (save-excursion
438 ;; (nth 3 (parse-partial-sexp prev (1- (point))
439 ;; nil nil prevstate))))
440 ;; ;; We found the end of a string.
441 ;; (save-excursion
442 ;; (setq foo2 (point))
443 ;; (let ((ept (point)))
444 ;; (forward-sexp -1)
445 ;; ;; Highlight the string when we see the end.
446 ;; ;; Doing it at the start leads to trouble:
447 ;; ;; either it fails to handle multiline strings
448 ;; ;; or it can run away when an unmatched " is inserted.
449 ;; (put-text-property (point) ept 'face
450 ;; (if (= (car state) 1)
451 ;; font-lock-doc-string-face
452 ;; font-lock-string-face)))))
453
454 (defun font-lock-unfontify-region (beg end)
455 (let ((modified (buffer-modified-p))
456 (buffer-undo-list t)
457 (inhibit-read-only t)
458 ;; Prevent warnings if the disk file has been altered.
459 (buffer-file-name))
460 (remove-text-properties beg end '(face nil))
461 (set-buffer-modified-p modified)))
462
463 ;; Called when any modification is made to buffer text.
464 (defun font-lock-after-change-function (beg end old-len)
465 (save-excursion
466 (save-match-data
467 ;; Discard the cache info if text before it has changed.
468 (and font-lock-cache-position
469 (> font-lock-cache-position beg)
470 (setq font-lock-cache-position nil))
471 ;; Rescan between start of line from `beg' and start of line after `end'.
472 (goto-char beg)
473 (beginning-of-line)
474 (setq beg (point))
475 (goto-char end)
476 (forward-line 1)
477 (setq end (point))
478 ;; First scan for strings and comments.
479 ;; Must scan from line start in case of
480 ;; inserting space into `intfoo () {}', and after widened.
481 (if font-lock-no-comments
482 (remove-text-properties beg end '(face nil))
483 (font-lock-fontify-region beg end))
484 (font-lock-hack-keywords beg end))))
485
486 ; ;; Now scan for keywords, but not if we are inside a comment now.
487 ; (or (and (not font-lock-no-comments)
488 ; (let ((state (parse-partial-sexp beg end nil nil
489 ; font-lock-cache-state)))
490 ; (or (nth 4 state) (nth 7 state))))
491 ; (font-lock-hack-keywords beg end))
492 \f
493 ;;; Fontifying arbitrary patterns
494
495 (defun font-lock-hack-keywords (start end &optional loudly)
496 "Fontify according to `font-lock-keywords' between START and END."
497 (let ((case-fold-search font-lock-keywords-case-fold-search)
498 (keywords font-lock-keywords)
499 (count 0)
500 ;; Prevent warnings if the disk file has been altered.
501 (buffer-file-name)
502 (inhibit-read-only t)
503 (buffer-undo-list t)
504 (modified (buffer-modified-p))
505 (old-syntax (syntax-table))
506 (bufname (buffer-name)))
507 (unwind-protect
508 (let (keyword regexp match highlights hs h s e)
509 (if loudly (message "Fontifying %s... (regexps...)" bufname))
510 (if font-lock-syntax-table (set-syntax-table font-lock-syntax-table))
511 (while keywords
512 (setq keyword (car keywords) keywords (cdr keywords)
513 regexp (if (stringp keyword) keyword (car keyword))
514 highlights (cond ((stringp keyword)
515 '((0 font-lock-keyword-face)))
516 ((numberp (cdr keyword))
517 (list (list (cdr keyword)
518 'font-lock-keyword-face)))
519 ((symbolp (cdr keyword))
520 (list (list 0 (cdr keyword))))
521 ((nlistp (nth 1 keyword))
522 (list (cdr keyword)))
523 (t
524 (cdr keyword))))
525 (goto-char start)
526 (while (re-search-forward regexp end t)
527 (setq hs highlights)
528 (while hs
529 (setq h (car hs) match (nth 0 h)
530 s (match-beginning match) e (match-end match)
531 hs (cdr hs))
532 (cond ((not s)
533 ;; No match but we might not signal an error
534 (or (nth 3 h)
535 (error "No subexpression %d in expression %d"
536 match (1+ count))))
537 ((and (not (nth 2 h))
538 (text-property-not-all s e 'face nil))
539 ;; Can't override and already fontified
540 nil)
541 ((not (eq (nth 2 h) 'keep))
542 ;; Can override but need not keep existing fontification
543 (put-text-property s e 'face (eval (nth 1 h))))
544 (t
545 ;; Can override but must keep existing fontification
546 ;; (Does anyone use this? sm.)
547 (let ((p (text-property-any s e 'face nil)) n
548 (face (eval (nth 1 h))))
549 (while p
550 (setq n (next-single-property-change p 'face nil e))
551 (put-text-property p n 'face face)
552 (setq p (text-property-any n e 'face nil))))))))
553 ;; the above form was:
554 ; (save-excursion
555 ; (goto-char s)
556 ; (while (< (point) e)
557 ; (let ((next (next-single-property-change (point) 'face
558 ; nil e)))
559 ; (if (or (null next) (> next e))
560 ; (setq next e))
561 ; (if (not (get-text-property (point) 'face))
562 ; (put-text-property (point) next 'face face))
563 ; (goto-char next))))
564
565 (if loudly (message "Fontifying %s... (regexps...%s)" bufname
566 (make-string (setq count (1+ count)) ?.)))))
567 (set-syntax-table old-syntax))
568 (and (buffer-modified-p)
569 (not modified)
570 (set-buffer-modified-p nil))))
571 \f
572 ;; The user level functions
573
574 (defvar font-lock-mode nil) ; for modeline
575
576 (defvar font-lock-fontified nil) ; whether we have hacked this buffer
577 (put 'font-lock-fontified 'permanent-local t)
578
579 ;;;###autoload
580 (defun font-lock-mode (&optional arg)
581 "Toggle Font Lock mode.
582 With arg, turn Font Lock mode on if and only if arg is positive.
583
584 When Font Lock mode is enabled, text is fontified as you type it:
585
586 - Comments are displayed in `font-lock-comment-face';
587 - Strings are displayed in `font-lock-string-face';
588 - Certain other expressions are displayed in other faces according to the
589 value of the variable `font-lock-keywords'.
590
591 You can enable Font Lock mode in any major mode automatically by turning on in
592 the major mode's hook. For example, put in your ~/.emacs:
593
594 (add-hook 'c-mode-hook 'turn-on-font-lock)
595
596 Or for any visited file with the following in your ~/.emacs:
597
598 (add-hook 'find-file-hooks 'turn-on-font-lock)
599
600 The default Font Lock mode faces and their attributes are defined in the
601 variable `font-lock-face-attributes', and Font Lock mode default settings in
602 the variable `font-lock-defaults-alist'.
603
604 When you turn Font Lock mode on/off the buffer is fontified/defontified, though
605 fontification occurs only if the buffer is less than `font-lock-maximum-size'.
606 To fontify a buffer without turning on Font Lock mode, and regardless of buffer
607 size, you can use \\[font-lock-fontify-buffer]."
608 (interactive "P")
609 (let ((on-p (if arg (> (prefix-numeric-value arg) 0) (not font-lock-mode))))
610 (if (equal (buffer-name) " *Compiler Input*") ; hack for bytecomp...
611 (setq on-p nil))
612 (if (not on-p)
613 (remove-hook 'after-change-functions 'font-lock-after-change-function)
614 (make-local-variable 'after-change-functions)
615 (add-hook 'after-change-functions 'font-lock-after-change-function))
616 (set (make-local-variable 'font-lock-mode) on-p)
617 (cond (on-p
618 (font-lock-set-defaults)
619 (make-local-variable 'before-revert-hook)
620 (make-local-variable 'after-revert-hook)
621 ;; If buffer is reverted, must clean up the state.
622 (add-hook 'before-revert-hook 'font-lock-revert-setup)
623 (add-hook 'after-revert-hook 'font-lock-revert-cleanup)
624 (run-hooks 'font-lock-mode-hook)
625 (cond (font-lock-fontified
626 nil)
627 ((or (null font-lock-maximum-size)
628 (> font-lock-maximum-size (buffer-size)))
629 (font-lock-fontify-buffer))
630 (font-lock-verbose
631 (message "Fontifying %s... buffer too big." (buffer-name)))))
632 (font-lock-fontified
633 (setq font-lock-fontified nil)
634 (remove-hook 'before-revert-hook 'font-lock-revert-setup)
635 (remove-hook 'after-revert-hook 'font-lock-revert-cleanup)
636 (font-lock-unfontify-region (point-min) (point-max))))
637 (force-mode-line-update)))
638
639 ;;;###autoload
640 (defun turn-on-font-lock ()
641 "Unconditionally turn on Font Lock mode."
642 (font-lock-mode 1))
643
644 ;; If the buffer is about to be reverted, it won't be fontified.
645 (defun font-lock-revert-setup ()
646 (setq font-lock-fontified nil))
647
648 ;; If the buffer has just been reverted, we might not even be in font-lock
649 ;; mode anymore, and if we are, the buffer may or may not have already been
650 ;; refontified. Refontify here if it looks like we need to.
651 (defun font-lock-revert-cleanup ()
652 (and font-lock-mode
653 (not font-lock-fontified)
654 (font-lock-mode 1)))
655
656 ;;;###autoload
657 (defun font-lock-fontify-buffer ()
658 "Fontify the current buffer the way `font-lock-mode' would."
659 (interactive)
660 (let ((was-on font-lock-mode)
661 (verbose (or font-lock-verbose (interactive-p)))
662 (modified (buffer-modified-p)))
663 (set (make-local-variable 'font-lock-fontified) nil)
664 (if verbose (message "Fontifying %s..." (buffer-name)))
665 ;; Turn it on to run hooks and get the right `font-lock-keywords' etc.
666 (or was-on (font-lock-set-defaults))
667 (condition-case nil
668 (save-excursion
669 (font-lock-unfontify-region (point-min) (point-max))
670 (if (not font-lock-no-comments)
671 (font-lock-fontify-region (point-min) (point-max) verbose))
672 (font-lock-hack-keywords (point-min) (point-max) verbose)
673 (setq font-lock-fontified t))
674 ;; We don't restore the old fontification, so it's best to unfontify.
675 (quit (font-lock-unfontify-region (point-min) (point-max))))
676 (if verbose (message "Fontifying %s... %s." (buffer-name)
677 (if font-lock-fontified "done" "aborted")))
678 (and (buffer-modified-p)
679 (not modified)
680 (set-buffer-modified-p nil))))
681
682 \f
683 ;;; Various information shared by several modes.
684 ;;; Information specific to a single mode should go in its load library.
685
686 (defconst lisp-font-lock-keywords-1
687 (list
688 ;; highlight defining forms. This doesn't work too nicely for
689 ;; (defun (setf foo) ...) but it does work for (defvar foo) which
690 ;; is more important.
691 (list (concat "^(\\(def\\(const\\|ine-key\\(\\|-after\\)\\|var\\)\\)\\>"
692 "\\s *\\([^ \t\n\)]+\\)?")
693 '(1 font-lock-keyword-face) '(4 font-lock-variable-name-face nil t))
694 (list (concat "^(\\(def\\(a\\(dvice\\|lias\\)\\|macro\\|subst\\|un\\)\\)\\>"
695 "\\s *\\([^ \t\n\)]+\\)?")
696 '(1 font-lock-keyword-face) '(4 font-lock-function-name-face nil t))
697 ;;
698 ;; this is highlights things like (def* (setf foo) (bar baz)), but may
699 ;; be slower (I haven't really thought about it)
700 ; ("^(def[-a-z]+\\s +\\(\\s(\\S)*\\s)\\|\\S(\\S *\\)"
701 ; 1 font-lock-function-name-face)
702 )
703 "For consideration as a value of `lisp-font-lock-keywords'.
704 This does fairly subdued highlighting.")
705
706 (defconst lisp-font-lock-keywords-2
707 (append
708 lisp-font-lock-keywords-1
709 (list
710 ;;
711 ;; Control structures.
712 ;; ELisp:
713 ; ("cond" "if" "while" "let\\*?" "prog[nv12*]?" "catch" "throw"
714 ; "save-restriction" "save-excursion"
715 ; "save-window-excursion" "save-match-data" "unwind-protect"
716 ; "condition-case" "track-mouse")
717 (cons
718 (concat "(\\("
719 "c\\(atch\\|ond\\(\\|ition-case\\)\\)\\|if\\|let\\*?\\|prog[nv12*]?\\|"
720 "save-\\(excursion\\|match-data\\|restriction\\|window-excursion\\)\\|"
721 "t\\(hrow\\|rack-mouse\\)\\|unwind-protect\\|while"
722 "\\)[ \t\n]") 1)
723 ;; CLisp:
724 ; ("when" "unless" "do" "flet" "labels" "return" "return-from")
725 '("(\\(do\\|flet\\|labels\\|return\\(\\|-from\\)\\|unless\\|when\\)[ \t\n]"
726 . 1)
727 ;;
728 ;; Fontify CLisp keywords.
729 '("\\s :\\([-a-zA-Z0-9]+\\)\\>" . 1)
730 ;;
731 ;; Function names in emacs-lisp docstrings (in the syntax that
732 ;; substitute-command-keys understands.)
733 '("\\\\\\\\\\[\\([^]\\\n]+\\)]" 1 font-lock-reference-face t)
734 ;;
735 ;; Words inside `' which tend to be function names
736 (let ((word-char "[-+a-zA-Z0-9_:*]"))
737 (list (concat "`\\(" word-char word-char "+\\)'")
738 1 'font-lock-reference-face t))
739 ;;
740 ;; & keywords as types
741 '("\\&\\(optional\\|rest\\)\\>" . font-lock-type-face)
742 ))
743 "For consideration as a value of `lisp-font-lock-keywords'.
744 This does a lot more highlighting.")
745
746 ;; default to the gaudier variety?
747 ;(defvar lisp-font-lock-keywords lisp-font-lock-keywords-2
748 ; "Additional expressions to highlight in Lisp modes.")
749 (defvar lisp-font-lock-keywords lisp-font-lock-keywords-1
750 "Additional expressions to highlight in Lisp modes.")
751
752
753 (defconst c-font-lock-keywords-1 nil
754 "For consideration as a value of `c-font-lock-keywords'.
755 This does fairly subdued highlighting.")
756
757 (defconst c-font-lock-keywords-2 nil
758 "For consideration as a value of `c-font-lock-keywords'.
759 This does a lot more highlighting.")
760
761 (defconst c++-font-lock-keywords-1 nil
762 "For consideration as a value of `c++-font-lock-keywords'.
763 This does fairly subdued highlighting.")
764
765 (defconst c++-font-lock-keywords-2 nil
766 "For consideration as a value of `c++-font-lock-keywords'.
767 This does a lot more highlighting.")
768
769 (let ((c-keywords
770 ; ("break" "continue" "do" "else" "for" "if" "return" "switch" "while")
771 "break\\|continue\\|do\\|else\\|for\\|if\\|return\\|switch\\|while")
772 (c-type-types
773 ; ("auto" "extern" "register" "static" "typedef" "struct" "union" "enum"
774 ; "signed" "unsigned" "short" "long" "int" "char" "float" "double"
775 ; "void" "volatile" "const")
776 (concat "auto\\|c\\(har\\|onst\\)\\|double\\|e\\(num\\|xtern\\)\\|"
777 "float\\|int\\|long\\|register\\|"
778 "s\\(hort\\|igned\\|t\\(atic\\|ruct\\)\\)\\|typedef\\|"
779 "un\\(ion\\|signed\\)\\|vo\\(id\\|latile\\)")) ; 6 ()s deep.
780 (c++-keywords
781 ; ("break" "continue" "do" "else" "for" "if" "return" "switch" "while"
782 ; "asm" "catch" "delete" "new" "operator" "sizeof" "this" "throw" "try"
783 ; "protected" "private" "public")
784 (concat "asm\\|break\\|c\\(atch\\|ontinue\\)\\|d\\(elete\\|o\\)\\|"
785 "else\\|for\\|if\\|new\\|operator\\|"
786 "p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|return\\|"
787 "s\\(izeof\\|witch\\)\\|t\\(h\\(is\\|row\\)\\|ry\\)\\|while"))
788 (c++-type-types
789 ; ("auto" "extern" "register" "static" "typedef" "struct" "union" "enum"
790 ; "signed" "unsigned" "short" "long" "int" "char" "float" "double"
791 ; "void" "volatile" "const" "class" "inline" "friend" "bool"
792 ; "virtual" "complex" "template")
793 (concat "auto\\|bool\\|c\\(har\\|lass\\|o\\(mplex\\|nst\\)\\)\\|"
794 "double\\|e\\(num\\|xtern\\)\\|f\\(loat\\|riend\\)\\|"
795 "in\\(line\\|t\\)\\|long\\|register\\|"
796 "s\\(hort\\|igned\\|t\\(atic\\|ruct\\)\\)\\|"
797 "t\\(emplate\\|ypedef\\)\\|un\\(ion\\|signed\\)\\|"
798 "v\\(irtual\\|o\\(id\\|latile\\)\\)")) ; 11 ()s deep.
799 (ctoken "[a-zA-Z0-9_:~]+"))
800 (setq c-font-lock-keywords-1
801 (list
802 ;;
803 ;; Fontify filenames in #include <...> preprocessor directives.
804 '("^#[ \t]*include[ \t]+\\(<[^>\"\n]+>\\)" 1 font-lock-string-face)
805 ;;
806 ;; Fontify function macro names.
807 '("^#[ \t]*define[ \t]+\\(\\(\\sw+\\)(\\)" 2 font-lock-function-name-face)
808 ;;
809 ;; Fontify otherwise as symbol names, and the preprocessor directive names.
810 '("^\\(#[ \t]*[a-z]+\\)\\>[ \t]*\\(\\sw+\\)?"
811 (1 font-lock-reference-face) (2 font-lock-variable-name-face nil t))
812 ;;
813 ;; Fontify function name definitions (without type on line).
814 (list (concat "^\\(" ctoken "\\)[ \t]*(") 1 'font-lock-function-name-face)
815 ))
816
817 (setq c-font-lock-keywords-2
818 (append c-font-lock-keywords-1
819 (list
820 ;;
821 ;; Fontify all storage classes and type specifiers (before declarations).
822 (cons (concat "\\<\\(" c-type-types "\\)\\>") 'font-lock-type-face)
823 ;;
824 ;; Fontify variable/structure name declarations and definitions, or
825 ;; function name declarations (plus definitions with type on same line).
826 (list (concat "\\<\\(" c-type-types "\\)[ \t*]+"
827 "\\(" ctoken "[ \t*]+\\)*"
828 "\\(" ctoken "\\)[ \t]*\\((\\)?")
829 9
830 '(if (match-beginning 10)
831 font-lock-function-name-face
832 font-lock-variable-name-face))
833 ;;
834 ;; Fontify function/variable name declarations at the start of the line.
835 ;; (Not everyone follows the GNU convention of function name at the start.)
836 (list (concat "^" ctoken "[ \t*]+"
837 "\\(" ctoken "[ \t*]+\\)*"
838 "\\(" ctoken "\\)[ \t]*\\((\\)?")
839 2
840 '(if (match-beginning 3)
841 font-lock-function-name-face
842 font-lock-variable-name-face))
843 ;;
844 ;; Fontify variable names declared with structures, or typedef names.
845 '("}[ \t*]*\\(\\sw+\\)[ \t]*[;,[]" 1 font-lock-variable-name-face)
846 ;;
847 ;; Fontify all builtin keywords (except case, default and goto; see below).
848 (concat "\\<\\(" c-keywords "\\)\\>")
849 ;;
850 ;; Fontify case/goto keywords and targets, and goto tags (incl "default:").
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 (setq c++-font-lock-keywords-1 c-font-lock-keywords-1)
857 (setq c++-font-lock-keywords-2
858 (append c++-font-lock-keywords-1
859 (list
860 ;; We don't just add to the C keywords for subtle differences and speed.
861 ;; See the above comments for `c-font-lock-keywords-2'.
862 (cons (concat "\\<\\(" c++-type-types "\\)\\>") 'font-lock-type-face)
863 (list (concat "\\<\\(" c++-type-types "\\)[ \t*&]+"
864 "\\(" ctoken "[ \t*&]+\\)*"
865 "\\(" ctoken "\\)[ \t]*\\((\\)?")
866 14
867 '(if (match-beginning 15)
868 font-lock-function-name-face
869 font-lock-variable-name-face))
870 (list (concat "^" ctoken "[ \t*]+"
871 "\\(" ctoken "[ \t*]+\\)*"
872 "\\(" ctoken "\\)[ \t]*\\((\\)?")
873 2
874 '(if (match-beginning 3)
875 font-lock-function-name-face
876 font-lock-variable-name-face))
877 '("}[ \t*]*\\(\\sw+\\)[ \t]*[;,[]" 1 font-lock-variable-name-face)
878 (concat "\\<\\(" c++-keywords "\\)\\>")
879 '("\\<\\(case\\|goto\\)\\>[ \t]*\\([^ \t\n:;]+\\)?"
880 (1 font-lock-keyword-face) (2 font-lock-reference-face nil t))
881 '("^[ \t]*\\(\\sw+\\)[ \t]*:[^:]" 1 font-lock-reference-face))))
882 )
883
884 ; default to the gaudier variety?
885 (defvar c-font-lock-keywords c-font-lock-keywords-1
886 "Additional expressions to highlight in C mode.")
887
888 (defvar c++-font-lock-keywords c++-font-lock-keywords-1
889 "Additional expressions to highlight in C++ mode.")
890
891 (defvar tex-font-lock-keywords
892 (list
893 '("\\(\\\\\\([a-zA-Z@]+\\|.\\)\\)" 1 font-lock-keyword-face t)
894 '("{\\\\em\\([^}]+\\)}" 1 font-lock-comment-face t)
895 '("{\\\\bf\\([^}]+\\)}" 1 font-lock-keyword-face t)
896 '("^[ \t\n]*\\\\def[\\\\@]\\(\\w+\\)" 1 font-lock-function-name-face t)
897 '("\\\\\\(begin\\|end\\){\\([a-zA-Z0-9\\*]+\\)}"
898 2 font-lock-function-name-face t)
899 '("[^\\\\]\\$\\([^$]*\\)\\$" 1 font-lock-string-face t)
900 ; '("\\$\\([^$]*\\)\\$" 1 font-lock-string-face t)
901 )
902 "Additional expressions to highlight in TeX mode.")
903
904 ;; There is no html-mode.el shipped with Emacs; `font-lock-defaults' entry
905 ; would be: (html-font-lock-keywords nil t)
906 ;(defconst html-font-lock-keywords
907 ; '(("<!--[^>]*>" 0 font-lock-comment-face t) ; Comment.
908 ; ("</?\\sw+" . font-lock-type-face) ; Normal tag start.
909 ; (">" . font-lock-type-face) ; Normal tag end.
910 ; ("<\\(/?\\(a\\|form\\|img\\|input\\)\\)\\>" ; Special tag name.
911 ; 1 font-lock-function-name-face t)
912 ; ("\\<\\(\\sw+\\)[>=]" 1 font-lock-keyword-face)) ; Tag attribute.
913 ; "Additional expressions to highlight in HTML mode.")
914
915 (defun font-lock-set-defaults ()
916 "Set fontification defaults appropriately for this mode.
917 Sets `font-lock-keywords', `font-lock-no-comments', `font-lock-syntax-table'
918 and `font-lock-keywords-case-fold-search' using `font-lock-defaults-alist'."
919 (or font-lock-keywords ; if not already set.
920 (let ((defaults (or font-lock-defaults
921 (cdr (assq major-mode font-lock-defaults-alist)))))
922 ;; Keywords?
923 (setq font-lock-keywords (eval (nth 0 defaults)))
924 ;; Syntactic?
925 (if (nth 1 defaults)
926 (set (make-local-variable 'font-lock-no-comments) t))
927 ;; Case fold?
928 (if (nth 2 defaults)
929 (set (make-local-variable 'font-lock-keywords-case-fold-search) t))
930 ;; Syntax table?
931 (if (nth 3 defaults)
932 (let ((slist (nth 3 defaults)))
933 (make-local-variable 'font-lock-syntax-table)
934 (setq font-lock-syntax-table (copy-syntax-table (syntax-table)))
935 (while slist
936 (modify-syntax-entry (car (car slist)) (cdr (car slist))
937 font-lock-syntax-table)
938 (setq slist (cdr slist))))))))
939
940 ;; Install ourselves:
941
942 (if purify-flag
943 (add-hook 'after-init-hook 'font-lock-make-faces)
944 (font-lock-make-faces))
945
946 (or (assq 'font-lock-mode minor-mode-alist)
947 (setq minor-mode-alist (cons '(font-lock-mode " Font") minor-mode-alist)))
948
949 ;; Provide ourselves:
950
951 (provide 'font-lock)
952
953 ;;; font-lock.el ends here