branch: externals/bufferlo
commit 4eaab7e03fef1e751f50fa64bacc55e0e5700edf
Author: Florian Rommel <m...@florommel.de>
Commit: Florian Rommel <m...@florommel.de>

    Streamline frame & tab bookmark loading and saving
    
    Clean up the code.
    bufferlo-bookmark-{frame|tab}-save now ignore the policies if they
    already have an associated bookmark.
---
 bufferlo.el | 237 +++++++++++++++++++++++++++++-------------------------------
 1 file changed, 113 insertions(+), 124 deletions(-)

diff --git a/bufferlo.el b/bufferlo.el
index 46d8b0d3a9..6e8a87b8dc 100644
--- a/bufferlo.el
+++ b/bufferlo.el
@@ -1899,34 +1899,40 @@ FRAME specifies the frame; the default value of nil 
selects the current frame."
                (when-let (replace (assoc (cadr bc) replace-alist))
                  (setf (cadr bc) (cdr replace)))))))))
 
-(defun bufferlo--bookmark-get-duplicate-policy (thing default-policy)
+(defun bufferlo--bookmark-get-duplicate-policy (thing default-policy mode)
   "Get the duplicate policy for THING bookmarks.
 THING should be either \"frame\" or \"tab\".
 Ask the user if DEFAULT-POLICY is set to \\='prompt.
-This functions throws :noload when the user quits."
+MODE is either \\='load or \\='save, depending on the invoking action.
+This functions throws :abort when the user quits."
   (if (not (eq default-policy 'prompt))
       default-policy
     (pcase (let ((read-answer-short t))
              (with-local-quit
                (read-answer
-                (concat
-                 (format "%s bookmark name already active: " (capitalize 
thing))
-                 "Allow, Clear bookmark after loading, Raise existing ")
-                '(("allow" ?a "Allow duplicate")
-                  ("clear" ?c "Clear the bookmark after loading")
-                  ("raise" ?r (format "Raise the %s with the existing bookmark"
-                                      thing))
+                (format "%s bookmark name already active: Allow, %s, Raise 
existing "
+                        (capitalize thing)
+                        (if (eq mode 'save)
+                            "Clear other bookmark"
+                          "Clear bookmark after loading"))
+                `(("allow" ?a "Allow duplicate")
+                  ("clear" ?c
+                   ,(if (eq mode 'save)
+                        (format "Clear the other %s's bookmark association" 
thing)
+                      (format "Clear this %s's bookmark association after 
loading" thing)))
+                  ("raise" ?r
+                   ,(format "Raise the %s with the active bookmark and quit" 
thing))
                   ("help" ?h "Help")
-                  ("quit" ?q "Quit and abort bookmark loading")))))
+                  ("quit" ?q "Quit and abort")))))
       ("allow" 'allow)
       ("clear" 'clear)
       ("raise" 'raise)
-      (_ (throw :noload t)))))
+      (_ (throw :abort t)))))
 
 (defun bufferlo--bookmark-tab-get-replace-policy ()
   "Get the replace policy for tab bookmarks.
 Ask the user if `bufferlo-bookmark-tab-replace-policy' is set to \\='prompt.
-This functions throws :noload when the user quits."
+This functions throws :abort when the user quits."
   (if (not (eq bufferlo-bookmark-tab-replace-policy 'prompt))
       bufferlo-bookmark-frame-load-policy
     (pcase (let ((read-answer-short t))
@@ -1935,29 +1941,38 @@ This functions throws :noload when the user quits."
                             '(("replace" ?o "Replace tab")
                               ("new" ?n "New tab")
                               ("help" ?h "Help")
-                              ("quit" ?q "Quit and abort bookmark loading")))))
+                              ("quit" ?q "Quit and abort")))))
       ("replace" 'replace)
       ("new" 'new)
-      (_ (throw :noload t)))))
+      (_ (throw :abort t)))))
 
-(defun bufferlo--bookmark-tab-get-clear-policy ()
+(defun bufferlo--bookmark-tab-get-clear-policy (mode)
   "Get the clear policy for tab bookmarks.
 Ask the user if `bufferlo-bookmark-tab-in-bookmarked-frame-policy' is
-set to \\='prompt.  This functions throws :noload when the user quits."
+set to \\='prompt.  This functions throws :abort when the user quits.
+MODE is either \\='load, \\='save, or \\='save-frame, depending on the
+invoking action.  This functions throws :abort when the user quits."
   (if (not (eq bufferlo-bookmark-tab-in-bookmarked-frame-policy 'prompt))
       bufferlo-bookmark-frame-load-policy
     (pcase (let ((read-answer-short t))
              (with-local-quit
                (read-answer
-                (concat "Tab bookmark conflicts with frame bookmark: "
-                        "Allow tab bookmark, Clear tab bookmark ")
-                '(("allow" ?a "Allow tab bookmark")
-                  ("clear" ?c "Clear tab bookmark")
+                (concat
+                 (pcase mode
+                   ('load "Tab bookmark conflicts with frame bookmark: ")
+                   ('save "Frame already bookmarked: ")
+                   ('save-frame "Tabs in this frame are bookmarked: "))
+                 (format "Allow tab bookmark, Clear %s bookmark "
+                         (if (eq mode 'save) "frame" "tab")))
+                `(("allow" ?a "Allow tab bookmark")
+                  ("clear" ?c ,(if (eq mode 'save)
+                                   "Clear frame bookmark, set tab bookmark"
+                                 "Clear tab bookmark"))
                   ("help" ?h "Help")
-                  ("quit" ?q "Quit and abort bookmark loading")))))
+                  ("quit" ?q "Quit and abort")))))
       ("allow" 'allow)
       ("clear" 'clear)
-      (_ (throw :noload t)))))
+      (_ (throw :abort t)))))
 
 (defvar bufferlo--bookmark-handler-no-message nil)
 
