emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 5b45c26: New jit-lock-antiblink-grace feature


From: João Távora
Subject: master 5b45c26: New jit-lock-antiblink-grace feature
Date: Wed, 4 Dec 2019 17:42:12 -0500 (EST)

branch: master
commit 5b45c269cda09fe46e110adb6f6767040f4ade59
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>

    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
---
 etc/NEWS         |  7 ++++++
 lisp/jit-lock.el | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/etc/NEWS b/etc/NEWS
index 8a72c31..3d17b8f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -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
 
diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el
index 48998a8..a17224e 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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]