Commit 5b45c269 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 defcustom.
(jit-lock--antiblink-line-beginning-position)
(jit-lock--antiblink-string-or-comment): New variables
(jit-lock--antiblink-post-command): New helper.
(jit-lock-mode): Tweak post-command-hook and
jit-lock-context-timer.

* etc/NEWS: Mention jit-lock-antiblink-grace
parent 0e774d4f
Pipeline #4241 failed with stage
in 90 minutes and 2 seconds
......@@ -626,6 +626,13 @@ If the region is active, the command joins all the lines in the
region. When there's no active region, the command works on the
current and the previous or the next line, as before.
---
** New customizable variable 'jit-lock-antiblink-grace'.
When typing strings, this helps avoid "blinking", an oscillation
between string and non-string fontification. The variable holds a
number of seconds (default is 2) before a potentially unwanted
fontification starts. Set to nil to get back the old behavior.
* Changes in Specialized Modes and Packages in Emacs 27.1
......
......@@ -123,6 +123,20 @@ The value of this variable is used when JIT Lock mode is turned on."
:type '(number :tag "seconds")
:group 'jit-lock)
(defcustom jit-lock-antiblink-grace 2
"Grace period after which to refontify due to unterminated strings.
If nil, no grace period is given. Otherwise, a newly created
unterminated string is fontified only to the end of the current
line, after which the system waits this many seconds of idle time
before deciding the string is multi-line and fontifying the
remaining lines. When typing strings, this helps avoid
\"blinking\", an unwanted oscillation between string and
non-string fontification."
:type '(choice (const :tag "never" nil)
(number :tag "seconds"))
:group 'jit-lock
:version "27.1")
(defcustom jit-lock-defer-time nil ;; 0.25
"Idle time after which deferred fontification should take place.
If nil, fontification is not deferred.
......@@ -157,6 +171,13 @@ If nil, contextual fontification is disabled.")
"List of buffers with pending deferred fontification.")
(defvar jit-lock-stealth-buffers nil
"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-line-beginning-position (make-marker)
"Last line beginning position after last command (a marker).")
(defvar jit-lock--antiblink-string-or-comment nil
"Non-nil if in string or comment after last command (a boolean).")
;;; JIT lock mode
......@@ -232,7 +253,10 @@ If you need to debug code run from jit-lock, see `jit-lock-debug-mode'."
(unless jit-lock-context-timer
(setq jit-lock-context-timer
(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
(or jit-lock-context-unfontify-pos (point-max))))
......@@ -669,6 +693,55 @@ will take place when text is fontified stealthily."
;; buffer, only jit-lock-context-* will re-fontify it.
(min jit-lock-context-unfontify-pos jit-lock-start))))))
(defun jit-lock--antiblink-post-command ()
(let* ((new-l-b-p (copy-marker (line-beginning-position)))
(l-b-p-2 (line-beginning-position 2))
(same-line
(and jit-lock-antiblink-grace
(not (= new-l-b-p l-b-p-2))
(eq (marker-buffer jit-lock--antiblink-line-beginning-position)
(current-buffer))
(= new-l-b-p jit-lock--antiblink-line-beginning-position)))
(new-s-o-c
(and same-line
(nth 8 (save-excursion (syntax-ppss l-b-p-2))))))
(cond (;; Opened a new multiline string...
(and same-line
(null jit-lock--antiblink-string-or-comment) new-s-o-c)
(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-s-o-c) jit-lock--antiblink-string-or-comment)
;; 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
;; makes sense because it 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 (and release the marker)
(set-marker jit-lock--antiblink-line-beginning-position nil)
(setq jit-lock--antiblink-line-beginning-position new-l-b-p
jit-lock--antiblink-string-or-comment new-s-o-c)))
(provide 'jit-lock)
;;; 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