@@ -1968,7 +1983,7 @@ via `bufferlo--bookmark-tab-make'. If the optional 
argument
 NO-MESSAGE is non-nil, inhibit the message after successfully
 restoring the bookmark. If EMBEDDED-TAB is non-nil, indicate that
 this bookmark is embedded in a frame bookmark."
-  (catch :noload
+  (catch :abort
     (let* ((bookmark-name (if (not embedded-tab)
                               (bookmark-name-from-full-record bookmark)
                             nil))
@@ -1980,8 +1995,7 @@ this bookmark is embedded in a frame bookmark."
       ;; Bookmark already loaded in another tab?
       (when abm
         (let ((duplicate-policy (bufferlo--bookmark-get-duplicate-policy
-                                 "tab"
-                                 bufferlo-bookmark-tab-duplicate-policy)))
+                                 "tab" bufferlo-bookmark-tab-duplicate-policy 
'load)))
           (pcase duplicate-policy
             ('allow)
             ('clear
@@ -1991,7 +2005,7 @@ this bookmark is embedded in a frame bookmark."
              (funcall msg-append "cleared tab bookmark"))
             ('raise
              (bufferlo--bookmark-raise abm)
-             (throw :noload t)))))
+             (throw :abort t)))))
 
       ;; Bookmark not loaded as part of a frame bookmark?
       (unless embedded-tab
@@ -2007,7 +2021,7 @@ this bookmark is embedded in a frame bookmark."
         ;; Handle an independent tab bookmark inside a frame bookmark
         (when (and bookmark-name
                    (frame-parameter nil 'bufferlo-bookmark-frame-name))
-          (let ((clear-policy (bufferlo--bookmark-tab-get-clear-policy)))
+          (let ((clear-policy (bufferlo--bookmark-tab-get-clear-policy 'load)))
             (pcase clear-policy
               ('clear
                (setq disconnect-tbm-p t))
@@ -2016,7 +2030,7 @@ this bookmark is embedded in a frame bookmark."
                (funcall msg-append "cleared tab bookmark"))))))
 
       ;; Do the real work: restore the tab
-      ;; NOTE: No :noload throws after this point
+      ;; NOTE: No :abort throws after this point
       (let* ((ws (copy-tree (alist-get 'window bookmark)))
              (dummy (generate-new-buffer " *bufferlo dummy buffer*"));
              (restore (lambda (bm)
@@ -2083,7 +2097,7 @@ FRAME specifies the frame; the default value of nil 
selects the current frame."
 (defun bufferlo--bookmark-frame-get-load-policy ()
   "Get the load policy for frame bookmarks.
 Ask the user if `bufferlo-bookmark-frame-load-policy' is set to \\='prompt.
