font-core.el 12.1 KB
Newer Older
1 2
;;; font-core.el --- Core interface to font-lock

Paul Eggert's avatar
Paul Eggert committed
3
;; Copyright (C) 1992-2020 Free Software Foundation, Inc.
4

5
;; Maintainer: emacs-devel@gnu.org
6
;; Keywords: languages, faces
7
;; Package: emacs
8 9 10

;; This file is part of GNU Emacs.

11
;; GNU Emacs is free software: you can redistribute it and/or modify
12
;; it under the terms of the GNU General Public License as published by
13 14
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
15 16 17 18 19 20 21

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
22
;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
23 24 25 26 27 28 29 30 31 32

;;; Code:

;; This variable is used by mode packages that support Font Lock mode by
;; defining their own keywords to use for `font-lock-keywords'.  (The mode
;; command should make it buffer-local and set it to provide the set up.)
(defvar font-lock-defaults nil
  "Defaults for Font Lock mode specified by the major mode.
Defaults should be of the form:

33
 (KEYWORDS [KEYWORDS-ONLY [CASE-FOLD [SYNTAX-ALIST ...]]])
34

35 36 37 38 39 40 41
KEYWORDS may be a symbol (a variable or function whose value is the keywords
to use for fontification) or a list of symbols (specifying different levels
of fontification).

If KEYWORDS-ONLY is non-nil, syntactic fontification (strings and
comments) is not performed.

42
If CASE-FOLD is non-nil, the case of the keywords is ignored when fontifying.
43

44 45 46 47 48 49
If SYNTAX-ALIST is non-nil, it should be a list of cons pairs of the form
\(CHAR-OR-STRING . STRING) used to set the local Font Lock syntax table, for
keyword and syntactic fontification (see `modify-syntax-entry').

These item elements are used by Font Lock mode to set the variables
`font-lock-keywords', `font-lock-keywords-only',
50
`font-lock-keywords-case-fold-search', `font-lock-syntax-table'.
51 52 53 54 55 56 57 58 59 60 61 62

Further item elements are alists of the form (VARIABLE . VALUE) and are in no
particular order.  Each VARIABLE is made buffer-local before set to VALUE.

Currently, appropriate variables include `font-lock-mark-block-function'.
If this is non-nil, it should be a function with no args used to mark any
enclosing block of text, for fontification via \\[font-lock-fontify-block].
Typical values are `mark-defun' for programming modes or `mark-paragraph' for
textual modes (i.e., the mode-dependent function is known to put point and mark
around a text block relevant to that mode).

