branch: elpa/logview
commit 8d91b86de4d3a1e795b51d64f8107b4be6ecaaa5
Author: Paul Pogonyshev <pogonys...@gmail.com>
Commit: Paul Pogonyshev <pogonys...@gmail.com>

    Rewrite automatic submode reguessing to run only when Emacs is idle, since 
this can now take non-trivial amount of time.
---
 logview.el | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 70 insertions(+), 5 deletions(-)

diff --git a/logview.el b/logview.el
index 99e94a17a1..062f063f72 100644
--- a/logview.el
+++ b/logview.el
@@ -146,10 +146,8 @@ This value is used as the fallback for customizable
 
 (defun logview--set-submode-affecting-variable (variable value)
   (set variable value)
-  (dolist (buffer (buffer-list))
-    (with-current-buffer buffer
-      (when (and (eq major-mode 'logview-mode) (not (logview-initialized-p)))
-        (logview--guess-submode)))))
+  (when (fboundp #'logview--maybe-guess-submodes-again)
+    (logview--maybe-guess-submodes-again)))
 
 (defun logview--set-highlight-affecting-variable (variable value)
   (set variable value)
@@ -614,6 +612,12 @@ this face is used."
 
 (defconst logview--valid-filter-prefixes '("lv" "LV" "a+" "a-" "t+" "t-" "m+" 
"m-"))
 
+(defvar logview--custom-submode-revision 0)
+(defvar logview--custom-submode-state nil)
+(defvar logview--submode-guessing-timer nil)
+(defvar logview--need-submode-guessing nil)
+(defvar-local logview--custom-submode-guessed-with 0)
+
 
 (defvar-local logview--point-min nil)
 (defvar-local logview--point-max nil)
@@ -2403,7 +2407,9 @@ returns non-nil."
                 (when promising
                   (setf remaining-attemps (1- remaining-attemps))))
               (forward-line 1)
-              (setq line-number (1+ line-number)))))))))
+              (setq line-number (1+ line-number))))))
+      ;; This is done regardless of whether guessing has succeeded or not.
+      (setf logview--custom-submode-guessed-with 
logview--custom-submode-revision))))
 
 ;; Returns non-nil if TEST-LINE is "promising".
 (defun logview--initialize-submode (name definition standard-timestamps 
&optional test-line)
@@ -2609,6 +2615,65 @@ returns non-nil."
                                :overwrite t))))))
   logview--all-timestamp-formats-cache)
 
+;; Schedule submode reguessing in all Logview buffers that have no submode.  
There is some
+;; black magic involved to do it one buffer a time and only when Emacs is idle 
(to avoid
+;; making it appear hung) and also handle visible buffers first.
+(defun logview--maybe-guess-submodes-again ()
+  (let ((state (list logview-additional-submodes 
logview-additional-level-mappings logview-additional-timestamp-formats)))
+    (unless (equal state logview--custom-submode-state)
+      (setf logview--custom-submode-state    state
+            logview--custom-submode-revision (1+ 
logview--custom-submode-revision)
+            logview--need-submode-guessing   (make-hash-table :test #'eq))
+      (dolist (buffer (buffer-list))
+        (when (logview--needs-reguessing-p buffer)
+          (puthash buffer t logview--need-submode-guessing)))
+      (logview--reschedule-submode-guessing))))
+
+(defun logview--needs-reguessing-p (buffer)
+  (when (buffer-live-p buffer)
+    (with-current-buffer buffer
+      (and (eq major-mode 'logview-mode)
+           (not (logview-initialized-p))
+           (< logview--custom-submode-guessed-with 
logview--custom-submode-revision)))))
+
+(defun logview--reschedule-submode-guessing ()
+  (when logview--submode-guessing-timer
+    (cancel-timer logview--submode-guessing-timer)
+    (setf logview--submode-guessing-timer nil))
+  (when logview--need-submode-guessing
+    (if (> (hash-table-count logview--need-submode-guessing) 0)
+        (setf logview--submode-guessing-timer (if (current-idle-time)
+                                                  (run-with-timer 0.2 nil
+                                                                  (lambda ()
+                                                                    (if 
(current-idle-time)
+                                                                        
(logview--guess-submode-again)
+                                                                      
(logview--reschedule-submode-guessing))))
+                                                (run-with-idle-timer 1 nil 
#'logview--guess-submode-again)))
+      (setf logview--need-submode-guessing nil))))
+
+(defun logview--guess-submode-again ()
+  (let* (obsolete-buffers
+         (reguessed-in (catch 'processed-buffer
+                         (logview--try-to-guess-submode-again (window-buffer 
(selected-window)))
+                         (let ((current-frame (selected-frame)))
+                           (dolist (frame (cons current-frame (delq 
current-frame (frame-list))))
+                             (dolist (window (window-list frame))
+                               (logview--try-to-guess-submode-again 
(window-buffer window)))))
+                         (maphash (lambda (buffer _)
+                                    (logview--try-to-guess-submode-again 
buffer)
+                                    (push buffer obsolete-buffers))
+                                  logview--need-submode-guessing))))
+    (remhash reguessed-in logview--need-submode-guessing)
+    (dolist (obsolete obsolete-buffers)
+      (remhash obsolete logview--need-submode-guessing))
+    (logview--reschedule-submode-guessing)))
+
+(defun logview--try-to-guess-submode-again (buffer)
+  (when (logview--needs-reguessing-p buffer)
+    (with-current-buffer buffer
+      (logview--guess-submode)
+      (throw 'processed-buffer buffer))))
+
 
 (defun logview--assert (&rest assertions)
   (unless (logview-initialized-p)

Reply via email to