diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2015-03-30 21:33:20 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2015-03-30 21:33:20 -0400 |
commit | bc9a6fcd29cd2e35a34e42f6e8b9492c98c1560f (patch) | |
tree | e44d050c05b9104e1259aa73d7acf9dde443f19a /lisp/jit-lock.el | |
parent | 2e4b0c98a77657e787e04ae680403b187b271c21 (diff) | |
download | emacs-bc9a6fcd29cd2e35a34e42f6e8b9492c98c1560f.tar.gz |
Let jit-lock know the result of font-lock-extend-region-functions.
* lisp/jit-lock.el (jit-lock--run-functions): New function.
(jit-lock-fontify-now): Use it. Handle fontification bounds more
precisely in case the backend functions fontify more than requested.
Don't round up to whole lines since that shouldn't be needed
any more.
* lisp/font-lock.el (font-lock-fontify-region-function): Adjust docstring.
(font-lock-inhibit-thing-lock): Make obsolete.
(font-lock-default-fontify-region): Return the bounds actually used.
* lisp/emacs-lisp/eieio-base.el (eieio-persistent-validate/fix-slot-value):
Fix compilation error.
Diffstat (limited to 'lisp/jit-lock.el')
-rw-r--r-- | lisp/jit-lock.el | 109 |
1 files changed, 65 insertions, 44 deletions
diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el index 788646c97be..d271a447756 100644 --- a/lisp/jit-lock.el +++ b/lisp/jit-lock.el @@ -351,6 +351,24 @@ is active." (min (point-max) (+ start jit-lock-chunk-size))) 'fontified 'defer))))) +(defun jit-lock--run-functions (beg end) + (let ((tight-beg nil) (tight-end nil) + (loose-beg beg) (loose-end end)) + (run-hook-wrapped + 'jit-lock-functions + (lambda (fun) + (pcase-let* + ((res (funcall fun beg end)) + (`(,this-beg . ,this-end) + (if (eq (car-safe res) 'jit-lock-bounds) + (cdr res) (cons beg end)))) + (setq tight-beg (max tight-beg (or this-beg (point-min)))) + (setq tight-end (max tight-end (or this-end (point-max)))) + (setq loose-beg (max loose-beg this-beg)) + (setq loose-end (max loose-end this-end)) + nil))) + `(,(min tight-beg beg) ,(max tight-end end) ,loose-beg ,loose-end))) + (defun jit-lock-fontify-now (&optional start end) "Fontify current buffer from START to END. Defaults to the whole buffer. END can be out of bounds." @@ -376,54 +394,57 @@ Defaults to the whole buffer. END can be out of bounds." (setq next (or (text-property-any start end 'fontified t) end)) - ;; Decide which range of text should be fontified. - ;; The problem is that START and NEXT may be in the - ;; middle of something matched by a font-lock regexp. - ;; Until someone has a better idea, let's start - ;; at the start of the line containing START and - ;; stop at the start of the line following NEXT. - (goto-char next) (setq next (line-beginning-position 2)) - (goto-char start) (setq start (line-beginning-position)) - - ;; Make sure the contextual refontification doesn't re-refontify - ;; what's already been refontified. - (when (and jit-lock-context-unfontify-pos - (< jit-lock-context-unfontify-pos next) - (>= jit-lock-context-unfontify-pos start) - ;; Don't move boundary forward if we have to - ;; refontify previous text. Otherwise, we risk moving - ;; it past the end of the multiline property and thus - ;; forget about this multiline region altogether. - (not (get-text-property start 'jit-lock-defer-multiline))) - (setq jit-lock-context-unfontify-pos next)) - ;; Fontify the chunk, and mark it as fontified. ;; We mark it first, to make sure that we don't indefinitely ;; re-execute this fontification if an error occurs. (put-text-property start next 'fontified t) - (condition-case err - (run-hook-with-args 'jit-lock-functions start next) - ;; If the user quits (which shouldn't happen in normal on-the-fly - ;; jit-locking), make sure the fontification will be performed - ;; before displaying the block again. - (quit (put-text-property start next 'fontified nil) - (funcall 'signal (car err) (cdr err)))) - - ;; The redisplay engine has already rendered the buffer up-to - ;; `orig-start' and won't notice if the above jit-lock-functions - ;; changed the appearance of any part of the buffer prior - ;; to that. So if `start' is before `orig-start', we need to - ;; cause a new redisplay cycle after this one so that any changes - ;; are properly reflected on screen. - ;; To make such repeated redisplay happen less often, we can - ;; eagerly extend the refontified region with - ;; jit-lock-after-change-extend-region-functions. - (when (< start orig-start) - (run-with-timer 0 nil #'jit-lock-force-redisplay - (copy-marker start) (copy-marker orig-start))) - - ;; Find the start of the next chunk, if any. - (setq start (text-property-any next end 'fontified nil)))))))) + (pcase-let + ;; `tight' is the part we've fully refontified, and `loose' + ;; is the part we've partly refontified (some of the + ;; functions have refontified it but maybe not all). + ((`(,tight-beg ,tight-end ,loose-beg ,loose-end) + (condition-case err + (jit-lock--run-functions start next) + ;; If the user quits (which shouldn't happen in normal + ;; on-the-fly jit-locking), make sure the fontification + ;; will be performed before displaying the block again. + (quit (put-text-property start next 'fontified nil) + (signal (car err) (cdr err)))))) + + ;; In case we fontified more than requested, take note. + (when (or (< tight-beg start) (> tight-end next)) + (put-text-property tight-beg tight-end 'fontified t)) + + ;; Make sure the contextual refontification doesn't re-refontify + ;; what's already been refontified. + (when (and jit-lock-context-unfontify-pos + (< jit-lock-context-unfontify-pos tight-end) + (>= jit-lock-context-unfontify-pos tight-beg) + ;; Don't move boundary forward if we have to + ;; refontify previous text. Otherwise, we risk moving + ;; it past the end of the multiline property and thus + ;; forget about this multiline region altogether. + (not (get-text-property tight-beg + 'jit-lock-defer-multiline))) + (setq jit-lock-context-unfontify-pos tight-end)) + + ;; The redisplay engine has already rendered the buffer up-to + ;; `orig-start' and won't notice if the above jit-lock-functions + ;; changed the appearance of any part of the buffer prior + ;; to that. So if `loose-beg' is before `orig-start', we need to + ;; cause a new redisplay cycle after this one so that the changes + ;; are properly reflected on screen. + ;; To make such repeated redisplay happen less often, we can + ;; eagerly extend the refontified region with + ;; jit-lock-after-change-extend-region-functions. + (when (< loose-beg orig-start) + (run-with-timer 0 nil #'jit-lock-force-redisplay + (copy-marker loose-beg) + (copy-marker orig-start))) + + ;; Find the start of the next chunk, if any. + (setq start + (text-property-any tight-end end 'fontified nil))))))))) (defun jit-lock-force-redisplay (start end) "Force the display engine to re-render START's buffer from START to END. |