Commit | Line | Data |
---|---|---|
030f4a35 | 1 | ;; Electric Font Lock Mode |
799761f0 | 2 | ;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. |
030f4a35 | 3 | |
799761f0 | 4 | ;; Author: jwz, then rms and sm <simon@gnu.ai.mit.edu> |
030f4a35 RS |
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 | ||
030f4a35 RS |
24 | ;;; Commentary: |
25 | ||
b89e1134 SM |
26 | ;; Font Lock mode is a minor mode that causes your comments to be displayed in |
27 | ;; one face, strings in another, reserved words in another, and so on. | |
030f4a35 RS |
28 | ;; |
29 | ;; Comments will be displayed in `font-lock-comment-face'. | |
30 | ;; Strings will be displayed in `font-lock-string-face'. | |
a1eb1cf1 | 31 | ;; Regexps are used to display selected patterns in other faces. |
030f4a35 RS |
32 | ;; |
33 | ;; To make the text you type be fontified, use M-x font-lock-mode. | |
b89e1134 | 34 | ;; When this minor mode is on, the faces of the current line are |
030f4a35 RS |
35 | ;; updated with every insertion or deletion. |
36 | ;; | |
b89e1134 | 37 | ;; To turn Font Lock mode on automatically, add this to your .emacs file: |
030f4a35 | 38 | ;; |
b89e1134 | 39 | ;; (add-hook 'emacs-lisp-mode-hook 'turn-on-font-lock) |
030f4a35 | 40 | ;; |
b89e1134 | 41 | ;; On a Sparc2, `font-lock-fontify-buffer' takes about 10 seconds for a 120k |
a1eb1cf1 RS |
42 | ;; file of C code using the default configuration, and about 25 seconds using |
43 | ;; the more extensive configuration, though times also depend on file contents. | |
44 | ;; You can speed this up substantially by removing some of the patterns that | |
45 | ;; are highlighted by default. Fontifying Lisp code is significantly faster, | |
46 | ;; because Lisp has a more regular syntax than C, so the expressions don't have | |
47 | ;; to be as hairy. | |
48 | ;; | |
b89e1134 SM |
49 | ;; If you add patterns for a new mode, say foo.el's `foo-mode', say in which |
50 | ;; you don't want syntactic fontification to occur, you can make Font Lock mode | |
51 | ;; use your regexps when turning on Font Lock by adding to `foo-mode-hook': | |
52 | ;; | |
53 | ;; (add-hook 'foo-mode-hook | |
54 | ;; '(lambda () (make-local-variable 'font-lock-defaults) | |
55 | ;; (setq font-lock-defaults '(foo-font-lock-keywords t)))) | |
56 | ;; | |
a1eb1cf1 RS |
57 | ;; Nasty regexps of the form "bar\\(\\|lo\\)\\|f\\(oo\\|u\\(\\|bar\\)\\)\\|lo" |
58 | ;; are made thusly: (make-regexp '("foo" "fu" "fubar" "bar" "barlo" "lo")) for | |
59 | ;; efficiency. See /pub/gnu/emacs/elisp-archive/functions/make-regexp.el.Z on | |
60 | ;; archive.cis.ohio-state.edu for this and other functions. | |
61 | \f | |
030f4a35 RS |
62 | ;;; Code: |
63 | ||
a1eb1cf1 RS |
64 | (defvar font-lock-comment-face 'font-lock-comment-face |
65 | "Face to use for comments.") | |
030f4a35 | 66 | |
a1eb1cf1 RS |
67 | (defvar font-lock-string-face 'font-lock-string-face |
68 | "Face to use for strings.") | |
030f4a35 | 69 | |
a1eb1cf1 | 70 | (defvar font-lock-function-name-face 'font-lock-function-name-face |
030f4a35 RS |
71 | "Face to use for function names.") |
72 | ||
a1eb1cf1 RS |
73 | (defvar font-lock-variable-name-face 'font-lock-variable-name-face |
74 | "Face to use for variable names.") | |
75 | ||
76 | (defvar font-lock-keyword-face 'font-lock-keyword-face | |
030f4a35 RS |
77 | "Face to use for keywords.") |
78 | ||
a1eb1cf1 | 79 | (defvar font-lock-type-face 'font-lock-type-face |
030f4a35 RS |
80 | "Face to use for data types.") |
81 | ||
a1eb1cf1 RS |
82 | (defvar font-lock-reference-face 'font-lock-reference-face |
83 | "Face to use for references.") | |
84 | ||
8f261d40 | 85 | (defvar font-lock-no-comments nil |
b89e1134 | 86 | "Non-nil means Font Lock should not fontify comments or strings.") |
8f261d40 | 87 | |
030f4a35 RS |
88 | (make-variable-buffer-local 'font-lock-keywords) |
89 | (defvar font-lock-keywords nil | |
90 | "*The keywords to highlight. | |
a1eb1cf1 RS |
91 | Elements should be of the form: |
92 | ||
826b2925 SM |
93 | MATCHER |
94 | (MATCHER . MATCH) | |
95 | (MATCHER . FACENAME) | |
96 | (MATCHER . HIGHLIGHT) | |
97 | (MATCHER HIGHLIGHT ...) | |
a1eb1cf1 RS |
98 | |
99 | where HIGHLIGHT should be of the form (MATCH FACENAME OVERRIDE LAXMATCH). | |
826b2925 SM |
100 | MATCHER can be either the regexp to search for, or the function name to call to |
101 | make the search (called with one argument, the limit of the search). MATCH is | |
102 | the subexpression of MATCHER to be highlighted. FACENAME is an expression | |
103 | whose value is the face name to use. FACENAME's default attributes may be | |
104 | defined in `font-lock-face-attributes'. | |
a1eb1cf1 RS |
105 | |
106 | OVERRIDE and LAXMATCH are flags. If OVERRIDE is t, existing fontification may | |
107 | be overriden. If `keep', only parts not already fontified are highlighted. | |
826b2925 | 108 | If LAXMATCH is non-nil, no error is signalled if there is no MATCH in MATCHER. |
a1eb1cf1 RS |
109 | |
110 | These regular expressions should not match text which spans lines. While | |
111 | \\[font-lock-fontify-buffer] handles multi-line patterns correctly, updating | |
112 | when you edit the buffer does not, since it considers text one line at a time. | |
113 | ||
114 | Be careful composing regexps for this list; | |
115 | the wrong pattern can dramatically slow things down!") | |
030f4a35 | 116 | |
b89e1134 SM |
117 | (defvar font-lock-defaults nil |
118 | "If set by a major mode, should be the defaults for Font Lock mode. | |
119 | The value should look like the `cdr' of an item in `font-lock-defaults-alist'.") | |
120 | ||
121 | (defvar font-lock-defaults-alist | |
826b2925 | 122 | (let ((tex-mode-defaults '(tex-font-lock-keywords nil nil ((?$ . "\"")))) |
fb512de9 SM |
123 | (c-mode-defaults |
124 | '((c-font-lock-keywords c-font-lock-keywords-1 c-font-lock-keywords-2) | |
125 | nil nil ((?_ . "w")))) | |
126 | (c++-mode-defaults | |
127 | '((c++-font-lock-keywords c++-font-lock-keywords-1 | |
128 | c++-font-lock-keywords-2) | |
129 | nil nil ((?_ . "w")))) | |
130 | (lisp-mode-defaults | |
131 | '((lisp-font-lock-keywords lisp-font-lock-keywords-1 | |
132 | lisp-font-lock-keywords-2) | |
133 | nil nil ((?: . "w") (?- . "w") (?* . "w"))))) | |
826b2925 SM |
134 | (list |
135 | (cons 'bibtex-mode tex-mode-defaults) | |
fb512de9 SM |
136 | (cons 'c++-c-mode c-mode-defaults) |
137 | (cons 'c++-mode c++-mode-defaults) | |
138 | (cons 'c-mode c-mode-defaults) | |
826b2925 SM |
139 | (cons 'emacs-lisp-mode lisp-mode-defaults) |
140 | (cons 'latex-mode tex-mode-defaults) | |
141 | (cons 'lisp-mode lisp-mode-defaults) | |
142 | (cons 'plain-tex-mode tex-mode-defaults) | |
143 | (cons 'scheme-mode lisp-mode-defaults) | |
144 | (cons 'slitex-mode tex-mode-defaults) | |
145 | (cons 'tex-mode tex-mode-defaults))) | |
b89e1134 SM |
146 | "*Alist of default major mode and Font Lock defaults. |
147 | Each item should be a list of the form: | |
148 | (MAJOR-MODE . (FONT-LOCK-KEYWORDS KEYWORDS-ONLY CASE-FOLD FONT-LOCK-SYNTAX)) | |
fb512de9 SM |
149 | where MAJOR-MODE is a symbol, and FONT-LOCK-KEYWORDS may be a symbol or a list |
150 | of symbols. If KEYWORDS-ONLY is non-nil, syntactic fontification (strings and | |
151 | comments) is not performed. If CASE-FOLD is non-nil, the case of the keywords | |
152 | is ignored when fontifying. FONT-LOCK-SYNTAX should be a list of cons pairs of | |
153 | the form (CHAR . STRING), it is used to set the local Font Lock syntax table | |
154 | for keyword fontification.") | |
b89e1134 | 155 | |
030f4a35 RS |
156 | (defvar font-lock-keywords-case-fold-search nil |
157 | "*Non-nil means the patterns in `font-lock-keywords' are case-insensitive.") | |
158 | ||
b056da51 | 159 | (defvar font-lock-syntax-table nil |
799761f0 | 160 | "Non-nil means use this syntax table for fontifying. |
b056da51 RS |
161 | If this is nil, the major mode's syntax table is used.") |
162 | ||
030f4a35 RS |
163 | (defvar font-lock-verbose t |
164 | "*Non-nil means `font-lock-fontify-buffer' should print status messages.") | |
165 | ||
799761f0 SM |
166 | ;;;###autoload |
167 | (defvar font-lock-maximum-decoration nil | |
826b2925 | 168 | "Non-nil means use the maximum decoration for fontifying. |
fb512de9 SM |
169 | If nil, use the default decoration (typically the minimum available). |
170 | If t, use the maximum decoration available. | |
171 | If a number, use that level of decoration (or if not available the maximum).") | |
826b2925 SM |
172 | |
173 | (defvar font-lock-maximum-size | |
174 | (if font-lock-maximum-decoration (* 150 1024) (* 300 1024)) | |
175 | "*If non-nil, the maximum size for buffers. | |
176 | Only buffers less than this can be fontified when Font Lock mode is turned on. | |
177 | If nil, means size is irrelevant.") | |
799761f0 | 178 | |
60b691e2 | 179 | ;;;###autoload |
030f4a35 RS |
180 | (defvar font-lock-mode-hook nil |
181 | "Function or functions to run on entry to Font Lock mode.") | |
a1eb1cf1 RS |
182 | \f |
183 | ;; Colour etc. support. | |
184 | ||
b89e1134 | 185 | (defvar font-lock-display-type nil |
a1eb1cf1 RS |
186 | "A symbol indicating the display Emacs is running under. |
187 | The symbol should be one of `color', `grayscale' or `mono'. | |
188 | If Emacs guesses this display attribute wrongly, either set this variable in | |
b89e1134 | 189 | your `~/.emacs' or set the resource `Emacs.displayType' in your `~/.Xdefaults'. |
a1eb1cf1 RS |
190 | See also `font-lock-background-mode' and `font-lock-face-attributes'.") |
191 | ||
b89e1134 | 192 | (defvar font-lock-background-mode nil |
a1eb1cf1 RS |
193 | "A symbol indicating the Emacs background brightness. |
194 | The symbol should be one of `light' or `dark'. | |
195 | If Emacs guesses this frame attribute wrongly, either set this variable in | |
b89e1134 SM |
196 | your `~/.emacs' or set the resource `Emacs.backgroundMode' in your |
197 | `~/.Xdefaults'. | |
a1eb1cf1 RS |
198 | See also `font-lock-display-type' and `font-lock-face-attributes'.") |
199 | ||
b89e1134 | 200 | (defvar font-lock-face-attributes nil |
a1eb1cf1 RS |
201 | "A list of default attributes to use for face attributes. |
202 | Each element of the list should be of the form | |
203 | ||
204 | (FACE FOREGROUND BACKGROUND BOLD-P ITALIC-P UNDERLINE-P) | |
205 | ||
206 | where FACE should be one of the face symbols `font-lock-comment-face', | |
207 | `font-lock-string-face', `font-lock-keyword-face', `font-lock-type-face', | |
208 | `font-lock-function-name-face', `font-lock-variable-name-face', and | |
209 | `font-lock-reference-face'. A form for each of these face symbols should be | |
210 | provided in the list, but other face symbols and attributes may be given and | |
211 | used in highlighting. See `font-lock-keywords'. | |
212 | ||
213 | Subsequent element items should be the attributes for the corresponding | |
214 | Font Lock mode faces. Attributes FOREGROUND and BACKGROUND should be strings | |
215 | \(default if nil), while BOLD-P, ITALIC-P, and UNDERLINE-P should specify the | |
216 | corresponding face attributes (yes if non-nil). | |
217 | ||
218 | Emacs uses default attributes based on display type and background brightness. | |
219 | See variables `font-lock-display-type' and `font-lock-background-mode'. | |
220 | ||
221 | Resources can be used to over-ride these face attributes. For example, the | |
222 | resource `Emacs.font-lock-comment-face.attributeUnderline' can be used to | |
223 | specify the UNDERLINE-P attribute for face `font-lock-comment-face'.") | |
224 | ||
8862b0db | 225 | (defun font-lock-make-faces (&optional override) |
b89e1134 SM |
226 | "Make faces from `font-lock-face-attributes'. |
227 | A default list is used if this is nil. | |
8862b0db | 228 | If optional OVERRIDE is non-nil, faces that already exist are reset. |
b89e1134 SM |
229 | See `font-lock-make-face' and `list-faces-display'." |
230 | ;; We don't need to `setq' any of these variables, but the user can see what | |
231 | ;; is being used if we do. | |
232 | (if (null font-lock-display-type) | |
233 | (setq font-lock-display-type | |
234 | (let ((display-resource (x-get-resource ".displayType" | |
235 | "DisplayType"))) | |
236 | (cond (display-resource (intern (downcase display-resource))) | |
237 | ((x-display-color-p) 'color) | |
238 | ((x-display-grayscale-p) 'grayscale) | |
239 | (t 'mono))))) | |
240 | (if (null font-lock-background-mode) | |
241 | (setq font-lock-background-mode | |
242 | (let ((bg-resource (x-get-resource ".backgroundMode" | |
243 | "BackgroundMode")) | |
244 | (params (frame-parameters))) | |
245 | (cond (bg-resource (intern (downcase bg-resource))) | |
61392e7b RS |
246 | ((< (apply '+ (x-color-values |
247 | (cdr (assq 'background-color params)))) | |
248 | (/ (apply '+ (x-color-values "white")) 3)) | |
b89e1134 SM |
249 | 'dark) |
250 | (t 'light))))) | |
251 | (if (null font-lock-face-attributes) | |
252 | (setq font-lock-face-attributes | |
253 | (let ((light-bg (eq font-lock-background-mode 'light))) | |
254 | (cond ((memq font-lock-display-type '(mono monochrome)) | |
255 | ;; Emacs 19.25's font-lock defaults: | |
256 | ;;'((font-lock-comment-face nil nil nil t nil) | |
257 | ;; (font-lock-string-face nil nil nil nil t) | |
258 | ;; (font-lock-keyword-face nil nil t nil nil) | |
259 | ;; (font-lock-function-name-face nil nil t t nil) | |
260 | ;; (font-lock-type-face nil nil nil t nil)) | |
261 | (list '(font-lock-comment-face nil nil t t nil) | |
262 | '(font-lock-string-face nil nil nil t nil) | |
263 | '(font-lock-keyword-face nil nil t nil nil) | |
264 | (list | |
265 | 'font-lock-function-name-face | |
266 | (cdr (assq 'background-color (frame-parameters))) | |
267 | (cdr (assq 'foreground-color (frame-parameters))) | |
268 | t nil nil) | |
269 | '(font-lock-variable-name-face nil nil t t nil) | |
270 | '(font-lock-type-face nil nil t nil t) | |
271 | '(font-lock-reference-face nil nil t nil t))) | |
272 | ((memq font-lock-display-type '(grayscale greyscale | |
273 | grayshade greyshade)) | |
274 | (list | |
275 | (list 'font-lock-comment-face | |
4d8765a2 | 276 | nil (if light-bg "Gray80" "DimGray") t t nil) |
b89e1134 | 277 | (list 'font-lock-string-face |
4d8765a2 | 278 | nil (if light-bg "Gray50" "LightGray") nil t nil) |
b89e1134 | 279 | (list 'font-lock-keyword-face |
4d8765a2 | 280 | nil (if light-bg "Gray90" "DimGray") t nil nil) |
b89e1134 SM |
281 | (list 'font-lock-function-name-face |
282 | (cdr (assq 'background-color (frame-parameters))) | |
283 | (cdr (assq 'foreground-color (frame-parameters))) | |
284 | t nil nil) | |
285 | (list 'font-lock-variable-name-face | |
4d8765a2 | 286 | nil (if light-bg "Gray90" "DimGray") t t nil) |
b89e1134 | 287 | (list 'font-lock-type-face |
4d8765a2 | 288 | nil (if light-bg "Gray80" "DimGray") t nil t) |
0caef3e3 | 289 | (list 'font-lock-reference-face |
4d8765a2 | 290 | nil (if light-bg "LightGray" "Gray50") t nil t))) |
b89e1134 SM |
291 | (light-bg ; light colour background |
292 | '((font-lock-comment-face "Firebrick") | |
293 | (font-lock-string-face "RosyBrown") | |
294 | (font-lock-keyword-face "Purple") | |
295 | (font-lock-function-name-face "Blue") | |
296 | (font-lock-variable-name-face "DarkGoldenrod") | |
297 | (font-lock-type-face "DarkOliveGreen") | |
298 | (font-lock-reference-face "CadetBlue"))) | |
299 | (t ; dark colour background | |
300 | '((font-lock-comment-face "OrangeRed") | |
301 | (font-lock-string-face "LightSalmon") | |
302 | (font-lock-keyword-face "LightSteelBlue") | |
303 | (font-lock-function-name-face "LightSkyBlue") | |
304 | (font-lock-variable-name-face "LightGoldenrod") | |
305 | (font-lock-type-face "PaleGreen") | |
306 | (font-lock-reference-face "Aquamarine"))))))) | |
8862b0db SM |
307 | ;; Now make the faces if we have to. |
308 | (mapcar (function (lambda (face-attributes) | |
309 | (let ((face (nth 0 face-attributes))) | |
acedc3e3 RS |
310 | (if override |
311 | (font-lock-make-face face-attributes) | |
312 | (if (not (and (boundp face) (facep (symbol-value face)))) | |
313 | (if (facep face) | |
314 | (set face face) | |
315 | (font-lock-make-face face-attributes))))))) | |
8862b0db | 316 | font-lock-face-attributes)) |
b89e1134 | 317 | |
a1eb1cf1 RS |
318 | (defun font-lock-make-face (face-attributes) |
319 | "Make a face from FACE-ATTRIBUTES. | |
320 | FACE-ATTRIBUTES should be like an element `font-lock-face-attributes', so that | |
321 | the face name is the first item in the list. A variable with the same name as | |
322 | the face is also set; its value is the face name." | |
323 | (let* ((face (nth 0 face-attributes)) | |
324 | (face-name (symbol-name face)) | |
325 | (set-p (function (lambda (face-name resource) | |
326 | (x-get-resource (concat face-name ".attribute" resource) | |
327 | (concat "Face.Attribute" resource))))) | |
328 | (on-p (function (lambda (face-name resource) | |
329 | (let ((set (funcall set-p face-name resource))) | |
330 | (and set (member (downcase set) '("on" "true")))))))) | |
331 | (make-face face) | |
332 | ;; Set attributes not set from X resources (and therefore `make-face'). | |
333 | (or (funcall set-p face-name "Foreground") | |
334 | (condition-case nil | |
335 | (set-face-foreground face (nth 1 face-attributes)) | |
336 | (error nil))) | |
337 | (or (funcall set-p face-name "Background") | |
338 | (condition-case nil | |
339 | (set-face-background face (nth 2 face-attributes)) | |
340 | (error nil))) | |
341 | (if (funcall set-p face-name "Bold") | |
342 | (and (funcall on-p face-name "Bold") (make-face-bold face nil t)) | |
343 | (and (nth 3 face-attributes) (make-face-bold face nil t))) | |
344 | (if (funcall set-p face-name "Italic") | |
345 | (and (funcall on-p face-name "Italic") (make-face-italic face nil t)) | |
346 | (and (nth 4 face-attributes) (make-face-italic face nil t))) | |
347 | (or (funcall set-p face-name "Underline") | |
348 | (set-face-underline-p face (nth 5 face-attributes))) | |
349 | (set face face))) | |
350 | \f | |
351 | ;; Fontification. | |
030f4a35 | 352 | |
a1eb1cf1 RS |
353 | ;; These variables record, for each buffer, the parse state at a particular |
354 | ;; position, always the start of a line. Used to make font-lock-fontify-region | |
355 | ;; faster. | |
030f4a35 RS |
356 | (defvar font-lock-cache-position nil) |
357 | (defvar font-lock-cache-state nil) | |
358 | (make-variable-buffer-local 'font-lock-cache-position) | |
359 | (make-variable-buffer-local 'font-lock-cache-state) | |
360 | ||
a1eb1cf1 | 361 | (defun font-lock-fontify-region (start end &optional loudly) |
030f4a35 RS |
362 | "Put proper face on each string and comment between START and END." |
363 | (save-excursion | |
a1eb1cf1 RS |
364 | (save-restriction |
365 | (widen) | |
366 | (goto-char start) | |
367 | (beginning-of-line) | |
368 | (if loudly (message "Fontifying %s... (syntactically...)" (buffer-name))) | |
799761f0 | 369 | (let ((inhibit-read-only t) (buffer-undo-list t) (buffer-file-name) |
a1eb1cf1 | 370 | (modified (buffer-modified-p)) |
826b2925 | 371 | (old-syntax (syntax-table)) |
799761f0 SM |
372 | (synstart (if comment-start-skip |
373 | (concat "\\s\"\\|" comment-start-skip) | |
374 | "\\s\"")) | |
375 | (comstart (if comment-start-skip | |
376 | (concat "\\s<\\|" comment-start-skip) | |
377 | "\\s<")) | |
a1eb1cf1 RS |
378 | (startline (point)) |
379 | state prev prevstate) | |
826b2925 SM |
380 | (unwind-protect |
381 | (progn | |
382 | (if font-lock-syntax-table | |
383 | (set-syntax-table font-lock-syntax-table)) | |
384 | ;; Find the state at the line-beginning before START. | |
385 | (if (eq startline font-lock-cache-position) | |
386 | (setq state font-lock-cache-state) | |
387 | ;; Find outermost containing sexp. | |
388 | (beginning-of-defun) | |
389 | ;; Find the state at STARTLINE. | |
390 | (while (< (point) startline) | |
391 | (setq state (parse-partial-sexp (point) startline 0))) | |
392 | (setq font-lock-cache-state state | |
393 | font-lock-cache-position (point))) | |
394 | ;; Now find the state precisely at START. | |
395 | (setq state (parse-partial-sexp (point) start nil nil state)) | |
396 | ;; If the region starts inside a string, show the extent of it. | |
a1eb1cf1 | 397 | (if (nth 3 state) |
826b2925 | 398 | (let ((beg (point))) |
a1eb1cf1 | 399 | (while (and (re-search-forward "\\s\"" end 'move) |
826b2925 | 400 | (nth 3 (parse-partial-sexp beg (point) nil nil |
b89e1134 | 401 | state)))) |
a1eb1cf1 | 402 | (put-text-property beg (point) 'face font-lock-string-face) |
826b2925 SM |
403 | (setq state (parse-partial-sexp beg (point) |
404 | nil nil state)))) | |
405 | ;; Likewise for a comment. | |
406 | (if (or (nth 4 state) (nth 7 state)) | |
407 | (let ((beg (point))) | |
408 | (save-restriction | |
409 | (narrow-to-region (point-min) end) | |
410 | (condition-case nil | |
411 | (progn | |
412 | (re-search-backward comstart (point-min) 'move) | |
413 | (forward-comment 1) | |
414 | ;; forward-comment skips all whitespace, | |
415 | ;; so go back to the real end of the comment. | |
416 | (skip-chars-backward " \t")) | |
417 | (error (goto-char end)))) | |
418 | (put-text-property beg (point) 'face | |
419 | font-lock-comment-face) | |
420 | (setq state (parse-partial-sexp beg (point) | |
421 | nil nil state)))) | |
422 | ;; Find each interesting place between here and END. | |
423 | (while (and (< (point) end) | |
424 | (setq prev (point) prevstate state) | |
425 | (re-search-forward synstart end t) | |
426 | (progn | |
427 | ;; Clear out the fonts of what we skip over. | |
428 | (remove-text-properties prev (point) '(face nil)) | |
429 | ;; Verify the state at that place | |
430 | ;; so we don't get fooled by \" or \;. | |
431 | (setq state (parse-partial-sexp prev (point) | |
432 | nil nil state)))) | |
433 | (let ((here (point))) | |
434 | (if (or (nth 4 state) (nth 7 state)) | |
435 | ;; We found a real comment start. | |
436 | (let ((beg (match-beginning 0))) | |
437 | (goto-char beg) | |
438 | (save-restriction | |
439 | (narrow-to-region (point-min) end) | |
440 | (condition-case nil | |
441 | (progn | |
442 | (forward-comment 1) | |
443 | ;; forward-comment skips all whitespace, | |
444 | ;; so go back to the real end of the comment. | |
445 | (skip-chars-backward " \t")) | |
446 | (error (goto-char end)))) | |
447 | (put-text-property beg (point) 'face | |
448 | font-lock-comment-face) | |
449 | (setq state (parse-partial-sexp here (point) | |
450 | nil nil state))) | |
451 | (if (nth 3 state) | |
452 | (let ((beg (match-beginning 0))) | |
453 | (while (and (re-search-forward "\\s\"" end 'move) | |
454 | (nth 3 (parse-partial-sexp | |
455 | here (point) nil nil state)))) | |
456 | (put-text-property beg (point) 'face | |
457 | font-lock-string-face) | |
458 | (setq state (parse-partial-sexp here (point) | |
459 | nil nil state)))))) | |
460 | ;; Make sure PREV is non-nil after the loop | |
461 | ;; only if it was set on the very last iteration. | |
462 | (setq prev nil))) | |
bda60941 SM |
463 | (set-syntax-table old-syntax) |
464 | (and prev | |
465 | (remove-text-properties prev end '(face nil))) | |
466 | (and (buffer-modified-p) | |
467 | (not modified) | |
468 | (set-buffer-modified-p nil))))))) | |
826b2925 | 469 | |
030f4a35 | 470 | |
030f4a35 | 471 | (defun font-lock-unfontify-region (beg end) |
313d590c | 472 | (let ((modified (buffer-modified-p)) |
799761f0 | 473 | (buffer-undo-list t) (inhibit-read-only t) (buffer-file-name)) |
313d590c | 474 | (remove-text-properties beg end '(face nil)) |
826b2925 SM |
475 | (and (buffer-modified-p) |
476 | (not modified) | |
477 | (set-buffer-modified-p nil)))) | |
030f4a35 RS |
478 | |
479 | ;; Called when any modification is made to buffer text. | |
480 | (defun font-lock-after-change-function (beg end old-len) | |
481 | (save-excursion | |
482 | (save-match-data | |
030f4a35 RS |
483 | ;; Discard the cache info if text before it has changed. |
484 | (and font-lock-cache-position | |
485 | (> font-lock-cache-position beg) | |
486 | (setq font-lock-cache-position nil)) | |
a1eb1cf1 | 487 | ;; Rescan between start of line from `beg' and start of line after `end'. |
030f4a35 RS |
488 | (goto-char beg) |
489 | (beginning-of-line) | |
490 | (setq beg (point)) | |
a1eb1cf1 RS |
491 | (goto-char end) |
492 | (forward-line 1) | |
493 | (setq end (point)) | |
1ec9e15b RS |
494 | ;; First scan for strings and comments. |
495 | ;; Must scan from line start in case of | |
a1eb1cf1 | 496 | ;; inserting space into `intfoo () {}', and after widened. |
8f261d40 | 497 | (if font-lock-no-comments |
826b2925 | 498 | (font-lock-unfontify-region beg end) |
a1eb1cf1 | 499 | (font-lock-fontify-region beg end)) |
799761f0 | 500 | ;; Now scan for keywords. |
9e116f87 SM |
501 | (font-lock-hack-keywords beg end)))) |
502 | ||
826b2925 | 503 | ;; The following must be rethought, since keywords can override fontification. |
9e116f87 SM |
504 | ; ;; Now scan for keywords, but not if we are inside a comment now. |
505 | ; (or (and (not font-lock-no-comments) | |
506 | ; (let ((state (parse-partial-sexp beg end nil nil | |
507 | ; font-lock-cache-state))) | |
508 | ; (or (nth 4 state) (nth 7 state)))) | |
509 | ; (font-lock-hack-keywords beg end)) | |
030f4a35 RS |
510 | \f |
511 | ;;; Fontifying arbitrary patterns | |
512 | ||
52436656 | 513 | (defun font-lock-compile-keywords (&optional keywords) |
826b2925 SM |
514 | ;; Compile `font-lock-keywords' into the form (t KEYWORD ...) where KEYWORD |
515 | ;; is the (MATCHER HIGHLIGHT ...) shown in the variable's doc string. | |
52436656 SM |
516 | (let ((keywords (or keywords font-lock-keywords))) |
517 | (setq font-lock-keywords | |
518 | (if (eq (car-safe keywords) t) | |
519 | keywords | |
520 | (cons t | |
521 | (mapcar | |
522 | (function (lambda (item) | |
523 | (cond ((nlistp item) | |
524 | (list item '(0 font-lock-keyword-face))) | |
525 | ((numberp (cdr item)) | |
526 | (list (car item) (list (cdr item) 'font-lock-keyword-face))) | |
527 | ((symbolp (cdr item)) | |
528 | (list (car item) (list 0 (cdr item)))) | |
529 | ((nlistp (nth 1 item)) | |
530 | (list (car item) (cdr item))) | |
531 | (t | |
532 | item)))) | |
533 | keywords)))))) | |
826b2925 SM |
534 | |
535 | (defsubst font-lock-apply-highlight (highlight) | |
536 | "Apply HIGHLIGHT following a match. See `font-lock-keywords'." | |
537 | (let* ((match (nth 0 highlight)) | |
538 | (beg (match-beginning match)) (end (match-end match)) | |
539 | (override (nth 2 highlight))) | |
540 | (cond ((not beg) | |
541 | ;; No match but we might not signal an error | |
542 | (or (nth 3 highlight) (error "Highlight %S failed" highlight))) | |
543 | ((and (not override) (text-property-not-all beg end 'face nil)) | |
544 | ;; Can't override and already fontified | |
545 | nil) | |
546 | ((not (eq override 'keep)) | |
547 | ;; Can override but need not keep existing fontification | |
548 | (put-text-property beg end 'face (eval (nth 1 highlight)))) | |
549 | (t | |
550 | ;; Can override but must keep existing fontification | |
551 | (let ((pos (text-property-any beg end 'face nil)) next | |
552 | (face (eval (nth 1 highlight)))) | |
553 | (while pos | |
554 | (setq next (next-single-property-change pos 'face nil end)) | |
555 | (put-text-property pos next 'face face) | |
556 | (setq pos (text-property-any next end 'face nil)))))))) | |
557 | ||
030f4a35 | 558 | (defun font-lock-hack-keywords (start end &optional loudly) |
a1eb1cf1 | 559 | "Fontify according to `font-lock-keywords' between START and END." |
030f4a35 | 560 | (let ((case-fold-search font-lock-keywords-case-fold-search) |
826b2925 SM |
561 | (keywords (cdr (if (eq (car-safe font-lock-keywords) t) |
562 | font-lock-keywords | |
563 | (font-lock-compile-keywords)))) | |
030f4a35 | 564 | (count 0) |
799761f0 | 565 | (inhibit-read-only t) (buffer-undo-list t) (buffer-file-name) |
313d590c | 566 | (modified (buffer-modified-p)) |
a1eb1cf1 RS |
567 | (old-syntax (syntax-table)) |
568 | (bufname (buffer-name))) | |
b056da51 | 569 | (unwind-protect |
826b2925 | 570 | (let (keyword matcher highlights) |
a1eb1cf1 RS |
571 | (if loudly (message "Fontifying %s... (regexps...)" bufname)) |
572 | (if font-lock-syntax-table (set-syntax-table font-lock-syntax-table)) | |
573 | (while keywords | |
574 | (setq keyword (car keywords) keywords (cdr keywords) | |
826b2925 | 575 | matcher (car keyword) highlights (cdr keyword)) |
b056da51 | 576 | (goto-char start) |
826b2925 SM |
577 | (while (if (stringp matcher) |
578 | (re-search-forward matcher end t) | |
579 | (funcall matcher end)) | |
580 | (mapcar 'font-lock-apply-highlight highlights)) | |
a1eb1cf1 | 581 | (if loudly (message "Fontifying %s... (regexps...%s)" bufname |
b056da51 | 582 | (make-string (setq count (1+ count)) ?.))))) |
bda60941 SM |
583 | (set-syntax-table old-syntax) |
584 | (and (buffer-modified-p) | |
585 | (not modified) | |
586 | (set-buffer-modified-p nil))))) | |
030f4a35 RS |
587 | \f |
588 | ;; The user level functions | |
589 | ||
590 | (defvar font-lock-mode nil) ; for modeline | |
030f4a35 RS |
591 | |
592 | (defvar font-lock-fontified nil) ; whether we have hacked this buffer | |
593 | (put 'font-lock-fontified 'permanent-local t) | |
594 | ||
595 | ;;;###autoload | |
596 | (defun font-lock-mode (&optional arg) | |
597 | "Toggle Font Lock mode. | |
598 | With arg, turn Font Lock mode on if and only if arg is positive. | |
599 | ||
600 | When Font Lock mode is enabled, text is fontified as you type it: | |
601 | ||
a1eb1cf1 RS |
602 | - Comments are displayed in `font-lock-comment-face'; |
603 | - Strings are displayed in `font-lock-string-face'; | |
604 | - Certain other expressions are displayed in other faces according to the | |
605 | value of the variable `font-lock-keywords'. | |
606 | ||
607 | You can enable Font Lock mode in any major mode automatically by turning on in | |
608 | the major mode's hook. For example, put in your ~/.emacs: | |
609 | ||
610 | (add-hook 'c-mode-hook 'turn-on-font-lock) | |
611 | ||
612 | Or for any visited file with the following in your ~/.emacs: | |
613 | ||
614 | (add-hook 'find-file-hooks 'turn-on-font-lock) | |
615 | ||
616 | The default Font Lock mode faces and their attributes are defined in the | |
617 | variable `font-lock-face-attributes', and Font Lock mode default settings in | |
618 | the variable `font-lock-defaults-alist'. | |
030f4a35 | 619 | |
826b2925 | 620 | Where modes support different levels of fontification, you can use the variable |
fb512de9 | 621 | `font-lock-maximum-decoration' to specify which level you generally prefer. |
b89e1134 SM |
622 | When you turn Font Lock mode on/off the buffer is fontified/defontified, though |
623 | fontification occurs only if the buffer is less than `font-lock-maximum-size'. | |
624 | To fontify a buffer without turning on Font Lock mode, and regardless of buffer | |
625 | size, you can use \\[font-lock-fontify-buffer]." | |
030f4a35 | 626 | (interactive "P") |
a1eb1cf1 | 627 | (let ((on-p (if arg (> (prefix-numeric-value arg) 0) (not font-lock-mode)))) |
030f4a35 RS |
628 | (if (equal (buffer-name) " *Compiler Input*") ; hack for bytecomp... |
629 | (setq on-p nil)) | |
a1eb1cf1 RS |
630 | (if (not on-p) |
631 | (remove-hook 'after-change-functions 'font-lock-after-change-function) | |
632 | (make-local-variable 'after-change-functions) | |
633 | (add-hook 'after-change-functions 'font-lock-after-change-function)) | |
030f4a35 RS |
634 | (set (make-local-variable 'font-lock-mode) on-p) |
635 | (cond (on-p | |
636 | (font-lock-set-defaults) | |
7daa8d6b | 637 | (make-local-variable 'before-revert-hook) |
87cd38d6 | 638 | (make-local-variable 'after-revert-hook) |
7daa8d6b KH |
639 | ;; If buffer is reverted, must clean up the state. |
640 | (add-hook 'before-revert-hook 'font-lock-revert-setup) | |
641 | (add-hook 'after-revert-hook 'font-lock-revert-cleanup) | |
030f4a35 | 642 | (run-hooks 'font-lock-mode-hook) |
b89e1134 SM |
643 | (cond (font-lock-fontified |
644 | nil) | |
645 | ((or (null font-lock-maximum-size) | |
646 | (> font-lock-maximum-size (buffer-size))) | |
647 | (font-lock-fontify-buffer)) | |
648 | (font-lock-verbose | |
649 | (message "Fontifying %s... buffer too big." (buffer-name))))) | |
030f4a35 RS |
650 | (font-lock-fontified |
651 | (setq font-lock-fontified nil) | |
7daa8d6b KH |
652 | (remove-hook 'before-revert-hook 'font-lock-revert-setup) |
653 | (remove-hook 'after-revert-hook 'font-lock-revert-cleanup) | |
799761f0 SM |
654 | (font-lock-unfontify-region (point-min) (point-max)) |
655 | (font-lock-thing-lock-cleanup)) | |
656 | (t | |
800479f5 KH |
657 | (remove-hook 'before-revert-hook 'font-lock-revert-setup) |
658 | (remove-hook 'after-revert-hook 'font-lock-revert-cleanup) | |
799761f0 | 659 | (font-lock-thing-lock-cleanup))) |
030f4a35 RS |
660 | (force-mode-line-update))) |
661 | ||
a1eb1cf1 RS |
662 | ;;;###autoload |
663 | (defun turn-on-font-lock () | |
664 | "Unconditionally turn on Font Lock mode." | |
665 | (font-lock-mode 1)) | |
666 | ||
bda60941 | 667 | ;; Turn off other related packages if they're on. I prefer a hook. --sm. |
800479f5 KH |
668 | ;; These explicit calls are easier to understand |
669 | ;; because people know what they will do. | |
bda60941 | 670 | ;; A hook is a mystery because it might do anything whatever. --rms. |
799761f0 SM |
671 | (defun font-lock-thing-lock-cleanup () |
672 | (cond ((and (boundp 'fast-lock-mode) fast-lock-mode) | |
673 | (fast-lock-mode -1)) | |
674 | ((and (boundp 'lazy-lock-mode) lazy-lock-mode) | |
675 | (lazy-lock-mode -1)))) | |
676 | ||
826b2925 SM |
677 | ;; Do something special for these packages after fontifying. I prefer a hook. |
678 | (defun font-lock-after-fontify-buffer () | |
679 | (cond ((and (boundp 'fast-lock-mode) fast-lock-mode) | |
680 | (fast-lock-after-fontify-buffer)) | |
681 | ((and (boundp 'lazy-lock-mode) lazy-lock-mode) | |
682 | (lazy-lock-after-fontify-buffer)))) | |
683 | ||
800479f5 | 684 | ;; If the buffer is about to be reverted, it won't be fontified afterward. |
7daa8d6b KH |
685 | (defun font-lock-revert-setup () |
686 | (setq font-lock-fontified nil)) | |
687 | ||
800479f5 KH |
688 | ;; If the buffer has just been reverted, normally that turns off |
689 | ;; Font Lock mode. So turn the mode back on if necessary. | |
7daa8d6b | 690 | (defun font-lock-revert-cleanup () |
800479f5 | 691 | (font-lock-mode 1)) |
7daa8d6b | 692 | |
a1eb1cf1 | 693 | ;;;###autoload |
030f4a35 | 694 | (defun font-lock-fontify-buffer () |
a1eb1cf1 | 695 | "Fontify the current buffer the way `font-lock-mode' would." |
030f4a35 RS |
696 | (interactive) |
697 | (let ((was-on font-lock-mode) | |
826b2925 SM |
698 | (verbose (and (or font-lock-verbose (interactive-p)) |
699 | (not (zerop (buffer-size))))) | |
a1eb1cf1 | 700 | (modified (buffer-modified-p))) |
b89e1134 | 701 | (set (make-local-variable 'font-lock-fontified) nil) |
a1eb1cf1 | 702 | (if verbose (message "Fontifying %s..." (buffer-name))) |
b89e1134 | 703 | ;; Turn it on to run hooks and get the right `font-lock-keywords' etc. |
366b3ecc | 704 | (or was-on (font-lock-set-defaults)) |
a1eb1cf1 RS |
705 | (condition-case nil |
706 | (save-excursion | |
799761f0 SM |
707 | (if font-lock-no-comments |
708 | (font-lock-unfontify-region (point-min) (point-max)) | |
709 | (font-lock-fontify-region (point-min) (point-max) verbose)) | |
a1eb1cf1 RS |
710 | (font-lock-hack-keywords (point-min) (point-max) verbose) |
711 | (setq font-lock-fontified t)) | |
712 | ;; We don't restore the old fontification, so it's best to unfontify. | |
b89e1134 | 713 | (quit (font-lock-unfontify-region (point-min) (point-max)))) |
a1eb1cf1 RS |
714 | (if verbose (message "Fontifying %s... %s." (buffer-name) |
715 | (if font-lock-fontified "done" "aborted"))) | |
716 | (and (buffer-modified-p) | |
717 | (not modified) | |
799761f0 | 718 | (set-buffer-modified-p nil)) |
826b2925 | 719 | (font-lock-after-fontify-buffer))) |
030f4a35 | 720 | \f |
a1eb1cf1 RS |
721 | ;;; Various information shared by several modes. |
722 | ;;; Information specific to a single mode should go in its load library. | |
030f4a35 | 723 | |
030f4a35 | 724 | (defconst lisp-font-lock-keywords-1 |
a1eb1cf1 | 725 | (list |
030f4a35 RS |
726 | ;; highlight defining forms. This doesn't work too nicely for |
727 | ;; (defun (setf foo) ...) but it does work for (defvar foo) which | |
728 | ;; is more important. | |
a1eb1cf1 | 729 | (list (concat "^(\\(def\\(const\\|ine-key\\(\\|-after\\)\\|var\\)\\)\\>" |
826b2925 | 730 | "[ \t']*\\([^ \t\n\(\)]+\\)?") |
a1eb1cf1 | 731 | '(1 font-lock-keyword-face) '(4 font-lock-variable-name-face nil t)) |
826b2925 SM |
732 | (list (concat "^(\\(def[^ \t\n\(\)]+\\|eval-" |
733 | "\\(a\\(fter-load\\|nd-compile\\)\\|when-compile\\)\\)\\>" | |
734 | "[ \t']*\\([^ \t\n\(\)]+\\)?") | |
735 | '(1 font-lock-keyword-face) '(4 font-lock-function-name-face nil t)) | |
030f4a35 | 736 | ) |
fb512de9 | 737 | "Subdued level highlighting Lisp modes.") |
030f4a35 RS |
738 | |
739 | (defconst lisp-font-lock-keywords-2 | |
799761f0 SM |
740 | (append lisp-font-lock-keywords-1 |
741 | (let ((word-char "[-+a-zA-Z0-9_:*]")) | |
742 | (list | |
743 | ;; | |
bda60941 | 744 | ;; Control structures. ELisp and CLisp combined. |
a1eb1cf1 | 745 | ; ("cond" "if" "while" "let\\*?" "prog[nv12*]?" "catch" "throw" |
fb512de9 SM |
746 | ; "save-restriction" "save-excursion" "save-window-excursion" |
747 | ; "save-selected-window" "save-match-data" "unwind-protect" | |
bda60941 SM |
748 | ; "condition-case" "track-mouse" |
749 | ; "when" "unless" "do" "flet" "labels" "return" "return-from") | |
799761f0 SM |
750 | (cons |
751 | (concat | |
752 | "(\\(" | |
bda60941 SM |
753 | "c\\(atch\\|ond\\(\\|ition-case\\)\\)\\|do\\|flet\\|if\\|" |
754 | "l\\(abels\\|et\\*?\\)\\|prog[nv12*]?\\|return\\(\\|-from\\)\\|" | |
fb512de9 | 755 | "save-\\(excursion\\|match-data\\|restriction\\|" |
bda60941 SM |
756 | "selected-window\\|window-excursion\\)\\|t\\(hrow\\|rack-mouse\\)\\|" |
757 | "un\\(less\\|wind-protect\\)\\|wh\\(en\\|ile\\)" | |
799761f0 | 758 | "\\)\\>") 1) |
799761f0 SM |
759 | ;; |
760 | ;; Function names in emacs-lisp docstrings (in the syntax that | |
761 | ;; `substitute-command-keys' understands). | |
826b2925 SM |
762 | (list (concat "\\\\\\\\\\[\\(" word-char "+\\)]") |
763 | 1 font-lock-reference-face t) | |
799761f0 SM |
764 | ;; |
765 | ;; Words inside `' which tend to be symbol names. | |
a1eb1cf1 | 766 | (list (concat "`\\(" word-char word-char "+\\)'") |
799761f0 SM |
767 | 1 'font-lock-reference-face t) |
768 | ;; | |
bda60941 SM |
769 | ;; CLisp `:' keywords as references. |
770 | (list (concat "\\<:" word-char "+\\>") 0 font-lock-reference-face t) | |
771 | ;; | |
772 | ;; ELisp and CLisp `&' keywords as types. | |
799761f0 SM |
773 | '("\\&\\(optional\\|rest\\|whole\\)\\>" . font-lock-type-face) |
774 | ))) | |
fb512de9 | 775 | "Gaudy level highlighting for Lisp modes.") |
030f4a35 | 776 | |
fb512de9 SM |
777 | (defvar lisp-font-lock-keywords lisp-font-lock-keywords-1 |
778 | "Default expressions to highlight in Lisp modes.") | |
030f4a35 RS |
779 | |
780 | ||
781 | (defconst c-font-lock-keywords-1 nil | |
fb512de9 | 782 | "Subdued level highlighting for C modes.") |
030f4a35 RS |
783 | |
784 | (defconst c-font-lock-keywords-2 nil | |
fb512de9 | 785 | "Gaudy level highlighting for C modes.") |
030f4a35 | 786 | |
1bd50840 | 787 | (defconst c++-font-lock-keywords-1 nil |
fb512de9 | 788 | "Subdued level highlighting for C++ modes.") |
1bd50840 RS |
789 | |
790 | (defconst c++-font-lock-keywords-2 nil | |
fb512de9 | 791 | "Gaudy level highlighting for C++ modes.") |
1bd50840 | 792 | |
b89e1134 SM |
793 | (let ((c-keywords |
794 | ; ("break" "continue" "do" "else" "for" "if" "return" "switch" "while") | |
795 | "break\\|continue\\|do\\|else\\|for\\|if\\|return\\|switch\\|while") | |
796 | (c-type-types | |
a1eb1cf1 RS |
797 | ; ("auto" "extern" "register" "static" "typedef" "struct" "union" "enum" |
798 | ; "signed" "unsigned" "short" "long" "int" "char" "float" "double" | |
b89e1134 SM |
799 | ; "void" "volatile" "const") |
800 | (concat "auto\\|c\\(har\\|onst\\)\\|double\\|e\\(num\\|xtern\\)\\|" | |
801 | "float\\|int\\|long\\|register\\|" | |
802 | "s\\(hort\\|igned\\|t\\(atic\\|ruct\\)\\)\\|typedef\\|" | |
803 | "un\\(ion\\|signed\\)\\|vo\\(id\\|latile\\)")) ; 6 ()s deep. | |
804 | (c++-keywords | |
805 | ; ("break" "continue" "do" "else" "for" "if" "return" "switch" "while" | |
806 | ; "asm" "catch" "delete" "new" "operator" "sizeof" "this" "throw" "try" | |
807 | ; "protected" "private" "public") | |
808 | (concat "asm\\|break\\|c\\(atch\\|ontinue\\)\\|d\\(elete\\|o\\)\\|" | |
809 | "else\\|for\\|if\\|new\\|operator\\|" | |
810 | "p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|return\\|" | |
811 | "s\\(izeof\\|witch\\)\\|t\\(h\\(is\\|row\\)\\|ry\\)\\|while")) | |
812 | (c++-type-types | |
813 | ; ("auto" "extern" "register" "static" "typedef" "struct" "union" "enum" | |
814 | ; "signed" "unsigned" "short" "long" "int" "char" "float" "double" | |
815 | ; "void" "volatile" "const" "class" "inline" "friend" "bool" | |
816 | ; "virtual" "complex" "template") | |
817 | (concat "auto\\|bool\\|c\\(har\\|lass\\|o\\(mplex\\|nst\\)\\)\\|" | |
818 | "double\\|e\\(num\\|xtern\\)\\|f\\(loat\\|riend\\)\\|" | |
819 | "in\\(line\\|t\\)\\|long\\|register\\|" | |
820 | "s\\(hort\\|igned\\|t\\(atic\\|ruct\\)\\)\\|" | |
821 | "t\\(emplate\\|ypedef\\)\\|un\\(ion\\|signed\\)\\|" | |
822 | "v\\(irtual\\|o\\(id\\|latile\\)\\)")) ; 11 ()s deep. | |
a1eb1cf1 | 823 | (ctoken "[a-zA-Z0-9_:~]+")) |
f60f18ae KH |
824 | (setq c-font-lock-keywords-1 |
825 | (list | |
f60f18ae | 826 | ;; |
a1eb1cf1 | 827 | ;; Fontify filenames in #include <...> preprocessor directives. |
f60f18ae KH |
828 | '("^#[ \t]*include[ \t]+\\(<[^>\"\n]+>\\)" 1 font-lock-string-face) |
829 | ;; | |
a1eb1cf1 RS |
830 | ;; Fontify function macro names. |
831 | '("^#[ \t]*define[ \t]+\\(\\(\\sw+\\)(\\)" 2 font-lock-function-name-face) | |
f60f18ae | 832 | ;; |
a1eb1cf1 RS |
833 | ;; Fontify otherwise as symbol names, and the preprocessor directive names. |
834 | '("^\\(#[ \t]*[a-z]+\\)\\>[ \t]*\\(\\sw+\\)?" | |
835 | (1 font-lock-reference-face) (2 font-lock-variable-name-face nil t)) | |
f60f18ae | 836 | ;; |
a1eb1cf1 RS |
837 | ;; Fontify function name definitions (without type on line). |
838 | (list (concat "^\\(" ctoken "\\)[ \t]*(") 1 'font-lock-function-name-face) | |
f60f18ae KH |
839 | )) |
840 | ||
841 | (setq c-font-lock-keywords-2 | |
842 | (append c-font-lock-keywords-1 | |
030f4a35 | 843 | (list |
030f4a35 | 844 | ;; |
a1eb1cf1 | 845 | ;; Fontify all storage classes and type specifiers (before declarations). |
b89e1134 | 846 | (cons (concat "\\<\\(" c-type-types "\\)\\>") 'font-lock-type-face) |
030f4a35 | 847 | ;; |
a1eb1cf1 RS |
848 | ;; Fontify variable/structure name declarations and definitions, or |
849 | ;; function name declarations (plus definitions with type on same line). | |
b89e1134 SM |
850 | (list (concat "\\<\\(" c-type-types "\\)[ \t*]+" |
851 | "\\(" ctoken "[ \t*]+\\)*" | |
852 | "\\(" ctoken "\\)[ \t]*\\((\\)?") | |
853 | 9 | |
854 | '(if (match-beginning 10) | |
855 | font-lock-function-name-face | |
856 | font-lock-variable-name-face)) | |
857 | ;; | |
858 | ;; Fontify function/variable name declarations at the start of the line. | |
859 | ;; (Not everyone follows the GNU convention of function name at the start.) | |
860 | (list (concat "^" ctoken "[ \t*]+" | |
861 | "\\(" ctoken "[ \t*]+\\)*" | |
a1eb1cf1 | 862 | "\\(" ctoken "\\)[ \t]*\\((\\)?") |
b89e1134 SM |
863 | 2 |
864 | '(if (match-beginning 3) | |
865 | font-lock-function-name-face | |
866 | font-lock-variable-name-face)) | |
030f4a35 | 867 | ;; |
a1eb1cf1 | 868 | ;; Fontify variable names declared with structures, or typedef names. |
b89e1134 | 869 | '("}[ \t*]*\\(\\sw+\\)[ \t]*[;,[]" 1 font-lock-variable-name-face) |
030f4a35 | 870 | ;; |
b89e1134 SM |
871 | ;; Fontify all builtin keywords (except case, default and goto; see below). |
872 | (concat "\\<\\(" c-keywords "\\)\\>") | |
030f4a35 | 873 | ;; |
b89e1134 | 874 | ;; Fontify case/goto keywords and targets, and goto tags (incl "default:"). |
a1eb1cf1 RS |
875 | '("\\<\\(case\\|goto\\)\\>[ \t]*\\([^ \t\n:;]+\\)?" |
876 | (1 font-lock-keyword-face) (2 font-lock-reference-face nil t)) | |
877 | '("^[ \t]*\\(\\sw+\\)[ \t]*:" 1 font-lock-reference-face) | |
f60f18ae | 878 | ))) |
1bd50840 | 879 | |
a1eb1cf1 | 880 | (setq c++-font-lock-keywords-1 c-font-lock-keywords-1) |
1bd50840 | 881 | (setq c++-font-lock-keywords-2 |
b89e1134 | 882 | (append c++-font-lock-keywords-1 |
a1eb1cf1 | 883 | (list |
b89e1134 SM |
884 | ;; We don't just add to the C keywords for subtle differences and speed. |
885 | ;; See the above comments for `c-font-lock-keywords-2'. | |
886 | (cons (concat "\\<\\(" c++-type-types "\\)\\>") 'font-lock-type-face) | |
887 | (list (concat "\\<\\(" c++-type-types "\\)[ \t*&]+" | |
888 | "\\(" ctoken "[ \t*&]+\\)*" | |
889 | "\\(" ctoken "\\)[ \t]*\\((\\)?") | |
890 | 14 | |
891 | '(if (match-beginning 15) | |
892 | font-lock-function-name-face | |
893 | font-lock-variable-name-face)) | |
894 | (list (concat "^" ctoken "[ \t*]+" | |
895 | "\\(" ctoken "[ \t*]+\\)*" | |
896 | "\\(" ctoken "\\)[ \t]*\\((\\)?") | |
897 | 2 | |
898 | '(if (match-beginning 3) | |
899 | font-lock-function-name-face | |
900 | font-lock-variable-name-face)) | |
901 | '("}[ \t*]*\\(\\sw+\\)[ \t]*[;,[]" 1 font-lock-variable-name-face) | |
902 | (concat "\\<\\(" c++-keywords "\\)\\>") | |
903 | '("\\<\\(case\\|goto\\)\\>[ \t]*\\([^ \t\n:;]+\\)?" | |
904 | (1 font-lock-keyword-face) (2 font-lock-reference-face nil t)) | |
905 | '("^[ \t]*\\(\\sw+\\)[ \t]*:[^:]" 1 font-lock-reference-face)))) | |
f60f18ae | 906 | ) |
030f4a35 | 907 | |
fb512de9 SM |
908 | (defvar c-font-lock-keywords c-font-lock-keywords-1 |
909 | "Default expressions to highlight in C mode.") | |
030f4a35 | 910 | |
fb512de9 SM |
911 | (defvar c++-font-lock-keywords c++-font-lock-keywords-1 |
912 | "Default expressions to highlight in C++ mode.") | |
030f4a35 | 913 | |
030f4a35 | 914 | (defvar tex-font-lock-keywords |
fb512de9 | 915 | ;; Regexps updated with help from Ulrik Dickow <dickow@nbi.dk>. |
826b2925 SM |
916 | '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}" |
917 | 2 font-lock-function-name-face) | |
918 | ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}" | |
919 | 2 font-lock-reference-face) | |
920 | ;; It seems a bit dubious to use `bold' and `italic' faces since we might | |
921 | ;; not be able to display those fonts. | |
922 | ("{\\\\bf\\([^}]+\\)}" 1 'bold keep) | |
923 | ("{\\\\\\(em\\|it\\|sl\\)\\([^}]+\\)}" 2 'italic keep) | |
924 | ("\\\\\\([a-zA-Z@]+\\|.\\)" . font-lock-keyword-face) | |
925 | ("^[ \t\n]*\\\\def[\\\\@]\\(\\w+\\)" 1 font-lock-function-name-face keep)) | |
030f4a35 RS |
926 | "Additional expressions to highlight in TeX mode.") |
927 | ||
fb512de9 SM |
928 | (defun font-lock-choose-keywords (keywords level) |
929 | ;; Return evaled LEVELth element of KEYWORDS. A LEVEL of nil is equal to a | |
930 | ;; LEVEL of 0, a LEVEL of t is equal to (1- (length KEYWORDS)). | |
bda60941 SM |
931 | (cond ((symbolp keywords) |
932 | keywords) | |
933 | ((numberp level) | |
934 | (or (nth level keywords) (car (reverse keywords)))) | |
935 | ((eq level t) | |
936 | (car (reverse keywords))) | |
937 | (t | |
938 | (car keywords)))) | |
fb512de9 | 939 | |
8f261d40 | 940 | (defun font-lock-set-defaults () |
a1eb1cf1 | 941 | "Set fontification defaults appropriately for this mode. |
b89e1134 | 942 | Sets `font-lock-keywords', `font-lock-no-comments', `font-lock-syntax-table' |
fb512de9 SM |
943 | and `font-lock-keywords-case-fold-search' using `font-lock-defaults' (or, if |
944 | nil, using `font-lock-defaults-alist') and `font-lock-maximum-decoration'." | |
826b2925 | 945 | ;; Set face defaults. |
8862b0db | 946 | (font-lock-make-faces) |
826b2925 SM |
947 | ;; Set fontification defaults. |
948 | (or font-lock-keywords | |
2df1ee23 RS |
949 | (let ((defaults (or font-lock-defaults |
950 | (cdr (assq major-mode font-lock-defaults-alist))))) | |
951 | ;; Keywords? | |
bda60941 SM |
952 | (setq font-lock-keywords |
953 | (font-lock-compile-keywords | |
954 | (eval (font-lock-choose-keywords (nth 0 defaults) | |
955 | font-lock-maximum-decoration)))) | |
2df1ee23 RS |
956 | ;; Syntactic? |
957 | (if (nth 1 defaults) | |
958 | (set (make-local-variable 'font-lock-no-comments) t)) | |
959 | ;; Case fold? | |
960 | (if (nth 2 defaults) | |
961 | (set (make-local-variable 'font-lock-keywords-case-fold-search) t)) | |
962 | ;; Syntax table? | |
b89e1134 SM |
963 | (if (nth 3 defaults) |
964 | (let ((slist (nth 3 defaults))) | |
fb512de9 SM |
965 | (set (make-local-variable 'font-lock-syntax-table) |
966 | (copy-syntax-table (syntax-table))) | |
b89e1134 SM |
967 | (while slist |
968 | (modify-syntax-entry (car (car slist)) (cdr (car slist)) | |
969 | font-lock-syntax-table) | |
970 | (setq slist (cdr slist)))))))) | |
a1eb1cf1 RS |
971 | |
972 | ;; Install ourselves: | |
973 | ||
a1eb1cf1 RS |
974 | (or (assq 'font-lock-mode minor-mode-alist) |
975 | (setq minor-mode-alist (cons '(font-lock-mode " Font") minor-mode-alist))) | |
976 | ||
977 | ;; Provide ourselves: | |
8f261d40 | 978 | |
030f4a35 RS |
979 | (provide 'font-lock) |
980 | ||
981 | ;;; font-lock.el ends here |