branch: externals/doc-view-follow commit e3ac3351a24b95efec64140b49ed3267a9485874 Author: Paul Nelson <ultr...@gmail.com> Commit: Paul Nelson <ultr...@gmail.com>
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."