comparison lisp/jit-lock.el @ 41336:36e754afaf7a

(jit-lock-defer-time): New var. (jit-lock-defer-timer, jit-lock-buffers): New vars. (jit-lock-mode): Initialize them. Cancel the timers more carefully. (jit-lock-function): Defer fontification if requested. (jit-lock-stealth-chunk-start): Pay attention to the new non-nil value. (jit-lock-stealth-fontify): Check the new `jit-lock-defer-multiline' text property. (jit-lock-deferred-fontify): New fun.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Wed, 21 Nov 2001 01:30:35 +0000
parents b174db545cfd
children 828432e1e1d4
comparison
equal deleted inserted replaced
41335:b300e8b6992e 41336:36e754afaf7a
125 :type '(choice (const :tag "never" nil) 125 :type '(choice (const :tag "never" nil)
126 (const :tag "always" t) 126 (const :tag "always" t)
127 (other :tag "syntax-driven" syntax-driven)) 127 (other :tag "syntax-driven" syntax-driven))
128 :group 'jit-lock) 128 :group 'jit-lock)
129 129
130 130 (defcustom jit-lock-defer-time nil ;; 0.5
131 "Idle time after which deferred fontification should take place.
132 If nil, fontification is not deferred."
133 :group 'jit-lock
134 :type '(choice (const :tag "never" nil)
135 (number :tag "seconds")))
131 136
132 ;;; Variables that are not customizable. 137 ;;; Variables that are not customizable.
133 138
134 (defvar jit-lock-mode nil 139 (defvar jit-lock-mode nil
135 "Non-nil means Just-in-time Lock mode is active.") 140 "Non-nil means Just-in-time Lock mode is active.")
146 (make-variable-buffer-local 'jit-lock-first-unfontify-pos) 151 (make-variable-buffer-local 'jit-lock-first-unfontify-pos)
147 152
148 153
149 (defvar jit-lock-stealth-timer nil 154 (defvar jit-lock-stealth-timer nil
150 "Timer for stealth fontification in Just-in-time Lock mode.") 155 "Timer for stealth fontification in Just-in-time Lock mode.")
156
157 (defvar jit-lock-defer-timer nil
158 "Timer for deferred fontification in Just-in-time Lock mode.")
159
160 (defvar jit-lock-buffers nil
161 "List of buffers with pending deferred fontification.")
151 162
152 ;;; JIT lock mode 163 ;;; JIT lock mode
153 164
154 (defun jit-lock-mode (arg) 165 (defun jit-lock-mode (arg)
155 "Toggle Just-in-time Lock mode. 166 "Toggle Just-in-time Lock mode.
184 the variable `jit-lock-stealth-nice'." 195 the variable `jit-lock-stealth-nice'."
185 (setq jit-lock-mode arg) 196 (setq jit-lock-mode arg)
186 (cond (;; Turn Just-in-time Lock mode on. 197 (cond (;; Turn Just-in-time Lock mode on.
187 jit-lock-mode 198 jit-lock-mode
188 199
189 ;; Mark the buffer for refontification 200 ;; Mark the buffer for refontification.
190 (jit-lock-refontify) 201 (jit-lock-refontify)
191 202
192 ;; Install an idle timer for stealth fontification. 203 ;; Install an idle timer for stealth fontification.
193 (when (and jit-lock-stealth-time (null jit-lock-stealth-timer)) 204 (when (and jit-lock-stealth-time (null jit-lock-stealth-timer))
194 (setq jit-lock-stealth-timer 205 (setq jit-lock-stealth-timer
195 (run-with-idle-timer jit-lock-stealth-time 206 (run-with-idle-timer jit-lock-stealth-time t
196 jit-lock-stealth-time
197 'jit-lock-stealth-fontify))) 207 'jit-lock-stealth-fontify)))
208
209 ;; Init deferred fontification timer.
210 (when (and jit-lock-defer-time (null jit-lock-defer-timer))
211 (setq jit-lock-defer-timer
212 (run-with-idle-timer jit-lock-defer-time t
213 'jit-lock-deferred-fontify)))
198 214
199 ;; Initialize deferred contextual fontification if requested. 215 ;; Initialize deferred contextual fontification if requested.
200 (when (eq jit-lock-defer-contextually t) 216 (when (eq jit-lock-defer-contextually t)
201 (setq jit-lock-first-unfontify-pos 217 (setq jit-lock-first-unfontify-pos
202 (or jit-lock-first-unfontify-pos (point-max)))) 218 (or jit-lock-first-unfontify-pos (point-max))))
205 (add-hook 'after-change-functions 'jit-lock-after-change nil t) 221 (add-hook 'after-change-functions 'jit-lock-after-change nil t)
206 (add-hook 'fontification-functions 'jit-lock-function)) 222 (add-hook 'fontification-functions 'jit-lock-function))
207 223
208 ;; Turn Just-in-time Lock mode off. 224 ;; Turn Just-in-time Lock mode off.
209 (t 225 (t
210 ;; Cancel our idle timer. 226 ;; Cancel our idle timers.
211 (when jit-lock-stealth-timer 227 (when (and (or jit-lock-stealth-timer jit-lock-defer-timer)
212 (cancel-timer jit-lock-stealth-timer) 228 ;; Only if there's no other buffer using them.
213 (setq jit-lock-stealth-timer nil)) 229 (not (catch 'found
230 (dolist (buf (buffer-list))
231 (with-current-buffer buf
232 (when jit-lock-mode (throw 'found t)))))))
233 (when jit-lock-stealth-timer
234 (cancel-timer jit-lock-stealth-timer)
235 (setq jit-lock-stealth-timer nil))
236 (when jit-lock-defer-timer
237 (cancel-timer jit-lock-defer-timer)
238 (setq jit-lock-defer-timer nil)))
214 239
215 ;; Remove hooks. 240 ;; Remove hooks.
216 (remove-hook 'after-change-functions 'jit-lock-after-change t) 241 (remove-hook 'after-change-functions 'jit-lock-after-change t)
217 (remove-hook 'fontification-functions 'jit-lock-function)))) 242 (remove-hook 'fontification-functions 'jit-lock-function))))
218 243
240 (defun jit-lock-refontify (&optional beg end) 265 (defun jit-lock-refontify (&optional beg end)
241 "Force refontification of the region BEG..END (default whole buffer)." 266 "Force refontification of the region BEG..END (default whole buffer)."
242 (with-buffer-prepared-for-jit-lock 267 (with-buffer-prepared-for-jit-lock
243 (save-restriction 268 (save-restriction
244 (widen) 269 (widen)
245 (add-text-properties (or beg (point-min)) (or end (point-max)) 270 (put-text-property (or beg (point-min)) (or end (point-max))
246 '(fontified nil))))) 271 'fontified nil))))
247 272
248 ;;; On demand fontification. 273 ;;; On demand fontification.
249 274
250 (defun jit-lock-function (start) 275 (defun jit-lock-function (start)
251 "Fontify current buffer starting at position START. 276 "Fontify current buffer starting at position START.
252 This function is added to `fontification-functions' when `jit-lock-mode' 277 This function is added to `fontification-functions' when `jit-lock-mode'
253 is active." 278 is active."
254 (when jit-lock-mode 279 (when jit-lock-mode
255 (jit-lock-fontify-now start (+ start jit-lock-chunk-size)))) 280 (if (null jit-lock-defer-time)
256 281 ;; No deferral.
282 (jit-lock-fontify-now start (+ start jit-lock-chunk-size))
283 ;; Record the buffer for later fontification.
284 (unless (memq (current-buffer) jit-lock-buffers)
285 (push (current-buffer) jit-lock-buffers))
286 ;; 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.
288 (with-buffer-prepared-for-jit-lock
289 (put-text-property start
290 (next-single-property-change
291 start 'fontified nil
292 (min (point-max) (+ start jit-lock-chunk-size)))
293 'fontified 'defer)))))
257 294
258 (defun jit-lock-fontify-now (&optional start end) 295 (defun jit-lock-fontify-now (&optional start end)
259 "Fontify current buffer from START to END. 296 "Fontify current buffer from START to END.
260 Defaults to the whole buffer. END can be out of bounds." 297 Defaults to the whole buffer. END can be out of bounds."
261 (with-buffer-prepared-for-jit-lock 298 (with-buffer-prepared-for-jit-lock
292 (goto-char start) (setq start (line-beginning-position)) 329 (goto-char start) (setq start (line-beginning-position))
293 330
294 ;; Fontify the chunk, and mark it as fontified. 331 ;; Fontify the chunk, and mark it as fontified.
295 ;; We mark it first, to make sure that we don't indefinitely 332 ;; We mark it first, to make sure that we don't indefinitely
296 ;; re-execute this fontification if an error occurs. 333 ;; re-execute this fontification if an error occurs.
297 (add-text-properties start next '(fontified t)) 334 (put-text-property start next 'fontified t)
298 (run-hook-with-args 'jit-lock-functions start next) 335 (run-hook-with-args 'jit-lock-functions start next)
299 336
300 ;; Find the start of the next chunk, if any. 337 ;; Find the start of the next chunk, if any.
301 (setq start (text-property-any next end 'fontified nil))))))))) 338 (setq start (text-property-any next end 'fontified nil)))))))))
302 339
303 340
304 ;;; Stealth fontification. 341 ;;; Stealth fontification.
308 Value is nil if there is nothing more to fontify." 345 Value is nil if there is nothing more to fontify."
309 (if (zerop (buffer-size)) 346 (if (zerop (buffer-size))
310 nil 347 nil
311 (save-restriction 348 (save-restriction
312 (widen) 349 (widen)
313 (let* ((next (text-property-any around (point-max) 'fontified nil)) 350 (let* ((next (text-property-not-all around (point-max) 'fontified t))
314 (prev (previous-single-property-change around 'fontified)) 351 (prev (previous-single-property-change around 'fontified))
315 (prop (get-text-property (max (point-min) (1- around)) 352 (prop (get-text-property (max (point-min) (1- around))
316 'fontified)) 353 'fontified))
317 (start (cond 354 (start (cond
318 ((null prev) 355 ((null prev)
319 ;; There is no property change between AROUND 356 ;; There is no property change between AROUND
320 ;; and the start of the buffer. If PROP is 357 ;; and the start of the buffer. If PROP is
321 ;; non-nil, everything in front of AROUND is 358 ;; non-nil, everything in front of AROUND is
322 ;; fontified, otherwise nothing is fontified. 359 ;; fontified, otherwise nothing is fontified.
323 (if prop 360 (if (eq prop t)
324 nil 361 nil
325 (max (point-min) 362 (max (point-min)
326 (- around (/ jit-lock-chunk-size 2))))) 363 (- around (/ jit-lock-chunk-size 2)))))
327 (prop 364 ((eq prop t)
328 ;; PREV is the start of a region of fontified 365 ;; PREV is the start of a region of fontified
329 ;; text containing AROUND. Start fontifying a 366 ;; text containing AROUND. Start fontifying a
330 ;; chunk size before the end of the unfontified 367 ;; chunk size before the end of the unfontified
331 ;; region in front of that. 368 ;; region in front of that.
332 (max (or (previous-single-property-change prev 'fontified) 369 (max (or (previous-single-property-change prev 'fontified)
347 384
348 (defun jit-lock-stealth-fontify () 385 (defun jit-lock-stealth-fontify ()
349 "Fontify buffers stealthily. 386 "Fontify buffers stealthily.
350 This functions is called after Emacs has been idle for 387 This functions is called after Emacs has been idle for
351 `jit-lock-stealth-time' seconds." 388 `jit-lock-stealth-time' seconds."
389 ;; I used to check `inhibit-read-only' here, but I can't remember why. -stef
352 (unless (or executing-kbd-macro 390 (unless (or executing-kbd-macro
353 (window-minibuffer-p (selected-window))) 391 (window-minibuffer-p (selected-window)))
354 (let ((buffers (buffer-list)) 392 (let ((buffers (buffer-list))
355 minibuffer-auto-raise 393 minibuffer-auto-raise
356 message-log-max) 394 message-log-max)
382 (when jit-lock-first-unfontify-pos 420 (when jit-lock-first-unfontify-pos
383 (save-restriction 421 (save-restriction
384 (widen) 422 (widen)
385 (when (and (>= jit-lock-first-unfontify-pos (point-min)) 423 (when (and (>= jit-lock-first-unfontify-pos (point-min))
386 (< jit-lock-first-unfontify-pos (point-max))) 424 (< jit-lock-first-unfontify-pos (point-max)))
425 ;; If we're in text that matches a complex multi-line
426 ;; font-lock pattern, make sure the whole text will be
427 ;; redisplayed eventually.
428 (when (get-text-property jit-lock-first-unfontify-pos
429 'jit-lock-defer-multiline)
430 (setq jit-lock-first-unfontify-pos
431 (or (previous-single-property-change
432 jit-lock-first-unfontify-pos
433 'jit-lock-defer-multiline)
434 (point-min))))
387 (with-buffer-prepared-for-jit-lock 435 (with-buffer-prepared-for-jit-lock
388 (put-text-property jit-lock-first-unfontify-pos 436 (remove-text-properties
389 (point-max) 'fontified nil)) 437 jit-lock-first-unfontify-pos (point-max)
438 '(fontified nil jit-lock-defer-multiline nil)))
390 (setq jit-lock-first-unfontify-pos (point-max))))) 439 (setq jit-lock-first-unfontify-pos (point-max)))))
391 440
392 ;; In the following code, the `sit-for' calls cause a 441 ;; In the following code, the `sit-for' calls cause a
393 ;; redisplay, so it's required that the 442 ;; redisplay, so it's required that the
394 ;; buffer-modified flag of a buffer that is displayed 443 ;; buffer-modified flag of a buffer that is displayed
395 ;; has the right value---otherwise the mode line of 444 ;; has the right value---otherwise the mode line of
396 ;; an unmodified buffer would show a `*'. 445 ;; an unmodified buffer would show a `*'.
397 (let (start 446 (let (start
398 (nice (or jit-lock-stealth-nice 0)) 447 (nice (or jit-lock-stealth-nice 0))
399 (point (point))) 448 (point (point-min)))
400 (while (and (setq start 449 (while (and (setq start
401 (jit-lock-stealth-chunk-start point)) 450 (jit-lock-stealth-chunk-start point))
402 (sit-for nice)) 451 (sit-for nice))
403 452
453 ;; fontify a block.
454 (jit-lock-fontify-now start (+ start jit-lock-chunk-size))
455 ;; If stealth jit-locking is done backwards, this leads to
456 ;; excessive O(n^2) refontification. -stef
457 ;; (when (>= jit-lock-first-unfontify-pos start)
458 ;; (setq jit-lock-first-unfontify-pos end))
459
404 ;; Wait a little if load is too high. 460 ;; Wait a little if load is too high.
405 (when (and jit-lock-stealth-load 461 (when (and jit-lock-stealth-load
406 (> (car (load-average)) jit-lock-stealth-load)) 462 (> (car (load-average)) jit-lock-stealth-load))
407 (sit-for (or jit-lock-stealth-time 30))) 463 (sit-for (or jit-lock-stealth-time 30)))))))))))))
408
409 ;; Unless there's input pending now, fontify.
410 (unless (input-pending-p)
411 (jit-lock-fontify-now
412 start (+ start jit-lock-chunk-size)))))))))))))
413 464
414 465
415 466
416 ;;; Deferred fontification. 467 ;;; Deferred fontification.
468
469 (defun jit-lock-deferred-fontify ()
470 "Fontify what was deferred."
471 (when jit-lock-buffers
472 ;; Mark the deferred regions back to `fontified = nil'
473 (dolist (buffer jit-lock-buffers)
474 (when (buffer-live-p buffer)
475 (with-current-buffer buffer
476 ;; (message "Jit-Defer %s" (buffer-name))
477 (with-buffer-prepared-for-jit-lock
478 (let ((pos (point-min)))
479 (while
480 (progn
481 (when (eq (get-text-property pos 'fontified) 'defer)
482 (put-text-property
483 pos (setq pos (next-single-property-change
484 pos 'fontified nil (point-max)))
485 'fontified nil))
486 (setq pos (next-single-property-change pos 'fontified)))))))))
487 (setq jit-lock-buffers nil)
488 ;; Force fontification of the visible parts.
489 (let ((jit-lock-defer-time nil))
490 ;; (message "Jit-Defer Now")
491 (sit-for 0)
492 ;; (message "Jit-Defer Done")
493 )))
494
417 495
418 (defun jit-lock-after-change (start end old-len) 496 (defun jit-lock-after-change (start end old-len)
419 "Mark the rest of the buffer as not fontified after a change. 497 "Mark the rest of the buffer as not fontified after a change.
420 Installed on `after-change-functions'. 498 Installed on `after-change-functions'.
421 START and END are the start and end of the changed text. OLD-LEN 499 START and END are the start and end of the changed text. OLD-LEN
433 (goto-char start) 511 (goto-char start)
434 (setq start (line-beginning-position)) 512 (setq start (line-beginning-position))
435 513
436 ;; If we're in text that matches a multi-line font-lock pattern, 514 ;; If we're in text that matches a multi-line font-lock pattern,
437 ;; make sure the whole text will be redisplayed. 515 ;; make sure the whole text will be redisplayed.
516 ;; I'm not sure this is ever necessary and/or sufficient. -stef
438 (when (get-text-property start 'font-lock-multiline) 517 (when (get-text-property start 'font-lock-multiline)
439 (setq start (or (previous-single-property-change 518 (setq start (or (previous-single-property-change
440 start 'font-lock-multiline) 519 start 'font-lock-multiline)
441 (point-min)))) 520 (point-min))))
442 521