Other variables include that for syntactic keyword fontification,
63 64 65 66
`font-lock-syntactic-keywords' and those for buffer-specialized fontification
functions, `font-lock-fontify-buffer-function',
`font-lock-unfontify-buffer-function', `font-lock-fontify-region-function',
`font-lock-unfontify-region-function', and `font-lock-inhibit-thing-lock'.")
67
;;;###autoload
68
(put 'font-lock-defaults 'risky-local-variable t)
69 70
(make-variable-buffer-local 'font-lock-defaults)

71 72 73 74 75
(defvar font-lock-function 'font-lock-default-function
  "A function which is called when `font-lock-mode' is toggled.
It will be passed one argument, which is the current value of
`font-lock-mode'.")

76
;; The mode for which font-lock was initialized, or nil if none.
77
(defvar font-lock-major-mode)
78

79
(define-minor-mode font-lock-mode
80
  "Toggle syntax highlighting in this buffer (Font Lock mode).
81 82 83 84 85

When Font Lock mode is enabled, text is fontified as you type it:

 - Comments are displayed in `font-lock-comment-face';
 - Strings are displayed in `font-lock-string-face';
86 87
 - Certain other expressions are displayed in other faces
   according to the value of the variable `font-lock-keywords'.
88 89 90 91

To customize the faces (colors, fonts, etc.) used by Font Lock for
fontifying different parts of buffer text, use \\[customize-face].

92 93 94
You can enable Font Lock mode in any major mode automatically by
turning on in the major mode's hook.  For example, put in your
~/.emacs:
95

96
 (add-hook \\='c-mode-hook \\='turn-on-font-lock)
97

98 99 100 101
Alternatively, you can use Global Font Lock mode to automagically
turn on Font Lock mode in buffers whose major mode supports it
and whose major mode is one of `font-lock-global-modes'.  For
example, put in your ~/.emacs:
102 103 104

 (global-font-lock-mode t)

105 106 107 108 109
Where major modes support different levels of fontification, you
can use the variable `font-lock-maximum-decoration' to specify
which level you generally prefer.  When you turn Font Lock mode
on/off the buffer is fontified/defontified, though fontification
occurs only if the buffer is less than `font-lock-maximum-size'.
110

111 112 113 114
To add your own highlighting for some major mode, and modify the
highlighting selected automatically via the variable
`font-lock-maximum-decoration', you can use
`font-lock-add-keywords'.
115

116 117
To fontify a buffer, without turning on Font Lock mode and
regardless of buffer size, you can use \\[font-lock-fontify-buffer].
118

119 120 121 122
To fontify a block (the function or paragraph containing point,
or a number of lines around point), perhaps because modification
on the current line caused syntactic change on other lines, you
can use \\[font-lock-fontify-block].
123

124
You can set your own default settings for some mode, by setting a
125 126
buffer local value for `font-lock-defaults', via its mode hook.

127 128
The above is the default behavior of `font-lock-mode'; you may
specify your own function which is called when `font-lock-mode'
129
is toggled via `font-lock-function'."
130
  nil nil nil
131
  :after-hook (font-lock-initial-fontify)
132 133
  ;; Don't turn on Font Lock mode if we don't have a display (we're running a
  ;; batch job) or if the buffer is invisible (the name starts with a space).
134
  (when (or noninteractive (eq (aref (buffer-name) 0) ?\s))
135
    (setq font-lock-mode nil))
136 137 138
  (funcall font-lock-function font-lock-mode)
  ;; Arrange to unfontify this buffer if we change major mode later.
  (if font-lock-mode
139
      (add-hook 'change-major-mode-hook 'font-lock-change-mode nil t)
140
    (remove-hook 'change-major-mode-hook 'font-lock-change-mode t)))
141 142 143 144

;; Get rid of fontification for the old major mode.
;; We do this when changing major modes.
(defun font-lock-change-mode ()
145 146
  (font-lock-mode -1))

147 148
(defun font-lock-defontify ()
  "Clear out all `font-lock-face' properties in current buffer.
149
A major mode that uses `font-lock-face' properties might want to put
150 151 152 153 154 155 156
this function onto `change-major-mode-hook'."
  (let ((modp (buffer-modified-p))
	(inhibit-read-only t))
    (save-restriction
      (widen)
      (remove-list-of-text-properties (point-min) (point-max)
				      '(font-lock-face)))
157
    (restore-buffer-modified-p modp)))
158

159
(defvar font-lock-set-defaults)
160
(defun font-lock-default-function (mode)
161
  ;; Turn on Font Lock mode.
162
  (when mode
163 164 165 166 167 168 169
    (set (make-local-variable 'char-property-alias-alist)
	 (copy-tree char-property-alias-alist))
    ;; Add `font-lock-face' as an alias for the `face' property.
    (let ((elt (assq 'face char-property-alias-alist)))
      (if elt
	  (unless (memq 'font-lock-face (cdr elt))
	    (setcdr elt (nconc (cdr elt) (list 'font-lock-face))))
170
	(push (list 'face 'font-lock-face) char-property-alias-alist))))
171
  ;; Turn off Font Lock mode.
172
  (unless mode
173 174 175 176 177 178 179
    ;; Remove `font-lock-face' as an alias for the `face' property.
    (set (make-local-variable 'char-property-alias-alist)
	 (copy-tree char-property-alias-alist))
    (let ((elt (assq 'face char-property-alias-alist)))
      (when elt
	(setcdr elt (remq 'font-lock-face (cdr elt)))
	(when (null (cdr elt))
180 181 182 183 184
	  (setq char-property-alias-alist
		(delq elt char-property-alias-alist))))))

  ;; Only do hard work if the mode has specified stuff in
  ;; `font-lock-defaults'.
185
  (when (font-lock-specified-p mode)
186
    (font-lock-mode-internal mode)))
187

188 189 190 191 192 193 194 195 196 197
(defun turn-on-font-lock ()
  "Turn on Font Lock mode (only if the terminal can display it)."
  (unless font-lock-mode
    (font-lock-mode)))

;;; Global Font Lock mode.

;; A few people have hassled in the past for a way to make it easier to turn on
;; Font Lock mode, without the user needing to know for which modes s/he has to
;; turn it on, perhaps the same way hilit19.el/hl319.el does.  I've always
Paul Eggert's avatar
Paul Eggert committed
198
;; balked at that way, as I see it as just re-molding the same problem in
199 200 201 202 203 204 205 206 207 208 209 210 211 212
;; another form.  That is; some person would still have to keep track of which
;; modes (which may not even be distributed with Emacs) support Font Lock mode.
;; The list would always be out of date.  And that person might have to be me.

;; Implementation.
;;
;; In a previous discussion the following hack came to mind.  It is a gross
;; hack, but it generally works.  We use the convention that major modes start
;; by calling the function `kill-all-local-variables', which in turn runs
;; functions on the hook variable `change-major-mode-hook'.  We attach our
;; function `font-lock-change-major-mode' to that hook.  Of course, when this
;; hook is run, the major mode is in the process of being changed and we do not
;; know what the final major mode will be.  So, `font-lock-change-major-mode'
;; only (a) notes the name of the current buffer, and (b) adds our function
213
;; `turn-on-font-lock-if-desired' to the hook variables
Luc Teirlinck's avatar
Luc Teirlinck committed
214 215
;; `after-change-major-mode-hook' and `post-command-hook' (for modes
;; that do not yet run `after-change-major-mode-hook').  By the time
216 217 218 219
;; the functions on the first of these hooks to be run are run, the new major
;; mode is assumed to be in place.  This way we get a Font Lock function run
;; when a major mode is turned on, without knowing major modes or their hooks.
;;
Luc Teirlinck's avatar
Luc Teirlinck committed
220 221 222 223 224 225 226
;; Naturally this requires that major modes run `kill-all-local-variables'
;; and `after-change-major-mode-hook', as they are supposed to.  For modes
;; that do not run `after-change-major-mode-hook' yet, `post-command-hook'
;; takes care of things if the mode is set directly or indirectly by
;; an interactive command; however, problems can occur if the mode is
;; set by a timer or process: in that case, proper handling of Font Lock mode
;; may be delayed until the next interactive command.
227 228 229 230 231 232

;; User interface.
;;
;; Although Global Font Lock mode is a pseudo-mode, I think that the user
;; interface should conform to the usual Emacs convention for modes, i.e., a
;; command to toggle the feature (`global-font-lock-mode') with a variable for
233
;; finer control of the mode's behavior (`font-lock-global-modes').
234 235 236 237 238 239 240 241 242
;;
;; The feature should not be enabled by loading font-lock.el, since other
;; mechanisms for turning on Font Lock mode, such as M-x font-lock-mode RET or
;; (add-hook 'c-mode-hook 'turn-on-font-lock), would cause Font Lock mode to be
;; turned on everywhere.  That would not be intuitive or informative because
;; loading a file tells you nothing about the feature or how to control it.  It
;; would also be contrary to the Principle of Least Surprise.  sm.

(defcustom font-lock-global-modes t
Lute Kamstra's avatar
Lute Kamstra committed
243
  "Modes for which Font Lock mode is automagically turned on.
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
Global Font Lock mode is controlled by the command `global-font-lock-mode'.
If nil, means no modes have Font Lock mode automatically turned on.
If t, all modes that support Font Lock mode have it automatically turned on.
If a list, it should be a list of `major-mode' symbol names for which Font Lock
mode should be automatically turned on.  The sense of the list is negated if it
begins with `not'.  For example:
 (c-mode c++-mode)
means that Font Lock mode is turned on for buffers in C and C++ modes only."
  :type '(choice (const :tag "none" nil)
		 (const :tag "all" t)
		 (set :menu-tag "mode specific" :tag "modes"
		      :value (not)
		      (const :tag "Except" not)
		      (repeat :inline t (symbol :tag "mode"))))
  :group 'font-lock)

260 261 262 263 264
(defun turn-on-font-lock-if-desired ()
  (when (cond ((eq font-lock-global-modes t)
	       t)
	      ((eq (car-safe font-lock-global-modes) 'not)
	       (not (memq major-mode (cdr font-lock-global-modes))))
265
	      (t (memq major-mode font-lock-global-modes)))
266 267 268
    (let (inhibit-quit)
      (turn-on-font-lock))))

269
(define-globalized-minor-mode global-font-lock-mode
270
  font-lock-mode turn-on-font-lock-if-desired
271 272 273
  ;; What was this :extra-args thingy for?  --Stef
  ;; :extra-args (dummy)
  :initialize 'custom-initialize-delay
274 275 276
  :init-value (not (or noninteractive emacs-basic-display))
  :group 'font-lock
  :version "22.1")
277 278 279 280 281 282

;;; End of Global Font Lock mode.

(provide 'font-core)

;;; font-core.el ends here