On Tue, Jul 9, 2019 at 4:40 PM Stefan Monnier wrote: > IOW make it so that font-lock: > - delays refontification after the current line if the end of line is > now within a string/comment (and wasn't before). > - "un-delays" this fontification if the end of line is now outside of any > string/comment (but was within it before). > - of course, with some kind of timeout, but one longer than 0.5s. > > Or something like that. Here's my take on that. Clément/Dmitry if you find the time test this. .. It should, in principle, reduce "blinking" in all modes (for people who aren't using electric-pair-mode or something like that). If it doesn't, I've made some kind of false assumption. Btw to restart jit-lock-mode in a running emacs, you need to do sth like this: (progn (jit-lock-mode -1) (cancel-timer jit-lock-context-timer) (setq jit-lock-context-timer nil) (jit-lock-mode 1)) João diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el index 48998a81fe..0d7c434f3f 100644 --- a/lisp/jit-lock.el +++ b/lisp/jit-lock.el @@ -123,6 +123,15 @@ jit-lock-context-time :type '(number :tag "seconds") :group 'jit-lock) +(defcustom jit-lock-multiline-string-grace 2 + "Like `jit-lock-context-time' but for unterminated multiline strings. +If the user has just opened an unterminated string at EOL, give +him/her some grace time before deciding it is a multi-line string +and fontifying accordingly, do so only if the user stares idle at +that string for more than this many seconds." + :type '(number :tag "seconds") + :group 'jit-lock) + (defcustom jit-lock-defer-time nil ;; 0.25 "Idle time after which deferred fontification should take place. If nil, fontification is not deferred. @@ -232,7 +241,7 @@ jit-lock-mode (unless jit-lock-context-timer (setq jit-lock-context-timer (run-with-idle-timer jit-lock-context-time t - 'jit-lock-context-fontify))) + (jit--lock-context-timer-function)))) (setq jit-lock-context-unfontify-pos (or jit-lock-context-unfontify-pos (point-max)))) @@ -306,6 +315,44 @@ jit-lock--debug-fontify pos 'fontified))))))))) (setq jit-lock-defer-buffers nil)))) +(defun jit--lock-context-timer-function () + (let (last ; point marker the last time context timer was run + in-s-or-c-p ; t if in string or comment that time around + grace-timer ; idle timer for fontifying unterminated s-or-c, or nil + ) + (lambda () + (let ((point (point-marker)) + (new-in-s-or-c-p + (nth 8 (save-excursion (syntax-ppss (line-end-position)))))) + (if (and jit-lock-multiline-string-grace + last + (eq (marker-buffer last) (current-buffer)) + (eq (line-number-at-pos last) (line-number-at-pos))) + (cond ((and (null in-s-or-c-p) new-in-s-or-c-p (null grace-timer)) + (setq grace-timer + (run-with-idle-timer jit-lock-multiline-string-grace nil + (lambda () + (jit-lock-context-fontify) + (setq grace-timer nil))))) + ((and in-s-or-c-p + (null new-in-s-or-c-p) + grace-timer) + (cancel-timer grace-timer) + (setq grace-timer nil)) + (t + ;; no state change, leave everything as it was + )) + ;; left the line somehow or customized feature away: cancel + ;; everything, resume normal operation. + (when grace-timer + (cancel-timer grace-timer) + (setq grace-timer nil))) + ;; proceed as usual, unless grace-timer is counting + (unless grace-timer + (jit-lock-context-fontify)) + (setq last point in-s-or-c-p new-in-s-or-c-p))))) + + (defun jit-lock-register (fun &optional contextual) "Register FUN as a fontification function to be called in this buffer. FUN will be called with two arguments START and END indicating the region