aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/jit-lock.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/jit-lock.el')
-rw-r--r--lisp/jit-lock.el210
1 files changed, 110 insertions, 100 deletions
diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el
index 0e131b665ef..89959ad8525 100644
--- a/lisp/jit-lock.el
+++ b/lisp/jit-lock.el
@@ -31,6 +31,8 @@
31 31
32 32
33(eval-when-compile 33(eval-when-compile
34 (require 'cl)
35
34 (defmacro with-buffer-unmodified (&rest body) 36 (defmacro with-buffer-unmodified (&rest body)
35 "Eval BODY, preserving the current buffer's modified state." 37 "Eval BODY, preserving the current buffer's modified state."
36 (declare (debug t)) 38 (declare (debug t))
@@ -169,6 +171,8 @@ If nil, contextual fontification is disabled.")
169 171
170(defvar jit-lock-stealth-timer nil 172(defvar jit-lock-stealth-timer nil
171 "Timer for stealth fontification in Just-in-time Lock mode.") 173 "Timer for stealth fontification in Just-in-time Lock mode.")
174(defvar jit-lock-stealth-repeat-timer nil
175 "Timer for repeated stealth fontification in Just-in-time Lock mode.")
172(defvar jit-lock-context-timer nil 176(defvar jit-lock-context-timer nil
173 "Timer for context fontification in Just-in-time Lock mode.") 177 "Timer for context fontification in Just-in-time Lock mode.")
174(defvar jit-lock-defer-timer nil 178(defvar jit-lock-defer-timer nil
@@ -176,6 +180,8 @@ If nil, contextual fontification is disabled.")
176 180
177(defvar jit-lock-defer-buffers nil 181(defvar jit-lock-defer-buffers nil
178 "List of buffers with pending deferred fontification.") 182 "List of buffers with pending deferred fontification.")
183(defvar jit-lock-stealth-buffers nil
184 "List of buffers that are being fontified stealthily.")
179 185
180;;; JIT lock mode 186;;; JIT lock mode
181 187
@@ -223,6 +229,13 @@ the variable `jit-lock-stealth-nice'."
223 (run-with-idle-timer jit-lock-stealth-time t 229 (run-with-idle-timer jit-lock-stealth-time t
224 'jit-lock-stealth-fontify))) 230 'jit-lock-stealth-fontify)))
225 231
232 ;; Create, but do not activate, the idle timer for repeated
233 ;; stealth fontification.
234 (when (and jit-lock-stealth-time (null jit-lock-stealth-repeat-timer))
235 (setq jit-lock-stealth-repeat-timer (timer-create))
236 (timer-set-function jit-lock-stealth-repeat-timer
237 'jit-lock-stealth-fontify '(t)))
238
226 ;; Init deferred fontification timer. 239 ;; Init deferred fontification timer.
227 (when (and jit-lock-defer-time (null jit-lock-defer-timer)) 240 (when (and jit-lock-defer-time (null jit-lock-defer-timer))
228 (setq jit-lock-defer-timer 241 (setq jit-lock-defer-timer
@@ -331,7 +344,7 @@ Defaults to the whole buffer. END can be out of bounds."
331 ;; from the end of a buffer to its start, can do repeated 344 ;; from the end of a buffer to its start, can do repeated
332 ;; `parse-partial-sexp' starting from `point-min', which can 345 ;; `parse-partial-sexp' starting from `point-min', which can
333 ;; take a long time in a large buffer. 346 ;; take a long time in a large buffer.
334 (let (next) 347 (let ((orig-start start) next)
335 (save-match-data 348 (save-match-data
336 ;; Fontify chunks beginning at START. The end of a 349 ;; Fontify chunks beginning at START. The end of a
337 ;; chunk is either `end', or the start of a region 350 ;; chunk is either `end', or the start of a region
@@ -374,6 +387,26 @@ Defaults to the whole buffer. END can be out of bounds."
374 (quit (put-text-property start next 'fontified nil) 387 (quit (put-text-property start next 'fontified nil)
375 (funcall 'signal (car err) (cdr err)))) 388 (funcall 'signal (car err) (cdr err))))
376 389
390 ;; The redisplay engine has already rendered the buffer up-to
391 ;; `orig-start' and won't notice if the above jit-lock-functions
392 ;; changed the appearance of any part of the buffer prior
393 ;; to that. So if `start' is before `orig-start', we need to
394 ;; cause a new redisplay cycle after this one so that any changes
395 ;; are properly reflected on screen.
396 ;; To make such repeated redisplay happen less often, we can
397 ;; eagerly extend the refontified region with
398 ;; jit-lock-after-change-extend-region-functions.
399 (when (< start orig-start)
400 (lexical-let ((start start)
401 (orig-start orig-start)
402 (buf (current-buffer)))
403 (run-with-timer
404 0 nil (lambda ()
405 (with-current-buffer buf
406 (with-buffer-prepared-for-jit-lock
407 (put-text-property start orig-start
408 'fontified t)))))))
409
377 ;; Find the start of the next chunk, if any. 410 ;; Find the start of the next chunk, if any.
378 (setq start (text-property-any next end 'fontified nil)))))))) 411 (setq start (text-property-any next end 'fontified nil))))))))
379 412
@@ -421,71 +454,55 @@ Value is nil if there is nothing more to fontify."
421 (t next)))) 454 (t next))))
422 result)))) 455 result))))
423 456
424 457(defun jit-lock-stealth-fontify (&optional repeat)
425(defun jit-lock-stealth-fontify ()
426 "Fontify buffers stealthily. 458 "Fontify buffers stealthily.
427This functions is called after Emacs has been idle for 459This function is called repeatedly after Emacs has become idle for
428`jit-lock-stealth-time' seconds." 460`jit-lock-stealth-time' seconds. Optional argument REPEAT is expected
429 ;; I used to check `inhibit-read-only' here, but I can't remember why. -stef 461non-nil in a repeated invocation of this function."
462 ;; Cancel timer for repeated invocations.
463 (unless repeat
464 (cancel-timer jit-lock-stealth-repeat-timer))
430 (unless (or executing-kbd-macro 465 (unless (or executing-kbd-macro
431 memory-full 466 memory-full
432 (window-minibuffer-p (selected-window))) 467 (window-minibuffer-p (selected-window))
433 (let ((buffers (buffer-list)) 468 ;; For first invocation set up `jit-lock-stealth-buffers'.
434 (outer-buffer (current-buffer)) 469 ;; In repeated invocations it's already been set up.
470 (null (if repeat
471 jit-lock-stealth-buffers
472 (setq jit-lock-stealth-buffers (buffer-list)))))
473 (let ((buffer (car jit-lock-stealth-buffers))
474 (delay 0)
435 minibuffer-auto-raise 475 minibuffer-auto-raise
436 message-log-max) 476 message-log-max
437 (with-local-quit 477 start)
438 (while (and buffers (not (input-pending-p))) 478 (if (and jit-lock-stealth-load
439 (with-current-buffer (pop buffers) 479 (> (car (load-average)) jit-lock-stealth-load))
440 (when jit-lock-mode 480 ;; Wait a little if load is too high.
441 ;; This is funny. Calling sit-for with 3rd arg non-nil 481 (setq delay jit-lock-stealth-time)
442 ;; so that it doesn't redisplay, internally calls 482 (if (buffer-live-p buffer)
443 ;; wait_reading_process_input also with a parameter 483 (with-current-buffer buffer
444 ;; saying "don't redisplay." Since this function here 484 (if (and jit-lock-mode
445 ;; is called periodically, this effectively leads to 485 (setq start (jit-lock-stealth-chunk-start (point))))
446 ;; process output not being redisplayed at all because 486 ;; Fontify one block of at most `jit-lock-chunk-size'
447 ;; redisplay_internal is never called. (That didn't 487 ;; characters.
448 ;; work in the old redisplay either.) So, we learn that 488 (with-temp-message (if jit-lock-stealth-verbose
449 ;; we mustn't call sit-for that way here. But then, we 489 (concat "JIT stealth lock "
450 ;; have to be cautious not to call sit-for in a widened 490 (buffer-name)))
451 ;; buffer, since this could display hidden parts of that 491 (jit-lock-fontify-now start
452 ;; buffer. This explains the seemingly weird use of 492 (+ start jit-lock-chunk-size))
453 ;; save-restriction/widen here. 493 ;; Run again after `jit-lock-stealth-nice' seconds.
454 494 (setq delay (or jit-lock-stealth-nice 0)))
455 (with-temp-message (if jit-lock-stealth-verbose 495 ;; Nothing to fontify here. Remove this buffer from
456 (concat "JIT stealth lock " 496 ;; `jit-lock-stealth-buffers' and run again immediately.
457 (buffer-name))) 497 (setq jit-lock-stealth-buffers (cdr jit-lock-stealth-buffers))))
458 498 ;; Buffer is no longer live. Remove it from
459 ;; In the following code, the `sit-for' calls cause a 499 ;; `jit-lock-stealth-buffers' and run again immediately.
460 ;; redisplay, so it's required that the 500 (setq jit-lock-stealth-buffers (cdr jit-lock-stealth-buffers))))
461 ;; buffer-modified flag of a buffer that is displayed 501 ;; Call us again.
462 ;; has the right value---otherwise the mode line of 502 (when jit-lock-stealth-buffers
463 ;; an unmodified buffer would show a `*'. 503 (timer-set-idle-time jit-lock-stealth-repeat-timer (current-idle-time))
464 (let (start 504 (timer-inc-time jit-lock-stealth-repeat-timer delay)
465 (nice (or jit-lock-stealth-nice 0)) 505 (timer-activate-when-idle jit-lock-stealth-repeat-timer t)))))
466 (point (point-min)))
467 (while (and (setq start
468 (jit-lock-stealth-chunk-start point))
469 ;; In case sit-for runs any timers,
470 ;; give them the expected current buffer.
471 (with-current-buffer outer-buffer
472 (sit-for nice)))
473
474 ;; fontify a block.
475 (jit-lock-fontify-now start (+ start jit-lock-chunk-size))
476 ;; If stealth jit-locking is done backwards, this leads to
477 ;; excessive O(n^2) refontification. -stef
478 ;; (when (>= jit-lock-context-unfontify-pos start)
479 ;; (setq jit-lock-context-unfontify-pos end))
480
481 ;; Wait a little if load is too high.
482 (when (and jit-lock-stealth-load
483 (> (car (load-average)) jit-lock-stealth-load))
484 ;; In case sit-for runs any timers,
485 ;; give them the expected current buffer.
486 (with-current-buffer outer-buffer
487 (sit-for (or jit-lock-stealth-time 30))))))))))))))
488
489 506
490 507
491;;; Deferred fontification. 508;;; Deferred fontification.
@@ -548,6 +565,19 @@ This functions is called after Emacs has been idle for
548 '(fontified nil jit-lock-defer-multiline nil))) 565 '(fontified nil jit-lock-defer-multiline nil)))
549 (setq jit-lock-context-unfontify-pos (point-max))))))))) 566 (setq jit-lock-context-unfontify-pos (point-max)))))))))
550 567
568(defvar jit-lock-start) (defvar jit-lock-end) ; Dynamically scoped variables.
569(defvar jit-lock-after-change-extend-region-functions nil
570 "Hook that can extend the text to refontify after a change.
571This is run after every buffer change. The functions are called with
572the three arguments of `after-change-functions': START END OLD-LEN.
573The extended region to refontify is returned indirectly by modifying
574the variables `jit-lock-start' and `jit-lock-end'.
575
576Note that extending the region this way is not strictly necessary, except
577that the nature of the redisplay code tends to otherwise leave some of
578the rehighlighted text displayed with the old highlight until the next
579redisplay (see comment about repeated redisplay in `jit-lock-fontify-now').")
580
551(defun jit-lock-after-change (start end old-len) 581(defun jit-lock-after-change (start end old-len)
552 "Mark the rest of the buffer as not fontified after a change. 582 "Mark the rest of the buffer as not fontified after a change.
553Installed on `after-change-functions'. 583Installed on `after-change-functions'.
@@ -557,44 +587,24 @@ This function ensures that lines following the change will be refontified
557in case the syntax of those lines has changed. Refontification 587in case the syntax of those lines has changed. Refontification
558will take place when text is fontified stealthily." 588will take place when text is fontified stealthily."
559 (when (and jit-lock-mode (not memory-full)) 589 (when (and jit-lock-mode (not memory-full))
560 (let ((region (font-lock-extend-region start end old-len))) 590 (let ((jit-lock-start start)
561 (save-excursion 591 (jit-lock-end end))
562 (with-buffer-prepared-for-jit-lock 592 (with-buffer-prepared-for-jit-lock
563 ;; It's important that the `fontified' property be set from the 593 (run-hook-with-args 'jit-lock-after-change-extend-region-functions
564 ;; beginning of the line, else font-lock will properly change the 594 start end old-len)
565 ;; text's face, but the display will have been done already and will 595 ;; Make sure we change at least one char (in case of deletions).
566 ;; be inconsistent with the buffer's content. 596 (setq jit-lock-end (min (max jit-lock-end (1+ start)) (point-max)))
567 ;; 597 ;; Request refontification.
568 ;; FIXME!!! (Alan Mackenzie, 2006-03-14): If start isn't at a BOL, 598 (put-text-property jit-lock-start jit-lock-end 'fontified nil))
569 ;; expanding the region to BOL might mis-fontify, should the BOL not 599 ;; Mark the change for deferred contextual refontification.
570 ;; be at a "safe" position. 600 (when jit-lock-context-unfontify-pos
571 (setq start (if region 601 (setq jit-lock-context-unfontify-pos
572 (car region) 602 ;; Here we use `start' because nothing guarantees that the
573 (goto-char start) 603 ;; text between start and end will be otherwise refontified:
574 (line-beginning-position))) 604 ;; usually it will be refontified by virtue of being
575 605 ;; displayed, but if it's outside of any displayed area in the
576 ;; If we're in text that matches a multi-line font-lock pattern, 606 ;; buffer, only jit-lock-context-* will re-fontify it.
577 ;; make sure the whole text will be redisplayed. 607 (min jit-lock-context-unfontify-pos jit-lock-start))))))
578 ;; I'm not sure this is ever necessary and/or sufficient. -stef
579 (when (get-text-property start 'font-lock-multiline)
580 (setq start (or (previous-single-property-change
581 start 'font-lock-multiline)
582 (point-min))))
583
584 (if region (setq end (cdr region)))
585 ;; Make sure we change at least one char (in case of deletions).
586 (setq end (min (max end (1+ start)) (point-max)))
587 ;; Request refontification.
588 (put-text-property start end 'fontified nil))
589 ;; Mark the change for deferred contextual refontification.
590 (when jit-lock-context-unfontify-pos
591 (setq jit-lock-context-unfontify-pos
592 ;; Here we use `start' because nothing guarantees that the
593 ;; text between start and end will be otherwise refontified:
594 ;; usually it will be refontified by virtue of being
595 ;; displayed, but if it's outside of any displayed area in the
596 ;; buffer, only jit-lock-context-* will re-fontify it.
597 (min jit-lock-context-unfontify-pos start)))))))
598 608
599(provide 'jit-lock) 609(provide 'jit-lock)
600 610