branch: externals/doc-view-follow
commit 0cd19dc337f011788a977d1a632de0a7841d5cce
Author: Paul Nelson <ultr...@gmail.com>
Commit: Paul Nelson <ultr...@gmail.com>

    Refactor
    
    * doc-view-follow-pdf-tools.el: Delete file.
    
    * doc-view-follow.el (doc-view-follow): Streamline docs.
    (doc-view-follow-supported-p, doc-view-follow-setup)
    (doc-view-follow-teardown, doc-view-follow-set-page)
    (doc-view-follow-get-page): Take mode parameter instead of context.
    (doc-view-follow-mode): Update error message.
    (doc-view-follow-sync-pages): Mild simplification.
    (doc-view-follow--maybe-enable): Check with mode parameter.
    (doc-view): Move doc-view implementations under with-eval-after-load.
    (pdf-tools): Move pdf-tools implementations here.
    
    * README.org (Usage, Extensibility, Convenience): Update.
---
 README.org                   |   6 +-
 doc-view-follow-pdf-tools.el |  57 -------------------
 doc-view-follow.el           | 133 +++++++++++++++++++++----------------------
 3 files changed, 67 insertions(+), 129 deletions(-)

diff --git a/README.org b/README.org
index 1e7dcb4070..4cf7c743e4 100644
--- a/README.org
+++ b/README.org
@@ -50,11 +50,11 @@ Both windows will automatically stay synchronized.
 
 * Extensibility
 
-The package uses generic functions, making it straightforward to add support 
for additional document viewing modes.  See =doc-view-follow-pdf-tools.el= for 
an example of how to do this.
+The package uses generic functions, making it straightforward to add support 
for additional document viewing modes.
 
 * Convenience
 
