diff options
author | João Távora <joaotavora@gmail.com> | 2019-07-12 19:27:53 +0100 |
---|---|---|
committer | João Távora <joaotavora@gmail.com> | 2019-12-04 23:38:06 +0100 |
commit | 5b45c269cda09fe46e110adb6f6767040f4ade59 (patch) | |
tree | 0a6cd49204b36d878db339d145d331ab10eb8f5d /lisp | |
parent | 0e774d4f355b4f12a625da5ca9602d1ba876bcc1 (diff) | |
download | emacs-5b45c269cda09fe46e110adb6f6767040f4ade59.tar.gz |
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
Diffstat (limited to 'lisp')
-rw-r--r-- | lisp/jit-lock.el | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el index 48998a81fe7..a17224e4bd0 100644 --- a/lisp/jit-lock.el +++ b/lisp/jit-lock.el @@ -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 |