Commit de321180 authored by João Távora's avatar João Távora

New jit-lock-antiblink-grace feature

* lisp/jit-lock.el (jit-lock-antiblink-grace): New variable.
(jit-lock--antiblink-grace-timer, jit-lock--antiblink-l-l-b)
(jit-lock--antiblink-i-s-o-c): New helpers.
(jit-lock-mode): Tweak post-command-hook and
jit-lock-context-timer.
(jit-lock--antiblink-post-command): New helper.
parent 9f2145f4
...@@ -123,6 +123,17 @@ The value of this variable is used when JIT Lock mode is turned on." ...@@ -123,6 +123,17 @@ The value of this variable is used when JIT Lock mode is turned on."
:type '(number :tag "seconds") :type '(number :tag "seconds")
:group 'jit-lock) :group 'jit-lock)
(defcustom jit-lock-antiblink-grace 2
"Like `jit-lock-context-time' but for unterminated multiline strings.
Setting this to a positive number of seconds helps avoid the
fontification \"blinking\" behaviour observed when adding
temporarily unterminated strings to source code. If the user has
recently created an unterminated string at EOL, allow for an idle
\"grace\" period to elapse before deciding it is a multi-line
string and fontifying the remainder of the buffer accordingly."
:type '(number :tag "seconds")
:group 'jit-lock)
(defcustom jit-lock-defer-time nil ;; 0.25 (defcustom jit-lock-defer-time nil ;; 0.25
"Idle time after which deferred fontification should take place. "Idle time after which deferred fontification should take place.
If nil, fontification is not deferred. If nil, fontification is not deferred.
...@@ -157,6 +168,15 @@ If nil, contextual fontification is disabled.") ...@@ -157,6 +168,15 @@ If nil, contextual fontification is disabled.")
"List of buffers with pending deferred fontification.") "List of buffers with pending deferred fontification.")
(defvar jit-lock-stealth-buffers nil (defvar jit-lock-stealth-buffers nil
"List of buffers that are being fontified stealthily.") "List of buffers that are being fontified stealthily.")
(defvar jit-lock--antiblink-grace-timer nil
"Idle timer for fontifying unterminated string or comment, or nil")
(defvar jit-lock--antiblink-l-l-b (make-marker)
"Last line beginning (l-l-b) position after last command (a marker).")
(defvar jit-lock--antiblink-i-s-o-c nil
"In string or comment (i-s-o-c) after last command (a boolean).")
;;; JIT lock mode ;;; JIT lock mode
...@@ -232,7 +252,10 @@ If you need to debug code run from jit-lock, see `jit-lock-debug-mode'." ...@@ -232,7 +252,10 @@ If you need to debug code run from jit-lock, see `jit-lock-debug-mode'."
(unless jit-lock-context-timer (unless jit-lock-context-timer
(setq jit-lock-context-timer (setq jit-lock-context-timer
(run-with-idle-timer jit-lock-context-time t (run-with-idle-timer jit-lock-context-time t
'jit-lock-context-fontify))) (lambda ()
(unless jit-lock--antiblink-grace-timer
(jit-lock-context-fontify))))))
(add-hook 'post-command-hook 'jit-lock--antiblink-post-command nil t)
(setq jit-lock-context-unfontify-pos (setq jit-lock-context-unfontify-pos
(or jit-lock-context-unfontify-pos (point-max)))) (or jit-lock-context-unfontify-pos (point-max))))
...@@ -669,6 +692,58 @@ will take place when text is fontified stealthily." ...@@ -669,6 +692,58 @@ will take place when text is fontified stealthily."
;; buffer, only jit-lock-context-* will re-fontify it. ;; buffer, only jit-lock-context-* will re-fontify it.
(min jit-lock-context-unfontify-pos jit-lock-start)))))) (min jit-lock-context-unfontify-pos jit-lock-start))))))
(defun jit-lock--antiblink-post-command ()
(let* ((new-l-l-b (set-marker (make-marker) (line-beginning-position)))
(new-i-s-o-c
(nth 8 (save-excursion (syntax-ppss (line-end-position)))))
(same-line
(and jit-lock-antiblink-grace
(eq (marker-buffer jit-lock--antiblink-l-l-b) (current-buffer))
(= new-l-l-b jit-lock--antiblink-l-l-b))))
(cond (;; opened a new multiline string...
(and same-line
(null jit-lock--antiblink-i-s-o-c) new-i-s-o-c)
;; assert that the grace timer is null and schedule it
(when jit-lock--antiblink-grace-timer
(display-warning
'font-lock :level
"`jit-lock--antiblink-grace-timer' not null" :warning))
(setq jit-lock--antiblink-grace-timer
(run-with-idle-timer jit-lock-antiblink-grace nil
(lambda ()
(jit-lock-context-fontify)
(setq jit-lock--antiblink-grace-timer nil)))))
(;; closed an unterminated multiline string.
(and same-line
(null new-i-s-o-c) jit-lock--antiblink-i-s-o-c)
;; Kill the grace timer, might already have run and died.
;; Don't refontify immediately: it adds an unreasonable
;; delay to a well-behaved operation. Leave it for the
;; `jit-lock-context-timer' as usual.
(when jit-lock--antiblink-grace-timer
(cancel-timer jit-lock--antiblink-grace-timer)
(setq jit-lock--antiblink-grace-timer nil))
)
(same-line
;; in same line, but no state change, leave everything as it was
)
(t
;; left the line somehow or customized feature away, etc
;; kill timer if running, resume normal operation.
(when jit-lock--antiblink-grace-timer
;; Do refontify immediately, adding a small delay. This
;; is per Lars' request, and it makes sense because we
;; should remark somehow that we are leaving the unstable
;; state.
(jit-lock-context-fontify)
(cancel-timer jit-lock--antiblink-grace-timer)
(setq jit-lock--antiblink-grace-timer nil))))
;; update variables
(setq jit-lock--antiblink-l-l-b new-l-l-b
jit-lock--antiblink-i-s-o-c new-i-s-o-c)))
(provide 'jit-lock) (provide 'jit-lock)
;;; jit-lock.el ends here ;;; jit-lock.el ends here
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment