branch: externals/doc-view-follow
commit e3ac3351a24b95efec64140b49ed3267a9485874
Author: Paul Nelson <[email protected]>
Commit: Paul Nelson <[email protected]>
Refactor doc-dual-view to use property lists for mode
configuration
* doc-dual-view.el (doc-dual-view-modes): Convert from custom variable
to defvar with plist-based structure. Change format to use clear
property names rather than positional arguments.
(doc-dual-view--call-func): New helper function to call mode-specific
functions by property name.
(doc-dual-view--order-windows): Simplify code formatting.
(doc-dual-view--sync-pages): Rewrite to use the new plist-based mode
configuration. Improve variable names and code organization.
(doc-dual-view-mode): Update to handle the new configuration format.
---
doc-dual-view.el | 115 ++++++++++++++++++++++++++++---------------------------
1 file changed, 58 insertions(+), 57 deletions(-)
diff --git a/doc-dual-view.el b/doc-dual-view.el
index 27327202be..883cbac20c 100644
--- a/doc-dual-view.el
+++ b/doc-dual-view.el
@@ -41,43 +41,46 @@
"Synchronize pages between two windows displaying the same document."
:group 'convenience)
-(defcustom doc-dual-view-modes
- '((pdf-view-mode
- (pdf-view-goto-page
- pdf-view-next-page-command
- pdf-view-previous-page-command)
- (lambda () (pdf-view-current-page)) ; convert macro to function
- (lambda () (pdf-cache-number-of-pages)))
- (doc-view-mode
- (doc-view-goto-page
- doc-view-next-page
- doc-view-previous-page)
- (lambda () (doc-view-current-page))
- (lambda () (doc-view-last-page-number))))
- "Alist for supported modes.
-List of mode-specific functions of the form
-
-(MAJOR-MODE GOTO-FUNCTIONS CURRENT-PAGE-FUNCTION MAX-PAGE-FUNCTION),
-
-where GOTO-FUNCTIONS is of the form (GOTO-FUNC NEXT-FUNC PREV-FUNC)."
- :type '(repeat (list (symbol :tag "Major Mode")
- (repeat :tag "Goto Page Functions" symbol)
- (function :tag "Current Page Function")
- (function :tag "Max Page Function"))))
+(defvar doc-dual-view-modes
+ '((doc-view-mode
+ :goto doc-view-goto-page
+ :next doc-view-next-page
+ :prev doc-view-previous-page
+ :current (lambda () (doc-view-current-page))
+ :max (lambda () (doc-view-last-page-number)))
+ (pdf-view-mode
+ :goto pdf-view-goto-page
+ :next pdf-view-next-page-command
+ :prev pdf-view-previous-page-command
+ :current (lambda () (pdf-view-current-page))
+ :max (lambda () (pdf-cache-number-of-pages))))
+ "Alist of supported major modes and relevant functions.
+Each entry has the format:
+(MAJOR-MODE
+ :goto GOTO-PAGE-FUNCTION
+ :next NEXT-PAGE-FUNCTION
+ :prev PREV-PAGE-FUNCTION
+ :current FUNCTION-RETURNING-CURRENT-PAGE
+ :max FUNCTION-RETURNING-MAX-PAGE)
+
+Other packages can add support for additional document viewing modes
+by adding entries to this list.")
+
+(defun doc-dual-view--call-func (mode-config action &rest args)
+ "Call function for ACTION from MODE-CONFIG with ARGS."
+ (apply (plist-get mode-config action) args))
(defun doc-dual-view--order-windows (windows)
"Order WINDOWS based on their position: leftmost, then topmost."
- (sort windows
- (lambda (window-a window-b)
- (let* ((edges-a (window-edges window-a))
- (edges-b (window-edges window-b))
- (left-a (nth 0 edges-a))
- (left-b (nth 0 edges-b))
- (top-a (nth 1 edges-a))
- (top-b (nth 1 edges-b)))
- (or (< left-a left-b)
- (and (= left-a left-b)
- (< top-a top-b)))))))
+ (sort windows (lambda (window-a window-b)
+ (let* ((edges-a (window-edges window-a))
+ (edges-b (window-edges window-b))
+ (left-a (nth 0 edges-a))
+ (left-b (nth 0 edges-b))
+ (top-a (nth 1 edges-a))
+ (top-b (nth 1 edges-b)))
+ (or (< left-a left-b)
+ (and (= left-a left-b) (< top-a top-b)))))))
(defvar doc-dual-view--sync-in-progress nil
"Flag to prevent recursive sync operations.")
@@ -87,46 +90,44 @@ where GOTO-FUNCTIONS is of the form (GOTO-FUNC NEXT-FUNC
PREV-FUNC)."
(unless doc-dual-view--sync-in-progress
(let ((doc-dual-view--sync-in-progress t))
(when-let*
- ((mode-funcs (assoc major-mode doc-dual-view-modes))
+ ((mode-config (cdr (assoc major-mode doc-dual-view-modes)))
(windows (doc-dual-view--order-windows
(get-buffer-window-list nil nil nil)))
((> (length windows) 1)))
- (let* ((goto-func (car (nth 1 mode-funcs)))
- (current-page-func (nth 2 mode-funcs))
- (current-page (funcall current-page-func))
- (max-page-func (nth 3 mode-funcs))
- (max-page (funcall max-page-func))
+ (let* ((current-page (doc-dual-view--call-func mode-config :current))
+ (max-page (doc-dual-view--call-func mode-config :max))
(current-window (selected-window))
(window-index (seq-position windows current-window)))
(seq-do-indexed
(lambda (win i)
- (when (and (not (eq win current-window))
- (window-live-p win))
+ (unless (eq win current-window)
(let ((target-page
(min max-page
(max 1 (+ current-page (- i window-index))))))
(with-selected-window win
- (let ((current (funcall current-page-func)))
- (when (not (= current target-page))
- (run-with-idle-timer
- 0.001 nil
- (lambda (target-win func page)
- (when (window-live-p target-win)
- (with-selected-window target-win
- (funcall func page))))
- win goto-func target-page)))))))
+ (unless (= target-page
+ (doc-dual-view--call-func mode-config :current))
+ (run-with-idle-timer
+ 0.001 nil
+ (lambda (target-win config page)
+ (when (window-live-p target-win)
+ (with-selected-window target-win
+ (doc-dual-view--call-func config :goto page))))
+ win mode-config target-page))))))
windows))))))
;;;###autoload
(define-minor-mode doc-dual-view-mode
"Minor mode to sync pages between two windows showing the same document."
:global nil
- (dolist (mode-funcs doc-dual-view-modes)
- (let ((goto-funcs (cadr mode-funcs)))
- (dolist (goto-func goto-funcs)
- (if doc-dual-view-mode
- (advice-add goto-func :after #'doc-dual-view--sync-pages)
- (advice-remove goto-func #'doc-dual-view--sync-pages))))))
+ (dolist (mode-entry doc-dual-view-modes)
+ (let* ((mode (car mode-entry))
+ (mode-config (cdr mode-entry)))
+ (dolist (action '(:goto :next :prev))
+ (let ((func (plist-get mode-config action)))
+ (if doc-dual-view-mode
+ (advice-add func :after #'doc-dual-view--sync-pages)
+ (advice-remove func #'doc-dual-view--sync-pages)))))))
(defun doc-dual-view--maybe-enable ()
"Enable `doc-dual-view-mode' if appropriate for this buffer."