-Since `doc-view-follow-mode` works with document files (PDF, PS, etc.) and 
`follow-mode` works with text buffers, you might want a single command that 
applies the appropriate mode based on your current buffer.  Here's a function 
that does so:
+Since =doc-view-follow-mode= works with document files (PDF, PS, etc.) and 
=follow-mode= works with text buffers, you might want a single command that 
applies the appropriate mode based on your current buffer.  Here's one:
 
 #+begin_src elisp
 (defun toggle-some-follow-mode ()
@@ -63,7 +63,7 @@ In buffers where `doc-view-follow-mode' is supported, toggle 
that mode.
 Otherwise, toggle the standard `follow-mode'."
   (interactive)
   (if (and (fboundp 'doc-view-follow-supported-p)
-           (doc-view-follow-supported-p))
+           (doc-view-follow-supported-p major-mode))
       (call-interactively 'doc-view-follow-mode)
     (call-interactively 'follow-mode)))
 
diff --git a/doc-view-follow-pdf-tools.el b/doc-view-follow-pdf-tools.el
deleted file mode 100644
index d4c4092651..0000000000
--- a/doc-view-follow-pdf-tools.el
+++ /dev/null
@@ -1,57 +0,0 @@
-;;; doc-view-follow-pdf-tools.el --- Support for doc-view-follow-mode with 
pdf-tools  -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2025  Free Software Foundation, Inc.
-
-;; Author: Paul D. Nelson <ultr...@gmail.com>
-;; Keywords: convenience
-
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Support for `doc-view-follow-mode' with `pdf-tools'.
-
-;;; Code:
-
-(require 'doc-view-follow)
-(require 'pdf-view)
-
-(declare-function doc-view-follow-sync-pages "doc-view-follow")
-
-(cl-defmethod doc-view-follow-supported-p (&context (major-mode pdf-view-mode))
-  "When MAJOR-MODE is `pdf-view-mode', return t."
-  t)
-
-(cl-defmethod doc-view-follow-setup (&context (major-mode pdf-view-mode))
-  "When MAJOR-MODE is `pdf-view-mode', setup `doc-view-follow-mode'."
-  (add-hook 'pdf-view-after-change-page-hook
-            #'doc-view-follow-sync-pages nil 'local))
-
-(cl-defmethod doc-view-follow-teardown (&context (major-mode pdf-view-mode))
-  "When MAJOR-MODE is `pdf-view-mode', teardown `doc-view-follow-mode'."
-  (remove-hook 'pdf-view-after-change-page-hook
-               #'doc-view-follow-sync-pages 'local))
-
-(cl-defmethod doc-view-follow-set-page (page &context (major-mode 
pdf-view-mode))
-  "When MAJOR-MODE is `pdf-view-mode', go to PAGE in the document buffer."
-  (let ((pdf-view-inhibit-redisplay nil)
-        (page (max 1 (min page (pdf-cache-number-of-pages)))))
-    (pdf-view-goto-page page)))
-
-(cl-defmethod doc-view-follow-get-page (&context (major-mode pdf-view-mode))
-  "When MAJOR-MODE is `pdf-view-mode', return the current page number."
-  (pdf-view-current-page))
-
-(provide 'doc-view-follow-pdf-tools)
-;;; doc-view-follow-pdf-tools.el ends here
diff --git a/doc-view-follow.el b/doc-view-follow.el
index 8bf43aba4f..a090eea917 100644
--- a/doc-view-follow.el
+++ b/doc-view-follow.el
@@ -34,15 +34,8 @@
 ;; particular, this allows a "book view" where the document is shown
 ;; in two side-by-side windows on consecutive pages.
 ;;
-;; `doc-view-mode' (built-in to Emacs) is supported by default.  To
-;; enable support for `pdf-view-mode' (from pdf-tools), add the
-;; following to your init file:
-;;
-;;   (with-eval-after-load 'pdf-view
-;;     (require 'doc-view-follow-pdf-tools))
-;;
-;; The file `doc-view-follow-pdf-tools.el' shows by example how the
-;; package might be extended to other document viewing modes.
+;; `doc-view-mode' (built-in to Emacs) and `pdf-view-mode' (from
+;; pdf-tools) are supported
 ;;
 ;; Usage:
 ;; - Enable globally: M-x global-doc-view-follow-mode
@@ -59,65 +52,62 @@
 (require 'follow)
 
 (defgroup doc-view-follow nil
-  "Synchronize pages between two windows displaying the same document."
+  "Synchronize pages between windows displaying the same document."
   :group 'convenience)
 
-(cl-defgeneric doc-view-follow-supported-p ()
-  "Check if the current buffer is supported by `doc-view-follow-mode'."
+;;;###autoload
+(cl-defgeneric doc-view-follow-supported-p (_mode)
+  "Check if MODE supports `doc-view-follow-mode'."
   nil)
 
-(cl-defgeneric doc-view-follow-setup ()
-  "Setup function for `doc-view-follow-mode'."
-  (error "`doc-view-follow-mode' is not supported in this buffer"))
+(cl-defgeneric doc-view-follow-setup (mode)
+  "Setup function for `doc-view-follow-mode' in MODE."
+  (error "`doc-view-follow-mode' is not supported in %s" mode))
 
-(cl-defgeneric doc-view-follow-teardown ()
-  "Teardown function for `doc-view-follow-mode'."
-  (error "`doc-view-follow-mode' is not supported in this buffer"))
+(cl-defgeneric doc-view-follow-teardown (mode)
+  "Teardown function for `doc-view-follow-mode' in MODE."
+  (error "`doc-view-follow-mode' is not supported in %s" mode))
 
-(cl-defgeneric doc-view-follow-set-page (_page)
-  "Go to PAGE in the current document buffer.
-Clamps PAGE to the valid range of pages."
-  (error "`doc-view-follow-mode' is not supported in this buffer"))
+(cl-defgeneric doc-view-follow-set-page (_page mode)
+  "Set PAGE in MODE document buffer."
+  (error "`doc-view-follow-mode' is not supported in %s" mode))
 
-(cl-defgeneric doc-view-follow-get-page ()
-  "Return the current page number in the document buffer."
-  (error "`doc-view-follow-mode' is not supported in this buffer"))
+(cl-defgeneric doc-view-follow-get-page (mode)
+  "Get current page number in MODE document buffer."
+  (error "`doc-view-follow-mode' is not supported in %s" mode))
 
 (defvar doc-view-follow--sync-in-progress nil
   "Flag to prevent recursive sync operations.")
 
 ;;;###autoload
 (define-minor-mode doc-view-follow-mode
-  "Minor mode to sync pages between windows showing the same document."
+  "Minor mode to sync pages between document windows."
   :global nil
-  :lighter nil
-  (unless (doc-view-follow-supported-p)
-    (error "`doc-view-follow-mode' is not supported in this buffer"))
+  (unless (doc-view-follow-supported-p major-mode)
+    (error "`doc-view-follow-mode' not supported in %s" major-mode))
   (if doc-view-follow-mode
       (progn
-        (doc-view-follow-setup)
+        (doc-view-follow-setup major-mode)
         (doc-view-follow-sync-pages))
-    (doc-view-follow-teardown)))
+    (doc-view-follow-teardown major-mode)))
 
-(defun doc-view-follow-sync-pages (&rest _args)
-  "Sync pages between windows showing the same document."
-  (when (and doc-view-follow-mode
-             (not doc-view-follow--sync-in-progress))
+(defun doc-view-follow-sync-pages (&rest _)
+  "Synchronize document pages between windows."
+  (when (and doc-view-follow-mode (not doc-view-follow--sync-in-progress))
     (let ((doc-view-follow--sync-in-progress t)
           (windows (follow-all-followers)))
       (when (> (length windows) 1)
-        (let* ((current-i (seq-position windows (selected-window)))
-               (current-page (doc-view-follow-get-page))
-               (page (- current-page current-i)))
+        (let* ((idx (seq-position windows (selected-window)))
+               (page (- (doc-view-follow-get-page major-mode) idx)))
           (dolist (win windows)
-            (unless (eq (selected-window) win)
+            (unless (eq win (selected-window))
               (with-selected-window win
-                (doc-view-follow-set-page page)))
-            (incf page)))))))
+                (doc-view-follow-set-page page major-mode)))
+            (setq page (1+ page))))))))
 
 (defun doc-view-follow--maybe-enable ()
   "Enable `doc-view-follow-mode' if appropriate for this buffer."
-  (when (doc-view-follow-supported-p)
+  (when (doc-view-follow-supported-p major-mode)
     (unless doc-view-follow-mode
       (doc-view-follow-mode 1))))
 
@@ -125,33 +115,38 @@ Clamps PAGE to the valid range of pages."
 (define-globalized-minor-mode global-doc-view-follow-mode
   doc-view-follow-mode doc-view-follow--maybe-enable)
 
-(require 'doc-view)
-
-(cl-defmethod doc-view-follow-supported-p (&context (major-mode doc-view-mode))
-  "When MAJOR-MODE is `doc-view-mode', return t."
-  t)
-
-(cl-defmethod doc-view-follow-setup (&context (major-mode doc-view-mode))
-  "When MAJOR-MODE is `doc-view-mode', setup `doc-view-follow-mode'."
-  (advice-add 'doc-view-goto-page :after #'doc-view-follow-sync-pages))
-
-(cl-defmethod doc-view-follow-teardown (&context (major-mode doc-view-mode))
-  "When MAJOR-MODE is `doc-view-mode', teardown `doc-view-follow-mode'."
-  (unless
-      (seq-some (lambda (buf)
-                  (and (eq (buffer-local-value 'major-mode buf) 'doc-view-mode)
-                       (buffer-local-value 'doc-view-follow-mode buf)))
-                (buffer-list))
-    (advice-remove 'doc-view-goto-page #'doc-view-follow-sync-pages)))
-
-(cl-defmethod doc-view-follow-set-page (page &context (major-mode 
doc-view-mode))
-  "When MAJOR-MODE is `doc-view-mode', go to PAGE in the document buffer."
-  (let ((page (max 1 (min page (doc-view-last-page-number)))))
-    (doc-view-goto-page page)))
-
-(cl-defmethod doc-view-follow-get-page (&context (major-mode doc-view-mode))
-  "When MAJOR-MODE is `doc-view-mode', return the current page number."
-  (doc-view-current-page))
+(with-eval-after-load 'doc-view
+  (declare-function doc-view-goto-page "doc-view")
+  (declare-function doc-view-last-page-number "doc-view")
+  (declare-function doc-view-current-page "doc-view")
+  
+  (cl-defmethod doc-view-follow-supported-p ((_mode (eql doc-view-mode))) t)
+  (cl-defmethod doc-view-follow-setup ((_mode (eql doc-view-mode)))
+    (advice-add 'doc-view-goto-page :after #'doc-view-follow-sync-pages))
+  (cl-defmethod doc-view-follow-teardown ((_mode (eql doc-view-mode)))
+    (advice-remove 'doc-view-goto-page #'doc-view-follow-sync-pages))
+  (cl-defmethod doc-view-follow-set-page (page (_mode (eql doc-view-mode)))
+    (doc-view-goto-page (max 1 (min page (doc-view-last-page-number)))))
+  (cl-defmethod doc-view-follow-get-page ((_mode (eql doc-view-mode)))
+    (doc-view-current-page)))
+
+(with-eval-after-load 'pdf-tools
+  (declare-function pdf-view-goto-page "pdf-view")
+  (declare-function pdf-cache-number-of-pages "pdf-cache")
+  (declare-function pdf-view-current-page "pdf-view")
+  (defvar pdf-view-inhibit-redisplay)
+  (cl-defmethod doc-view-follow-supported-p ((_mode (eql pdf-view-mode))) t)
+  (cl-defmethod doc-view-follow-setup ((_mode (eql pdf-view-mode)))
+    (add-hook 'pdf-view-after-change-page-hook
+              #'doc-view-follow-sync-pages nil t))
+  (cl-defmethod doc-view-follow-teardown ((_mode (eql pdf-view-mode)))
+    (remove-hook 'pdf-view-after-change-page-hook
+                 #'doc-view-follow-sync-pages t))
+  (cl-defmethod doc-view-follow-set-page (page (_mode (eql pdf-view-mode)))
+    (let ((pdf-view-inhibit-redisplay nil))
+      (pdf-view-goto-page (max 1 (min page (pdf-cache-number-of-pages))))))
+  (cl-defmethod doc-view-follow-get-page ((_mode (eql pdf-view-mode)))
+    (pdf-view-current-page)))
 
 (provide 'doc-view-follow)
 ;;; doc-view-follow.el ends here

Reply via email to