-This functions throws :noload when the user quits."
+This functions throws :abort when the user quits."
   (if (not (eq bufferlo-bookmark-frame-load-policy 'prompt))
       bufferlo-bookmark-frame-load-policy
     (pcase (let ((read-answer-short t))
@@ -2096,18 +2110,18 @@ This functions throws :noload when the user quits."
                   ("replace" ?r "Replace frame, adopt the loaded bookmark")
                   ("merge" ?m "Merge the new tab content with the existing 
bookmark")
                   ("help" ?h "Help")
-                  ("quit" ?q "Quit and abort bookmark loading")))))
+                  ("quit" ?q "Quit and abort")))))
       ("current" 'replace-frame-retain-current-bookmark)
       ("replace" 'replace-frame-adopt-loaded-bookmark)
       ("merge" 'merge)
-      (_ (throw :noload t)))))
+      (_ (throw :abort t)))))
 
 (defun bufferlo--bookmark-frame-handler (bookmark &optional no-message)
   "Handle bufferlo frame bookmark.
 The argument BOOKMARK is the to-be restored frame bookmark created via
 `bufferlo--bookmark-frame-make'.  The optional argument NO-MESSAGE inhibits
 the message after successfully restoring the bookmark."
-  (catch :noload
+  (catch :abort
     (let* ((bookmark-name (bookmark-name-from-full-record bookmark))
            (abm (assoc bookmark-name (bufferlo--active-bookmarks)))
            (fbm (frame-parameter nil 'bufferlo-bookmark-frame-name))
@@ -2125,11 +2139,10 @@ the message after successfully restoring the bookmark."
       ;; Bookmark already loaded in another frame?
       (when abm
         (setq duplicate-policy (bufferlo--bookmark-get-duplicate-policy
-                                "frame"
-                                bufferlo-bookmark-frame-duplicate-policy))
+                                "frame" 
bufferlo-bookmark-frame-duplicate-policy 'load))
         (when (eq duplicate-policy 'raise)
           (bufferlo--bookmark-raise abm)
-          (throw :noload t)))
+          (throw :abort t)))
 
       ;; No currently active bookmark in the frame?
       (if (not fbm)
@@ -2142,7 +2155,7 @@ the message after successfully restoring the bookmark."
            (when (not (equal fbm bookmark-name)) ; allow reloads of existing 
bookmark
              (unless no-message
                (message "Frame already bookmarked as %s; not loaded." fbm))
-             (throw :noload t)))
+             (throw :abort t)))
           ('replace-frame-retain-current-bookmark
            (funcall msg-append (format "retained existing bookmark %s." fbm)))
           ('replace-frame-adopt-loaded-bookmark
@@ -2153,7 +2166,7 @@ the message after successfully restoring the bookmark."
                                        bookmark-name)))))
 
       ;; Do the real work with the target frame selected (current or newly 
created)
-      ;; NOTE: No :noload throws after this point
+      ;; NOTE: No :abort throws after this point
       (with-selected-frame (if new-frame-p
                                (with-temp-buffer (make-frame))
                              (selected-frame))
@@ -2656,54 +2669,41 @@ is not recommended."
           nil nil nil 'bufferlo-bookmark-tab-history
           (alist-get 'bufferlo-bookmark-tab-name (bufferlo--current-tab)))))
   (bufferlo--warn)
-  (catch :nosave
-    (let ((msg))
-      (when-let ((abm (assoc name (bufferlo--active-bookmarks)))
-                 (duplicate-policy bufferlo-bookmark-tab-duplicate-policy))
-        (when (eq duplicate-policy 'prompt)
-          (pcase (let ((read-answer-short t))
-                   (with-local-quit
-                     (read-answer "Tab bookmark name already active: Allow, 
Clear existing, Raise existing, Quit "
-                                  '(("allow" ?a "Allow duplicate")
-                                    ("clear" ?c "Clear the active matching tab 
bookmarks, preferring new")
-                                    ("raise" ?r "Raise the existing tab 
bookmark")
-                                    ("help" ?h "Help")
-                                    ("quit" ?q "Quit with no changes")))))
-            ("allow" (setq duplicate-policy 'allow))
-            ("clear" (setq duplicate-policy 'clear))
-            ("raise" (setq duplicate-policy 'raise))
-            (_ (throw :nosave t))))
-        (pcase duplicate-policy
-          ('allow)
-          ('clear
-           (bufferlo--clear-tab-bookmarks-by-name name))
-          ('clear-warn
-           (bufferlo--clear-tab-bookmarks-by-name name)
-           (setq msg (concat msg "; cleared duplicate active tab bookmarks")))
-          ('raise
-           (bufferlo--bookmark-raise abm)
-           (throw :nosave t))))
-      (when (frame-parameter nil 'bufferlo-bookmark-frame-name)
-        (let ((clear-policy bufferlo-bookmark-tab-in-bookmarked-frame-policy))
-          (when (eq clear-policy 'prompt)
-            (pcase (let ((read-answer-short t))
-                     (with-local-quit
-                       (read-answer "Frame already bookmarked: Allow tab 
bookmark, Clear frame bookmark, Quit to cancel "
-                                    '(("allow" ?a "Allow tab bookmark, retain 
frame bookmark")
-                                      ("clear" ?c "Clear frame bookmark, set 
tab bookmark")
-                                      ("help" ?h "Help")
-                                      ("quit" ?q "Quit--retain the frame 
bookmark")))))
-              ("allow" (setq clear-policy 'allow))
-              ("clear" (setq clear-policy 'clear))
-              (_ (setq clear-policy nil)))) ; quit case
-          (pcase clear-policy
+  (catch :abort
+    (let* ((abm (assoc name (bufferlo--active-bookmarks)))
+           (tbm (alist-get 'bufferlo-bookmark-tab-name 
(tab-bar--current-tab-find)))
+           (msg)
+           (msg-append (lambda (s) (setq msg (concat msg "; " s)))))
+
+      ;; Only check policies when the bm is not already associated with this 
tab
+      (unless (and tbm (equal tbm (car abm)))
+
+        ;; Bookmark already loaded in another tab?
+        (when abm
+          (pcase (bufferlo--bookmark-get-duplicate-policy
+                  "tab" bufferlo-bookmark-tab-duplicate-policy 'save)
+            ('allow)
+            ('clear
+             (bufferlo--clear-tab-bookmarks-by-name name))
+            ('clear-warn
+             (bufferlo--clear-tab-bookmarks-by-name name)
+             (funcall msg-append "cleared duplicate active tab bookmark"))
+            ('raise
+             (bufferlo--bookmark-raise abm)
+             (throw :abort t))))
+
+        ;; Tab inside a frame bookmark?
+        (when (frame-parameter nil 'bufferlo-bookmark-frame-name)
+          (pcase (bufferlo--bookmark-tab-get-clear-policy 'save)
             ('allow)
             ('clear
              (set-frame-parameter nil 'bufferlo-bookmark-frame-name nil))
             ('clear-warn
              (set-frame-parameter nil 'bufferlo-bookmark-frame-name nil)
-             (setq msg (concat msg "; cleared frame bookmark")))
+             (funcall msg-append "cleared frame bookmark"))
             (_ ))))
+
+      ;; Finally, save the bookmark
       (bufferlo--bookmark-tab-save name no-overwrite no-message msg))))
 
 (defun bufferlo-bookmark-tab-load (name)
@@ -2805,55 +2805,44 @@ but is not recommended."
           nil nil nil 'bufferlo-bookmark-frame-history
           (frame-parameter nil 'bufferlo-bookmark-frame-name))))
   (bufferlo--warn)
-  (catch :nosave
-    (let ((msg))
-      (when-let ((abm (assoc name (bufferlo--active-bookmarks)))
-                 (duplicate-policy bufferlo-bookmark-frame-duplicate-policy))
-        (when (eq duplicate-policy 'prompt)
-          (pcase (let ((read-answer-short t))
-                   (with-local-quit
-                     (read-answer "Frame bookmark name already active: Allow, 
Clear existing, Raise existing, Quit "
-                                  '(("allow" ?a "Allow duplicate")
-                                    ("clear" ?c "Clear the active matching 
frame bookmarks, preferring new")
-                                    ("raise" ?r "Raise the existing frame 
bookmark")
-                                    ("help" ?h "Help")
-                                    ("quit" ?q "Quit with no changes")))))
-            ("allow" (setq duplicate-policy 'allow))
-            ("clear" (setq duplicate-policy 'clear))
-            ("raise" (setq duplicate-policy 'raise))
-            (_ (throw :nosave t))))
-        (pcase duplicate-policy
-          ('allow)
-          ('clear
-           (bufferlo--clear-frame-bookmarks-by-name name))
-          ('clear-warn
-           (bufferlo--clear-frame-bookmarks-by-name name)
-           (setq msg (concat msg "; cleared duplicate active frame 
bookmarks")))
-          ('raise
-           (bufferlo--bookmark-raise abm)
-           (throw :nosave t))))
-      (when (> (length (bufferlo--active-bookmarks (list (selected-frame)) 
'tbm)) 0)
-        (let ((clear-policy bufferlo-bookmark-tab-in-bookmarked-frame-policy))
-          (when (eq clear-policy 'prompt)
-            (pcase (let ((read-answer-short t))
-                     (with-local-quit
-                       (read-answer "Tabs in this frame have bookmarks: Allow 
tab bookmarks, Clear tab bookmarks "
-                                    '(("allow" ?a "Allow tab bookmarks")
-                                      ("clear" ?c "Clear tab bookmarks")
-                                      ("help" ?h "Help")
-                                      ("quit" ?q "Quit")))))
-              ("allow" (setq clear-policy 'allow))
-              ("clear" (setq clear-policy 'clear))
-              (_ (throw :nosave t))))
-          (pcase clear-policy
+  (catch :abort
+    (let* ((abm (assoc name (bufferlo--active-bookmarks)))
+           (fbm (frame-parameter nil 'bufferlo-bookmark-frame-name))
+           (msg)
+           (msg-append (lambda (s) (setq msg (concat msg "; " s)))))
+
+      ;; Only check policies when the bm is not already associated with this 
frame
+      (unless (and fbm (equal fbm (car abm)))
+
+        ;; Bookmark already loaded in another frame?
+        (when abm
+          (pcase (bufferlo--bookmark-get-duplicate-policy
+                  "frame" bufferlo-bookmark-frame-duplicate-policy 'save)
+            ('allow)
+            ('clear
+             (bufferlo--clear-frame-bookmarks-by-name name))
+            ('clear-warn
+             (bufferlo--clear-frame-bookmarks-by-name name)
+             (funcall msg-append "cleared duplicate active frame bookmark"))
+            ('raise
+             (bufferlo--bookmark-raise abm)
+             (throw :abort t))))
+
+        ;; Tab bookmarks in this frame?
+        (when (> (length
+                  (bufferlo--active-bookmarks (list (selected-frame)) 'tbm))
+                 0)
+          (pcase (bufferlo--bookmark-tab-get-clear-policy 'save-frame)
             ('clear
              (let ((current-prefix-arg '(4))) ; emulate C-u
                (bufferlo-clear-active-bookmarks (list (selected-frame)))))
             ('clear-warn
              (let ((current-prefix-arg '(4))) ; emulate C-u
                (bufferlo-clear-active-bookmarks (list (selected-frame))))
-             (setq msg (concat msg "; cleared tab bookmarks")))
+             (funcall msg-append "cleared tab bookmarks"))
             ('allow))))
+
+      ;; Finally, save the bookmark
       (bufferlo--bookmark-frame-save name no-overwrite no-message msg))))
 
 (defun bufferlo-bookmark-frame-load (name)
@@ -3014,7 +3003,7 @@ one to be saved will take precedence.
 Duplicate bookmarks are handled according to
 `bufferlo-bookmarks-save-duplicates-policy'."
   (interactive)
-  (catch :nosave
+  (catch :abort
     (when-let ((duplicate-bookmarks (bufferlo--active-bookmark-duplicates))
                (duplicate-policy bufferlo-bookmarks-save-duplicates-policy))
       (when (eq duplicate-policy 'prompt)
@@ -3027,10 +3016,10 @@ Duplicate bookmarks are handled according to
                                   ("quit" ?q "Quit with no changes")))))
           ("allow" (setq duplicate-policy 'allow))
           ("disallow" (setq duplicate-policy 'disallow))
-          (_ (throw :nosave t))))
+          (_ (throw :abort t))))
       (pcase duplicate-policy
         ('allow)
-        (_ (throw :nosave t))))
+        (_ (throw :abort t))))
     (let ((bufferlo-bookmarks-save-predicate-functions
            (if (or all (consp current-prefix-arg))
                (list #'bufferlo-bookmarks-save-all-p)

Reply via email to