diff options
Diffstat (limited to 'lisp/jit-lock.el')
| -rw-r--r-- | lisp/jit-lock.el | 210 |
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. |
| 427 | This functions is called after Emacs has been idle for | 459 | This 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 | 461 | non-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. | ||
| 571 | This is run after every buffer change. The functions are called with | ||
| 572 | the three arguments of `after-change-functions': START END OLD-LEN. | ||
| 573 | The extended region to refontify is returned indirectly by modifying | ||
| 574 | the variables `jit-lock-start' and `jit-lock-end'. | ||
| 575 | |||
| 576 | Note that extending the region this way is not strictly necessary, except | ||
| 577 | that the nature of the redisplay code tends to otherwise leave some of | ||
| 578 | the rehighlighted text displayed with the old highlight until the next | ||
| 579 | redisplay (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. |
| 553 | Installed on `after-change-functions'. | 583 | Installed on `after-change-functions'. |
| @@ -557,44 +587,24 @@ This function ensures that lines following the change will be refontified | |||
| 557 | in case the syntax of those lines has changed. Refontification | 587 | in case the syntax of those lines has changed. Refontification |
| 558 | will take place when text is fontified stealthily." | 588 | will 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 | ||