comparison lisp/jit-lock.el @ 89909:68c22ea6027c

Sync to HEAD
author Kenichi Handa <handa@m17n.org>
date Fri, 16 Apr 2004 12:51:06 +0000
parents 375f2633d815
children 29e773288013
comparison
equal deleted inserted replaced
89908:ee1402f7b568 89909:68c22ea6027c
1 ;;; jit-lock.el --- just-in-time fontification 1 ;;; jit-lock.el --- just-in-time fontification
2 2
3 ;; Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc. 3 ;; Copyright (C) 1998, 2000, 2001, 2004 Free Software Foundation, Inc.
4 4
5 ;; Author: Gerd Moellmann <gerd@gnu.org> 5 ;; Author: Gerd Moellmann <gerd@gnu.org>
6 ;; Keywords: faces files 6 ;; Keywords: faces files
7 7
8 ;; This file is part of GNU Emacs. 8 ;; This file is part of GNU Emacs.
30 30
31 31
32 (eval-when-compile 32 (eval-when-compile
33 (defmacro with-buffer-unmodified (&rest body) 33 (defmacro with-buffer-unmodified (&rest body)
34 "Eval BODY, preserving the current buffer's modified state." 34 "Eval BODY, preserving the current buffer's modified state."
35 (declare (debug t))
35 (let ((modified (make-symbol "modified"))) 36 (let ((modified (make-symbol "modified")))
36 `(let ((,modified (buffer-modified-p))) 37 `(let ((,modified (buffer-modified-p)))
37 (unwind-protect 38 (unwind-protect
38 (progn ,@body) 39 (progn ,@body)
39 (unless ,modified 40 (unless ,modified
40 (restore-buffer-modified-p nil)))))) 41 (restore-buffer-modified-p nil))))))
41 42
42 (defmacro with-buffer-prepared-for-jit-lock (&rest body) 43 (defmacro with-buffer-prepared-for-jit-lock (&rest body)
43 "Execute BODY in current buffer, overriding several variables. 44 "Execute BODY in current buffer, overriding several variables.
44 Preserves the `buffer-modified-p' state of the current buffer." 45 Preserves the `buffer-modified-p' state of the current buffer."
46 (declare (debug t))
45 `(with-buffer-unmodified 47 `(with-buffer-unmodified
46 (let ((buffer-undo-list t) 48 (let ((buffer-undo-list t)
47 (inhibit-read-only t) 49 (inhibit-read-only t)
48 (inhibit-point-motion-hooks t) 50 (inhibit-point-motion-hooks t)
49 (inhibit-modification-hooks t) 51 (inhibit-modification-hooks t)
53 ,@body)))) 55 ,@body))))
54 56
55 57
56 58
57 ;;; Customization. 59 ;;; Customization.
60
61 (defgroup jit-lock nil
62 "Font Lock support mode to fontify just-in-time."
63 :version "21.1"
64 :group 'font-lock)
58 65
59 (defcustom jit-lock-chunk-size 500 66 (defcustom jit-lock-chunk-size 500
60 "*Jit-lock chunks of this many characters, or smaller." 67 "*Jit-lock chunks of this many characters, or smaller."
61 :type 'integer 68 :type 'integer
62 :group 'jit-lock) 69 :group 'jit-lock)
107 "*If non-nil, means stealth fontification should show status messages." 114 "*If non-nil, means stealth fontification should show status messages."
108 :type 'boolean 115 :type 'boolean
109 :group 'jit-lock) 116 :group 'jit-lock)
110 117
111 118
112 (defcustom jit-lock-defer-contextually 'syntax-driven 119 (defvaralias 'jit-lock-defer-contextually 'jit-lock-contextually)
113 "*If non-nil, means deferred fontification should be syntactically true. 120 (defcustom jit-lock-contextually 'syntax-driven
114 If nil, means deferred fontification occurs only on those lines modified. This 121 "*If non-nil, means fontification should be syntactically true.
122 If nil, means fontification occurs only on those lines modified. This
115 means where modification on a line causes syntactic change on subsequent lines, 123 means where modification on a line causes syntactic change on subsequent lines,
116 those subsequent lines are not refontified to reflect their new context. 124 those subsequent lines are not refontified to reflect their new context.
117 If t, means deferred fontification occurs on those lines modified and all 125 If t, means fontification occurs on those lines modified and all
118 subsequent lines. This means those subsequent lines are refontified to reflect 126 subsequent lines. This means those subsequent lines are refontified to reflect
119 their new syntactic context, either immediately or when scrolling into them. 127 their new syntactic context, after `jit-lock-context-time' seconds.
120 If any other value, e.g., `syntax-driven', means deferred syntactically true 128 If any other value, e.g., `syntax-driven', means syntactically true
121 fontification occurs only if syntactic fontification is performed using the 129 fontification occurs only if syntactic fontification is performed using the
122 buffer mode's syntax table, i.e., only if `font-lock-keywords-only' is nil. 130 buffer mode's syntax table, i.e., only if `font-lock-keywords-only' is nil.
123 131
124 The value of this variable is used when JIT Lock mode is turned on." 132 The value of this variable is used when JIT Lock mode is turned on."
125 :type '(choice (const :tag "never" nil) 133 :type '(choice (const :tag "never" nil)
126 (const :tag "always" t) 134 (const :tag "always" t)
127 (other :tag "syntax-driven" syntax-driven)) 135 (other :tag "syntax-driven" syntax-driven))
128 :group 'jit-lock) 136 :group 'jit-lock)
129 137
138 (defcustom jit-lock-context-time 0.5
139 "Idle time after which text is contextually refontified, if applicable."
140 :type '(number :tag "seconds"))
141
130 (defcustom jit-lock-defer-time nil ;; 0.25 142 (defcustom jit-lock-defer-time nil ;; 0.25
131 "Idle time after which deferred fontification should take place. 143 "Idle time after which deferred fontification should take place.
132 If nil, fontification is not deferred." 144 If nil, fontification is not deferred."
133 :group 'jit-lock 145 :group 'jit-lock
134 :type '(choice (const :tag "never" nil) 146 :type '(choice (const :tag "never" nil)
143 (defvar jit-lock-functions nil 155 (defvar jit-lock-functions nil
144 "Functions to do the actual fontification. 156 "Functions to do the actual fontification.
145 They are called with two arguments: the START and END of the region to fontify.") 157 They are called with two arguments: the START and END of the region to fontify.")
146 (make-variable-buffer-local 'jit-lock-functions) 158 (make-variable-buffer-local 'jit-lock-functions)
147 159
148 (defvar jit-lock-first-unfontify-pos nil 160 (defvar jit-lock-context-unfontify-pos nil
149 "Consider text after this position as contextually unfontified. 161 "Consider text after this position as contextually unfontified.
150 If nil, contextual fontification is disabled.") 162 If nil, contextual fontification is disabled.")
151 (make-variable-buffer-local 'jit-lock-first-unfontify-pos) 163 (make-variable-buffer-local 'jit-lock-context-unfontify-pos)
152 164
153 165
154 (defvar jit-lock-stealth-timer nil 166 (defvar jit-lock-stealth-timer nil
155 "Timer for stealth fontification in Just-in-time Lock mode.") 167 "Timer for stealth fontification in Just-in-time Lock mode.")
156 168 (defvar jit-lock-context-timer nil
169 "Timer for context fontification in Just-in-time Lock mode.")
157 (defvar jit-lock-defer-timer nil 170 (defvar jit-lock-defer-timer nil
158 "Timer for deferred fontification in Just-in-time Lock mode.") 171 "Timer for deferred fontification in Just-in-time Lock mode.")
159 172
160 (defvar jit-lock-buffers nil 173 (defvar jit-lock-defer-buffers nil
161 "List of buffers with pending deferred fontification.") 174 "List of buffers with pending deferred fontification.")
162 175
163 ;;; JIT lock mode 176 ;;; JIT lock mode
164 177
165 (defun jit-lock-mode (arg) 178 (defun jit-lock-mode (arg)
179 - Stealthy buffer fontification if `jit-lock-stealth-time' is non-nil. 192 - Stealthy buffer fontification if `jit-lock-stealth-time' is non-nil.
180 This means remaining unfontified areas of buffers are fontified if Emacs has 193 This means remaining unfontified areas of buffers are fontified if Emacs has
181 been idle for `jit-lock-stealth-time' seconds, while Emacs remains idle. 194 been idle for `jit-lock-stealth-time' seconds, while Emacs remains idle.
182 This is useful if any buffer has any deferred fontification. 195 This is useful if any buffer has any deferred fontification.
183 196
184 - Deferred context fontification if `jit-lock-defer-contextually' is 197 - Deferred context fontification if `jit-lock-contextually' is
185 non-nil. This means fontification updates the buffer corresponding to 198 non-nil. This means fontification updates the buffer corresponding to
186 true syntactic context, after `jit-lock-stealth-time' seconds of Emacs 199 true syntactic context, after `jit-lock-context-time' seconds of Emacs
187 idle time, while Emacs remains idle. Otherwise, fontification occurs 200 idle time, while Emacs remains idle. Otherwise, fontification occurs
188 on modified lines only, and subsequent lines can remain fontified 201 on modified lines only, and subsequent lines can remain fontified
189 corresponding to previous syntactic contexts. This is useful where 202 corresponding to previous syntactic contexts. This is useful where
190 strings or comments span lines. 203 strings or comments span lines.
191 204
210 (when (and jit-lock-defer-time (null jit-lock-defer-timer)) 223 (when (and jit-lock-defer-time (null jit-lock-defer-timer))
211 (setq jit-lock-defer-timer 224 (setq jit-lock-defer-timer
212 (run-with-idle-timer jit-lock-defer-time t 225 (run-with-idle-timer jit-lock-defer-time t
213 'jit-lock-deferred-fontify))) 226 'jit-lock-deferred-fontify)))
214 227
215 ;; Initialize deferred contextual fontification if requested. 228 ;; Initialize contextual fontification if requested.
216 (when (eq jit-lock-defer-contextually t) 229 (when (eq jit-lock-contextually t)
217 (setq jit-lock-first-unfontify-pos 230 (unless jit-lock-context-timer
218 (or jit-lock-first-unfontify-pos (point-max)))) 231 (setq jit-lock-context-timer
232 (run-with-idle-timer jit-lock-context-time t
233 'jit-lock-context-fontify)))
234 (setq jit-lock-context-unfontify-pos
235 (or jit-lock-context-unfontify-pos (point-max))))
219 236
220 ;; Setup our hooks. 237 ;; Setup our hooks.
221 (add-hook 'after-change-functions 'jit-lock-after-change nil t) 238 (add-hook 'after-change-functions 'jit-lock-after-change nil t)
222 (add-hook 'fontification-functions 'jit-lock-function)) 239 (add-hook 'fontification-functions 'jit-lock-function))
223 240
224 ;; Turn Just-in-time Lock mode off. 241 ;; Turn Just-in-time Lock mode off.
225 (t 242 (t
226 ;; Cancel our idle timers. 243 ;; Cancel our idle timers.
227 (when (and (or jit-lock-stealth-timer jit-lock-defer-timer) 244 (when (and (or jit-lock-stealth-timer jit-lock-defer-timer
245 jit-lock-context-timer)
228 ;; Only if there's no other buffer using them. 246 ;; Only if there's no other buffer using them.
229 (not (catch 'found 247 (not (catch 'found
230 (dolist (buf (buffer-list)) 248 (dolist (buf (buffer-list))
231 (with-current-buffer buf 249 (with-current-buffer buf
232 (when jit-lock-mode (throw 'found t))))))) 250 (when jit-lock-mode (throw 'found t)))))))
233 (when jit-lock-stealth-timer 251 (when jit-lock-stealth-timer
234 (cancel-timer jit-lock-stealth-timer) 252 (cancel-timer jit-lock-stealth-timer)
235 (setq jit-lock-stealth-timer nil)) 253 (setq jit-lock-stealth-timer nil))
254 (when jit-lock-context-timer
255 (cancel-timer jit-lock-context-timer)
256 (setq jit-lock-context-timer nil))
236 (when jit-lock-defer-timer 257 (when jit-lock-defer-timer
237 (cancel-timer jit-lock-defer-timer) 258 (cancel-timer jit-lock-defer-timer)
238 (setq jit-lock-defer-timer nil))) 259 (setq jit-lock-defer-timer nil)))
239 260
240 ;; Remove hooks. 261 ;; Remove hooks.
246 "Register FUN as a fontification function to be called in this buffer. 267 "Register FUN as a fontification function to be called in this buffer.
247 FUN will be called with two arguments START and END indicating the region 268 FUN will be called with two arguments START and END indicating the region
248 that needs to be (re)fontified. 269 that needs to be (re)fontified.
249 If non-nil, CONTEXTUAL means that a contextual fontification would be useful." 270 If non-nil, CONTEXTUAL means that a contextual fontification would be useful."
250 (add-hook 'jit-lock-functions fun nil t) 271 (add-hook 'jit-lock-functions fun nil t)
251 (when (and contextual jit-lock-defer-contextually) 272 (when (and contextual jit-lock-contextually)
252 (set (make-local-variable 'jit-lock-defer-contextually) t)) 273 (set (make-local-variable 'jit-lock-contextually) t))
253 (jit-lock-mode t)) 274 (jit-lock-mode t))
254 275
255 (defun jit-lock-unregister (fun) 276 (defun jit-lock-unregister (fun)
256 "Unregister FUN as a fontification function. 277 "Unregister FUN as a fontification function.
257 Only applies to the current buffer." 278 Only applies to the current buffer."
279 (when jit-lock-mode 300 (when jit-lock-mode
280 (if (null jit-lock-defer-time) 301 (if (null jit-lock-defer-time)
281 ;; No deferral. 302 ;; No deferral.
282 (jit-lock-fontify-now start (+ start jit-lock-chunk-size)) 303 (jit-lock-fontify-now start (+ start jit-lock-chunk-size))
283 ;; Record the buffer for later fontification. 304 ;; Record the buffer for later fontification.
284 (unless (memq (current-buffer) jit-lock-buffers) 305 (unless (memq (current-buffer) jit-lock-defer-buffers)
285 (push (current-buffer) jit-lock-buffers)) 306 (push (current-buffer) jit-lock-defer-buffers))
286 ;; Mark the area as defer-fontified so that the redisplay engine 307 ;; Mark the area as defer-fontified so that the redisplay engine
287 ;; is happy and so that the idle timer can find the places to fontify. 308 ;; is happy and so that the idle timer can find the places to fontify.
288 (with-buffer-prepared-for-jit-lock 309 (with-buffer-prepared-for-jit-lock
289 (put-text-property start 310 (put-text-property start
290 (next-single-property-change 311 (next-single-property-change
328 349
329 ;; Fontify the chunk, and mark it as fontified. 350 ;; Fontify the chunk, and mark it as fontified.
330 ;; We mark it first, to make sure that we don't indefinitely 351 ;; We mark it first, to make sure that we don't indefinitely
331 ;; re-execute this fontification if an error occurs. 352 ;; re-execute this fontification if an error occurs.
332 (put-text-property start next 'fontified t) 353 (put-text-property start next 'fontified t)
333 (run-hook-with-args 'jit-lock-functions start next) 354 (condition-case err
355 (run-hook-with-args 'jit-lock-functions start next)
356 ;; If the user quits (which shouldn't happen in normal on-the-fly
357 ;; jit-locking), make sure the fontification will be performed
358 ;; before displaying the block again.
359 (quit (put-text-property start next 'fontified nil)
360 (funcall 'signal (car err) (cdr err))))
334 361
335 ;; Find the start of the next chunk, if any. 362 ;; Find the start of the next chunk, if any.
336 (setq start (text-property-any next end 'fontified nil)))))))) 363 (setq start (text-property-any next end 'fontified nil))))))))
337 364
338 365
388 (unless (or executing-kbd-macro 415 (unless (or executing-kbd-macro
389 (window-minibuffer-p (selected-window))) 416 (window-minibuffer-p (selected-window)))
390 (let ((buffers (buffer-list)) 417 (let ((buffers (buffer-list))
391 minibuffer-auto-raise 418 minibuffer-auto-raise
392 message-log-max) 419 message-log-max)
393 (while (and buffers (not (input-pending-p))) 420 (with-local-quit
394 (let ((buffer (car buffers))) 421 (while (and buffers (not (input-pending-p)))
395 (setq buffers (cdr buffers)) 422 (with-current-buffer (pop buffers)
396
397 (with-current-buffer buffer
398 (when jit-lock-mode 423 (when jit-lock-mode
399 ;; This is funny. Calling sit-for with 3rd arg non-nil 424 ;; This is funny. Calling sit-for with 3rd arg non-nil
400 ;; so that it doesn't redisplay, internally calls 425 ;; so that it doesn't redisplay, internally calls
401 ;; wait_reading_process_input also with a parameter 426 ;; wait_reading_process_input also with a parameter
402 ;; saying "don't redisplay." Since this function here 427 ;; saying "don't redisplay." Since this function here
412 437
413 (with-temp-message (if jit-lock-stealth-verbose 438 (with-temp-message (if jit-lock-stealth-verbose
414 (concat "JIT stealth lock " 439 (concat "JIT stealth lock "
415 (buffer-name))) 440 (buffer-name)))
416 441
417 ;; Perform deferred unfontification, if any.
418 (when jit-lock-first-unfontify-pos
419 (save-restriction
420 (widen)
421 (when (and (>= jit-lock-first-unfontify-pos (point-min))
422 (< jit-lock-first-unfontify-pos (point-max)))
423 ;; If we're in text that matches a complex multi-line
424 ;; font-lock pattern, make sure the whole text will be
425 ;; redisplayed eventually.
426 (when (get-text-property jit-lock-first-unfontify-pos
427 'jit-lock-defer-multiline)
428 (setq jit-lock-first-unfontify-pos
429 (or (previous-single-property-change
430 jit-lock-first-unfontify-pos
431 'jit-lock-defer-multiline)
432 (point-min))))
433 (with-buffer-prepared-for-jit-lock
434 (remove-text-properties
435 jit-lock-first-unfontify-pos (point-max)
436 '(fontified nil jit-lock-defer-multiline nil)))
437 (setq jit-lock-first-unfontify-pos (point-max)))))
438
439 ;; In the following code, the `sit-for' calls cause a 442 ;; In the following code, the `sit-for' calls cause a
440 ;; redisplay, so it's required that the 443 ;; redisplay, so it's required that the
441 ;; buffer-modified flag of a buffer that is displayed 444 ;; buffer-modified flag of a buffer that is displayed
442 ;; has the right value---otherwise the mode line of 445 ;; has the right value---otherwise the mode line of
443 ;; an unmodified buffer would show a `*'. 446 ;; an unmodified buffer would show a `*'.
450 453
451 ;; fontify a block. 454 ;; fontify a block.
452 (jit-lock-fontify-now start (+ start jit-lock-chunk-size)) 455 (jit-lock-fontify-now start (+ start jit-lock-chunk-size))
453 ;; If stealth jit-locking is done backwards, this leads to 456 ;; If stealth jit-locking is done backwards, this leads to
454 ;; excessive O(n^2) refontification. -stef 457 ;; excessive O(n^2) refontification. -stef
455 ;; (when (>= jit-lock-first-unfontify-pos start) 458 ;; (when (>= jit-lock-context-unfontify-pos start)
456 ;; (setq jit-lock-first-unfontify-pos end)) 459 ;; (setq jit-lock-context-unfontify-pos end))
457 460
458 ;; Wait a little if load is too high. 461 ;; Wait a little if load is too high.
459 (when (and jit-lock-stealth-load 462 (when (and jit-lock-stealth-load
460 (> (car (load-average)) jit-lock-stealth-load)) 463 (> (car (load-average)) jit-lock-stealth-load))
461 (sit-for (or jit-lock-stealth-time 30))))))))))))) 464 (sit-for (or jit-lock-stealth-time 30)))))))))))))
464 467
465 ;;; Deferred fontification. 468 ;;; Deferred fontification.
466 469
467 (defun jit-lock-deferred-fontify () 470 (defun jit-lock-deferred-fontify ()
468 "Fontify what was deferred." 471 "Fontify what was deferred."
469 (when jit-lock-buffers 472 (when jit-lock-defer-buffers
470 ;; Mark the deferred regions back to `fontified = nil' 473 ;; Mark the deferred regions back to `fontified = nil'
471 (dolist (buffer jit-lock-buffers) 474 (dolist (buffer jit-lock-defer-buffers)
472 (when (buffer-live-p buffer) 475 (when (buffer-live-p buffer)
473 (with-current-buffer buffer 476 (with-current-buffer buffer
474 ;; (message "Jit-Defer %s" (buffer-name)) 477 ;; (message "Jit-Defer %s" (buffer-name))
475 (with-buffer-prepared-for-jit-lock 478 (with-buffer-prepared-for-jit-lock
476 (let ((pos (point-min))) 479 (let ((pos (point-min)))
480 (put-text-property 483 (put-text-property
481 pos (setq pos (next-single-property-change 484 pos (setq pos (next-single-property-change
482 pos 'fontified nil (point-max))) 485 pos 'fontified nil (point-max)))
483 'fontified nil)) 486 'fontified nil))
484 (setq pos (next-single-property-change pos 'fontified))))))))) 487 (setq pos (next-single-property-change pos 'fontified)))))))))
485 (setq jit-lock-buffers nil) 488 (setq jit-lock-defer-buffers nil)
486 ;; Force fontification of the visible parts. 489 ;; Force fontification of the visible parts.
487 (let ((jit-lock-defer-time nil)) 490 (let ((jit-lock-defer-time nil))
488 ;; (message "Jit-Defer Now") 491 ;; (message "Jit-Defer Now")
489 (sit-for 0) 492 (sit-for 0)
490 ;; (message "Jit-Defer Done") 493 ;; (message "Jit-Defer Done")
491 ))) 494 )))
492 495
496
497 (defun jit-lock-context-fontify ()
498 "Refresh fontification to take new context into account."
499 (dolist (buffer (buffer-list))
500 (with-current-buffer buffer
501 (when jit-lock-context-unfontify-pos
502 ;; (message "Jit-Context %s" (buffer-name))
503 (save-restriction
504 (widen)
505 (when (and (>= jit-lock-context-unfontify-pos (point-min))
506 (< jit-lock-context-unfontify-pos (point-max)))
507 ;; If we're in text that matches a complex multi-line
508 ;; font-lock pattern, make sure the whole text will be
509 ;; redisplayed eventually.
510 ;; Despite its name, we treat jit-lock-defer-multiline here
511 ;; rather than in jit-lock-defer since it has to do with multiple
512 ;; lines, i.e. with context.
513 (when (get-text-property jit-lock-context-unfontify-pos
514 'jit-lock-defer-multiline)
515 (setq jit-lock-context-unfontify-pos
516 (or (previous-single-property-change
517 jit-lock-context-unfontify-pos
518 'jit-lock-defer-multiline)
519 (point-min))))
520 (with-buffer-prepared-for-jit-lock
521 ;; Force contextual refontification.
522 (remove-text-properties
523 jit-lock-context-unfontify-pos (point-max)
524 '(fontified nil jit-lock-defer-multiline nil)))
525 (setq jit-lock-context-unfontify-pos (point-max))))))))
493 526
494 (defun jit-lock-after-change (start end old-len) 527 (defun jit-lock-after-change (start end old-len)
495 "Mark the rest of the buffer as not fontified after a change. 528 "Mark the rest of the buffer as not fontified after a change.
496 Installed on `after-change-functions'. 529 Installed on `after-change-functions'.
497 START and END are the start and end of the changed text. OLD-LEN 530 START and END are the start and end of the changed text. OLD-LEN
520 ;; Make sure we change at least one char (in case of deletions). 553 ;; Make sure we change at least one char (in case of deletions).
521 (setq end (min (max end (1+ start)) (point-max))) 554 (setq end (min (max end (1+ start)) (point-max)))
522 ;; Request refontification. 555 ;; Request refontification.
523 (put-text-property start end 'fontified nil)) 556 (put-text-property start end 'fontified nil))
524 ;; Mark the change for deferred contextual refontification. 557 ;; Mark the change for deferred contextual refontification.
525 (when jit-lock-first-unfontify-pos 558 (when jit-lock-context-unfontify-pos
526 (setq jit-lock-first-unfontify-pos 559 (setq jit-lock-context-unfontify-pos
527 (min jit-lock-first-unfontify-pos start)))))) 560 (min jit-lock-context-unfontify-pos start))))))
528 561
529 (provide 'jit-lock) 562 (provide 'jit-lock)
530 563
564 ;;; arch-tag: 56b5de6e-f581-453b-bb97-49c39372ff9e
531 ;;; jit-lock.el ends here 565 ;;; jit-lock.el ends here