branch: externals/bufferlo
commit 6303e22034df7222fead696463b6950b51256eee
Author: shipmints <shipmi...@gmail.com>
Commit: Flo Rommel <m...@florommel.de>

    Idiomatic use of cl-labels
    
    A few related refinements.
---
 bufferlo.el | 1125 ++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 569 insertions(+), 556 deletions(-)

diff --git a/bufferlo.el b/bufferlo.el
index 732450e202..eb3e246bcb 100644
--- a/bufferlo.el
+++ b/bufferlo.el
@@ -1508,9 +1508,10 @@ advised functions.  Honors 
`bufferlo-bookmark-frame-duplicate-policy'."
                (> (seq-count (lambda (x) (equal bookmark-name (car x)))
                              (bufferlo--active-bookmarks))
                   1)))
-    (let* ((msg nil)
-           (msg-append (lambda (s) (setq msg (concat msg "; " s))))
-           (aborted
+    (let ((msg nil))
+      (cl-labels
+          ((msg-append (s) (setq msg (concat msg "; " s))))
+        (when
             (catch :abort
               ;; `bufferlo--bookmark-get-duplicate-policy' throws :abort
               (let ((duplicate-policy (bufferlo--bookmark-get-duplicate-policy
@@ -1524,7 +1525,7 @@ advised functions.  Honors 
`bufferlo-bookmark-frame-duplicate-policy'."
                    (setq bookmark-name nil))
                   ('clear-warn
                    (setq bookmark-name nil)
-                   (funcall msg-append "cleared frame bookmark"))
+                   (msg-append "cleared frame bookmark"))
                   ('ignore
                    (throw :abort t))
                   ('raise
@@ -1539,9 +1540,8 @@ advised functions.  Honors 
`bufferlo-bookmark-frame-duplicate-policy'."
                 (message "Undelete frame bufferlo bookmark%s%s"
                          (if bookmark-name (format ": %s" bookmark-name) "")
                          (or msg "")))
-              nil)))
-      (when aborted
-        (delete-frame)))))
+              nil)
+          (delete-frame))))))
 
 (defun bufferlo--tab-post-undo-close-tab-function (tab)
   "Handle `tab-bar-undo-close-tab' TAB.
@@ -1551,9 +1551,10 @@ Honors `bufferlo-bookmark-tab-duplicate-policy'."
                (> (seq-count (lambda (x) (equal bookmark-name (car x)))
                              (bufferlo--active-bookmarks))
                   1)))
-    (let* ((msg nil)
-           (msg-append (lambda (s) (setq msg (concat msg "; " s))))
-           (aborted
+    (let ((msg nil))
+      (cl-labels
+          ((msg-append (s) (setq msg (concat msg "; " s))))
+        (when
             (catch :abort
               (let ((duplicate-policy (bufferlo--bookmark-get-duplicate-policy
                                        bookmark-name "tab"
@@ -1565,7 +1566,7 @@ Honors `bufferlo-bookmark-tab-duplicate-policy'."
                    (setq bookmark-name nil))
                   ('clear-warn
                    (setq bookmark-name nil)
-                   (funcall msg-append "cleared tab bookmark"))
+                   (msg-append "cleared tab bookmark"))
                   ('ignore
                    (throw :abort t))
                   ('raise
@@ -1584,10 +1585,9 @@ Honors `bufferlo-bookmark-tab-duplicate-policy'."
                 (message "Undo close tab bufferlo bookmark%s%s"
                          (if bookmark-name (format ": %s" bookmark-name) "")
                          (or msg "")))
-              nil)))
-      (when aborted
-        (let (tab-bar-tab-prevent-close-functions)
-          (tab-bar-close-tab))))))
+              nil)
+          (let (tab-bar-tab-prevent-close-functions)
+            (tab-bar-close-tab)))))))
 
 (defun bufferlo--tab-bar-undo-close-tab-advice (oldfn &rest args)
   "Activate the advice for `tab-bar-undo-close-tab'.
@@ -1670,31 +1670,30 @@ If EXCLUSIVE-TABNUM is nil, select the default tab.
 If EXCLUSIVE-TABNUM is \\='all, select all tabs of the frame.
 If EXCLUDE-FRAME is nil, do not exclude a local buffer list
 and ignore EXCLUDE-TABNUM."
-  (let* ((exclude-tab (when (and exclude-tabnum (not (eq exclude-tabnum 'all)))
-                        (nth exclude-tabnum
-                             (funcall tab-bar-tabs-function exclude-frame))))
-         (get-inactive-tabs-buffers
-          (lambda (f)
-            (seq-mapcat
-             (lambda (tb)
-               (unless (and (eq f exclude-frame)
-                            (or (eq exclude-tabnum 'all)
-                                (eq tb exclude-tab)))
-                 (bufferlo--get-tab-buffers tb)))
-             (funcall tab-bar-tabs-function f))))
-         (get-frames-buffers
-          (lambda ()
-            (seq-mapcat
-             (lambda (f)
-               (unless (and (eq f exclude-frame)
-                            (or (eq exclude-tabnum 'all)
-                                (not exclude-tab)
-                                (eq 'current-tab (car exclude-tab))))
-                 (bufferlo--current-buffers f)))
-             (frame-list)))))
-    (seq-uniq
-     (append (seq-mapcat get-inactive-tabs-buffers (frame-list))
-             (funcall get-frames-buffers)))))
+  (let ((exclude-tab (when (and exclude-tabnum (not (eq exclude-tabnum 'all)))
+                       (nth exclude-tabnum
+                            (funcall tab-bar-tabs-function exclude-frame)))))
+    (cl-labels
+        ((get-inactive-tabs-buffers (f)
+           (seq-mapcat
+            (lambda (tb)
+              (unless (and (eq f exclude-frame)
+                           (or (eq exclude-tabnum 'all)
+                               (eq tb exclude-tab)))
+                (bufferlo--get-tab-buffers tb)))
+            (funcall tab-bar-tabs-function f)))
+         (get-frames-buffers ()
+           (seq-mapcat
+            (lambda (f)
+              (unless (and (eq f exclude-frame)
+                           (or (eq exclude-tabnum 'all)
+                               (not exclude-tab)
+                               (eq 'current-tab (car exclude-tab))))
+                (bufferlo--current-buffers f)))
+            (frame-list))))
+      (seq-uniq
+       (append (seq-mapcat #'get-inactive-tabs-buffers (frame-list))
+               (get-frames-buffers))))))
 
 (defun bufferlo--get-orphan-buffers ()
   "Get all buffers that are not in any local list of a frame or tab."
@@ -1841,34 +1840,35 @@ argument INTERNAL-TOO is non-nil."
   (setq frame (or frame (selected-frame)))
   (when (or (not bufferlo-delete-frame-kill-buffers-prompt)
             (y-or-n-p "Kill frame and its buffers? "))
-    (let ((fbm (frame-parameter frame 'bufferlo-bookmark-frame-name))
-          (save-as-current (lambda (frame)
-                             ;; We need this if called in a batch
-                             (with-selected-frame frame
-                               (bufferlo-bookmark-frame-save-current)))))
-      (pcase bufferlo-bookmark-frame-save-on-delete
-        ((or 't 'on-kill-buffers)
-         (when (y-or-n-p (format-message "Save frame bookmark `%s'? " fbm))
-           (funcall save-as-current frame)))
-        ((or 'when-bookmarked 'on-kill-buffers-when-bookmarked)
-         (when fbm (funcall save-as-current frame))))
-      ;; If batch, raise frame in case of prompts for buffers that need saving.
-      (raise-frame frame)
-      (let ((bufferlo-kill-buffers-prompt nil)
-            (bufferlo--kill-buffer-frame-or-tab-closing t))
-        (bufferlo-kill-buffers nil frame 'all internal-too))
-      ;; kill-buffer calls replace-buffer-in-windows which will
-      ;; delete windows *and* their frame so we have to test if
-      ;; the frame in question is still live.
-      (when (frame-live-p frame)
-        ;; TODO: Emacs 30 frame-deletable-p
-        ;; account for top-level, non-child frames
-        (when (= 1 (length (seq-filter
-                            (lambda (x) (null (frame-parameter x 
'parent-frame)))
-                            (frame-list))))
-          (make-frame)) ; leave one for the user
-        (let ((bufferlo-bookmark-frame-save-on-delete nil))
-          (delete-frame frame))))))
+    (let ((fbm (frame-parameter frame 'bufferlo-bookmark-frame-name)))
+      (cl-labels
+          ((save-as-current (frame)
+             ;; We need this if called in a batch
+             (with-selected-frame frame
+               (bufferlo-bookmark-frame-save-current))))
+        (pcase bufferlo-bookmark-frame-save-on-delete
+          ((or 't 'on-kill-buffers)
+           (when (y-or-n-p (format-message "Save frame bookmark `%s'? " fbm))
+             (save-as-current frame)))
+          ((or 'when-bookmarked 'on-kill-buffers-when-bookmarked)
+           (when fbm (save-as-current frame))))
+        ;; If batch, raise frame in case of prompts for buffers that need 
saving.
+        (raise-frame frame)
+        (let ((bufferlo-kill-buffers-prompt nil)
+              (bufferlo--kill-buffer-frame-or-tab-closing t))
+          (bufferlo-kill-buffers nil frame 'all internal-too))
+        ;; kill-buffer calls replace-buffer-in-windows which will
+        ;; delete windows *and* their frame so we have to test if
+        ;; the frame in question is still live.
+        (when (frame-live-p frame)
+          ;; TODO: Emacs 30 frame-deletable-p
+          ;; account for top-level, non-child frames
+          (when (= 1 (length (seq-filter
+                              (lambda (x) (null (frame-parameter x 
'parent-frame)))
+                              (frame-list))))
+            (make-frame)) ; leave one for the user
+          (let ((bufferlo-bookmark-frame-save-on-delete nil))
+            (delete-frame frame)))))))
 
 (defun bufferlo-tab-close-kill-buffers (&optional killall internal-too)
   "Close the current tab and kill the local buffers.
@@ -1933,63 +1933,61 @@ for the to-be-selected frame and tab.
 This does not select the buffer -- just the containing frame and tab."
   (interactive "b")
   (bufferlo--warn)
-  (let* ((buffer (get-buffer buffer-or-name))
-         (search-tabs (lambda (f)
-                        (let ((i 0))
-                          (mapcar
-                           (lambda (tab)
-                             (setq i (1+ i))
-                             (when (bufferlo-local-buffer-p buffer f (1- i) t)
-                               (list f (frame-parameter f 'name)
-                                     (eq f (selected-frame))
-                                     i (cdr (assq 'name tab)))))
-                           (funcall tab-bar-tabs-function f)))))
-         (search-frames (lambda (f)
-                          (unless (frame-parameter f 'no-accept-focus)
-                            (if (funcall tab-bar-tabs-function f)
-                                ;; has tabs
-                                (funcall search-tabs f)
-                              ;; has no tabs
-                              (when (bufferlo-local-buffer-p buffer f nil t)
-                                (list (list f (frame-parameter f 'name)
-                                            (eq f (selected-frame))
-                                            nil nil)))))))
-         (candidates (seq-filter 'identity
-                                 (seq-mapcat
-                                  (lambda (f)
-                                    (funcall search-frames f))
-                                  (frame-list))))
-         (candidates (mapcar
-                      (lambda (c)
-                        (let ((sel (if (nth 2 c) " [this]" ""))
-                              (frame-name (nth 1 c))
-                              (frame-obj  (nth 0 c))
-                              (tab-index  (nth 3 c))
-                              (tab-name   (nth 4 c)))
-                          (if tab-index
-                              (cons (format "Frame: %s (%s)%s  Tab %s: %s"
-                                            frame-name frame-obj sel
-                                            tab-index tab-name)
-                                    c)
-                            (cons (format "Frame: %s (%s)%s"
-                                          frame-name frame-obj sel)
-                                  c))))
-                      candidates))
-         (selected (if (cdr candidates)
-                       (completing-read
-                        "Select frame/tab: "
-                        candidates
-                        nil 'require-match)
-                     (caar candidates)))
-         (selected (assoc selected candidates)))
-    (if (not selected)
-        (message "Orphan: No frame/tab contains buffer '%s'" (buffer-name 
buffer))
-      (let ((frame (nth 1 selected))
-            (tab-index (nth 4 selected)))
-        (select-frame-set-input-focus frame)
-        (when tab-index
-          (tab-bar-select-tab tab-index))
-        frame))))
+  (let ((buffer (get-buffer buffer-or-name)))
+    (cl-labels
+        ((search-tabs (f)
+           (let ((i 0))
+             (mapcar
+              (lambda (tab)
+                (setq i (1+ i))
+                (when (bufferlo-local-buffer-p buffer f (1- i) t)
+                  (list f (frame-parameter f 'name)
+                        (eq f (selected-frame))
+                        i (cdr (assq 'name tab)))))
+              (funcall tab-bar-tabs-function f))))
+         (search-frames (f)
+           (unless (frame-parameter f 'no-accept-focus)
+             (if (funcall tab-bar-tabs-function f)
+                 ;; has tabs
+                 (search-tabs f)
+               ;; has no tabs
+               (when (bufferlo-local-buffer-p buffer f nil t)
+                 (list (list f (frame-parameter f 'name)
+                             (eq f (selected-frame))
+                             nil nil)))))))
+      (let* ((candidates (seq-filter #'identity
+                                     (seq-mapcat #'search-frames 
(frame-list))))
+             (candidates (mapcar
+                          (lambda (c)
+                            (let ((sel (if (nth 2 c) " [this]" ""))
+                                  (frame-name (nth 1 c))
+                                  (frame-obj  (nth 0 c))
+                                  (tab-index  (nth 3 c))
+                                  (tab-name   (nth 4 c)))
+                              (if tab-index
+                                  (cons (format "Frame: %s (%s)%s  Tab %s: %s"
+                                                frame-name frame-obj sel
+                                                tab-index tab-name)
+                                        c)
+                                (cons (format "Frame: %s (%s)%s"
+                                              frame-name frame-obj sel)
+                                      c))))
+                          candidates))
+             (selected (if (cdr candidates)
+                           (completing-read
+                            "Select frame/tab: "
+                            candidates
+                            nil 'require-match)
+                         (caar candidates)))
+             (selected (assoc selected candidates)))
+        (if (not selected)
+            (message "Orphan: No frame/tab contains buffer '%s'" (buffer-name 
buffer))
+          (let ((frame (nth 1 selected))
+                (tab-index (nth 4 selected)))
+            (select-frame-set-input-focus frame)
+            (when tab-index
+              (tab-bar-select-tab tab-index))
+            frame))))))
 
 (defun bufferlo-find-buffer-switch (buffer-or-name)
   "Switch to the frame/tab containing BUFFER-OR-NAME and select the buffer.
@@ -2675,178 +2673,178 @@ Returns nil on success, non-nil on abort."
            (disconnect-tbm-p)
            (restored-buffer-names)
            (skipped-buffer-names)
-           (msg)
-           (msg-append (lambda (s) (setq msg (concat msg "; " s)))))
-
-      ;; Bookmark already loaded in another tab?
-      (when abm
-        ;; Throws :abort
-        (let ((duplicate-policy (bufferlo--bookmark-get-duplicate-policy
-                                 bookmark-name "tab"
-                                 bufferlo-bookmark-tab-duplicate-policy
-                                 'load
-                                 embedded-tab)))
-          (pcase duplicate-policy
-            ('allow)
-            ('clear
-             (setq bookmark-name nil))
-            ('clear-warn
-             (setq bookmark-name nil)
-             (funcall msg-append "cleared tab bookmark"))
-            ('ignore
-             (throw :abort t))
-            ('raise
-             (bufferlo--bookmark-raise abm)
-             (throw :abort t)))))
-
-      ;; Bookmark not loaded as part of a frame bookmark or in a set?
-      ;; Frame and set handlers manage tabs, so we don't do it here.
-      (unless (or embedded-tab bufferlo--bookmark-set-loading)
-
-        ;; Handle an independent tab bookmark on a frame with an
-        ;; active frame bookmark.  Do this first, before a new tab is
-        ;; created.
-        (when (and bookmark-name
-                   (frame-parameter nil 'bufferlo-bookmark-frame-name))
+           (msg))
+      (cl-labels
+          ((msg-append (s) (setq msg (concat msg "; " s))))
+        ;; Bookmark already loaded in another tab?
+        (when abm
           ;; Throws :abort
-          (let ((clear-policy (bufferlo--bookmark-tab-get-clear-policy 'load)))
-            (pcase clear-policy
+          (let ((duplicate-policy (bufferlo--bookmark-get-duplicate-policy
+                                   bookmark-name "tab"
+                                   bufferlo-bookmark-tab-duplicate-policy
+                                   'load
+                                   embedded-tab)))
+            (pcase duplicate-policy
+              ('allow)
               ('clear
-               (setq disconnect-tbm-p t))
+               (setq bookmark-name nil))
               ('clear-warn
-               (setq disconnect-tbm-p t)
-               (funcall msg-append "cleared tab bookmark")))))
-
-        ;; Replace current tab or create new tab?
-        ;; Throws :abort
-        (let ((replace-policy (bufferlo--bookmark-tab-get-replace-policy)))
-          (pcase replace-policy
-            ('replace)
-            ('new
-             (unless (consp current-prefix-arg) ; user new tab suppression
-               (let ((tab-bar-new-tab-choice t))
-                 (tab-bar-new-tab-to)
-                 (let ((current-tab (cdr (bufferlo--current-tab)))
-                       (tab-explicit-name (alist-get 'tab-explicit-name 
bookmark))
-                       (tab-group (alist-get 'tab-group bookmark)))
-                   (when tab-explicit-name
-                     (setf (alist-get 'name current-tab) tab-explicit-name)
-                     (setf (alist-get 'explicit-name current-tab) t))
-                   (when tab-group
-                     (tab-bar-change-tab-group tab-group)))))))))
-
-      ;; Do the real work: restore the tab.
-      ;; 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)
-                        (let ((orig-name (car bm))
-                              (record (cadr bm))
-                              (restore-failed))
-
-                          (set-buffer dummy)
-                          ;; Test if bookmark-handler did not complain...
-                          (setq restore-failed
-                                (condition-case err
-                                    (progn
-                                      (funcall (or (bookmark-get-handler 
record)
-                                                   'bookmark-default-handler)
-                                               record)
-                                      (run-hooks 'bookmark-after-jump-hook)
-                                      nil)
-                                  (error
-                                   (message "Bufferlo bookmark: Could not 
restore %s (error %s)"
-                                            orig-name err)
-                                   t)))
-                          ;; ...then test that the buffer actually changed.
-                          (setq restore-failed (or restore-failed
-                                                   (eq (current-buffer) 
dummy)))
-
-                          (if restore-failed
-                              (progn
-                                (bufferlo--bookmark-insert-placeholer 
orig-name)
-                                (push orig-name skipped-buffer-names))
-                            (push orig-name restored-buffer-names))
-
-                          (unless (eq (current-buffer) dummy)
-                            ;; Return a list of (cons <string> <buffer>).
-                            ;; The buffer may be renamed later (by uniquify).
-                            ;; Using the buffer name directly would not
-                            ;; account for this!
-                            (cons orig-name (current-buffer))))))
-
-             (renamed (mapcar restore (alist-get 'buffer-bookmarks bookmark)))
-             (replace-renamed (lambda (b)
-                                (if-let* ((replace
-                                           (assoc b renamed)))
-                                    (cdr replace) b)))
-             (bm-buffer-list (mapcar replace-renamed
-                                     (alist-get 'buffer-list bookmark)))
-             ;; Some of the items may already be buffers after renaming.
-             ;; Others are still buffer names (strings).  These items had no
-             ;; bookmark associated with them.
-             (bm-buffer-list (seq-filter #'get-buffer bm-buffer-list))
-             (bm-buffer-list (mapcar #'get-buffer bm-buffer-list)))
-
-        (kill-buffer dummy)
-
-        ;; Note that we replace buffer names with buffers in ws.
-        ;; `window-state-put' accepts this.
-        (bufferlo--ws-replace-buffer-names ws renamed)
-
-        ;; We do the following to work around two problems with
-        ;; bookmark--jump-via.  In older versions, when called
-        ;; interactively and not through bufferlo commands, it calls a
-        ;; display-function which could interfere with
-        ;; window-state-put.
-        ;;
-        ;; In Emacs 31, bookmark--jump-via wraps the bookmark-handler
-        ;; call with save-window-excursion which restores the
-        ;; window-configuration after we've just restored the one from
-        ;; the bookmark.  We let bookmark--jump-via be evil and defer
-        ;; window-state-put until after bookmark--jump-via is done.
-        (let ((bm-after-jump-hook-sym (gensym "bufferlo-bm-after-jump-"))
-              (frame (selected-frame))
-              (tab-number (1+ (tab-bar--current-tab-index)))
-              (buffer (current-buffer)))
-          (fset bm-after-jump-hook-sym
-                (lambda ()
-                  (remove-hook 'bookmark-after-jump-hook 
bm-after-jump-hook-sym)
-                  (with-selected-frame frame ; defensive
-                    (let ((tab-bar-tab-post-select-functions))
-                      (tab-bar-select-tab tab-number) ; defensive
-                     (window-state-put ws (frame-root-window) 'safe)
-                      (set-frame-parameter nil 'buffer-list bm-buffer-list)
-                      (set-frame-parameter nil 'buried-buffer-list nil)
-                      (setf (alist-get 'bufferlo-bookmark-tab-name
-                                       (cdr (bufferlo--current-tab)))
-                            (unless disconnect-tbm-p bookmark-name))
-                      (sit-for 0)
-                      (run-hook-with-args
-                       'bufferlo-bookmark-tab-handler-functions
-                       bookmark-name
-                       (unless disconnect-tbm-p bookmark-name)
-                       (bufferlo--current-tab)
-                       restored-buffer-names
-                       skipped-buffer-names)
-                      buffer))))
-          (add-hook 'bookmark-after-jump-hook bm-after-jump-hook-sym -99)
-          (when not-jump
-            (run-hooks 'bookmark-after-jump-hook))))
-
-      ;; Log message
-      (unless (or no-message bufferlo--bookmark-handler-no-message)
-        (message "Restored bufferlo tab bookmark%s%s%s%s"
-                 (if orig-bookmark-name (format ": %s" orig-bookmark-name) "")
-                 (or msg "")
-                 (if restored-buffer-names
-                     (format " (%s)"
-                             (mapconcat #'identity restored-buffer-names ", 
")) "")
-                 (if skipped-buffer-names
-                     (format " (skipped: %s)"
-                             (mapconcat #'identity skipped-buffer-names ", ")) 
"")))
-      ;; Explicitly return success; abort returns non-nil
-      nil)))
+               (setq bookmark-name nil)
+               (msg-append "cleared tab bookmark"))
+              ('ignore
+               (throw :abort t))
+              ('raise
+               (bufferlo--bookmark-raise abm)
+               (throw :abort t)))))
+
+        ;; Bookmark not loaded as part of a frame bookmark or in a set?
+        ;; Frame and set handlers manage tabs, so we don't do it here.
+        (unless (or embedded-tab bufferlo--bookmark-set-loading)
+
+          ;; Handle an independent tab bookmark on a frame with an
+          ;; active frame bookmark.  Do this first, before a new tab is
+          ;; created.
+          (when (and bookmark-name
+                     (frame-parameter nil 'bufferlo-bookmark-frame-name))
+            ;; Throws :abort
+            (let ((clear-policy (bufferlo--bookmark-tab-get-clear-policy 
'load)))
+              (pcase clear-policy
+                ('clear
+                 (setq disconnect-tbm-p t))
+                ('clear-warn
+                 (setq disconnect-tbm-p t)
+                 (msg-append "cleared tab bookmark")))))
+
+          ;; Replace current tab or create new tab?
+          ;; Throws :abort
+          (let ((replace-policy (bufferlo--bookmark-tab-get-replace-policy)))
+            (pcase replace-policy
+              ('replace)
+              ('new
+               (unless (consp current-prefix-arg) ; user new tab suppression
+                 (let ((tab-bar-new-tab-choice t))
+                   (tab-bar-new-tab-to)
+                   (let ((current-tab (cdr (bufferlo--current-tab)))
+                         (tab-explicit-name (alist-get 'tab-explicit-name 
bookmark))
+                         (tab-group (alist-get 'tab-group bookmark)))
+                     (when tab-explicit-name
+                       (setf (alist-get 'name current-tab) tab-explicit-name)
+                       (setf (alist-get 'explicit-name current-tab) t))
+                     (when tab-group
+                       (tab-bar-change-tab-group tab-group)))))))))
+
+        ;; Do the real work: restore the tab.
+        ;; 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)
+                          (let ((orig-name (car bm))
+                                (record (cadr bm))
+                                (restore-failed))
+
+                            (set-buffer dummy)
+                            ;; Test if bookmark-handler did not complain...
+                            (setq restore-failed
+                                  (condition-case err
+                                      (progn
+                                        (funcall (or (bookmark-get-handler 
record)
+                                                     'bookmark-default-handler)
+                                                 record)
+                                        (run-hooks 'bookmark-after-jump-hook)
+                                        nil)
+                                    (error
+                                     (message "Bufferlo bookmark: Could not 
restore %s (error %s)"
+                                              orig-name err)
+                                     t)))
+                            ;; ...then test that the buffer actually changed.
+                            (setq restore-failed (or restore-failed
+                                                     (eq (current-buffer) 
dummy)))
+
+                            (if restore-failed
+                                (progn
+                                  (bufferlo--bookmark-insert-placeholer 
orig-name)
+                                  (push orig-name skipped-buffer-names))
+                              (push orig-name restored-buffer-names))
+
+                            (unless (eq (current-buffer) dummy)
+                              ;; Return a list of (cons <string> <buffer>).
+                              ;; The buffer may be renamed later (by uniquify).
+                              ;; Using the buffer name directly would not
+                              ;; account for this!
+                              (cons orig-name (current-buffer))))))
+
+               (renamed (mapcar restore (alist-get 'buffer-bookmarks 
bookmark)))
+               (replace-renamed (lambda (b)
+                                  (if-let* ((replace
+                                             (assoc b renamed)))
+                                      (cdr replace) b)))
+               (bm-buffer-list (mapcar replace-renamed
+                                       (alist-get 'buffer-list bookmark)))
+               ;; Some of the items may already be buffers after renaming.
+               ;; Others are still buffer names (strings).  These items had no
+               ;; bookmark associated with them.
+               (bm-buffer-list (seq-filter #'get-buffer bm-buffer-list))
+               (bm-buffer-list (mapcar #'get-buffer bm-buffer-list)))
+
+          (kill-buffer dummy)
+
+          ;; Note that we replace buffer names with buffers in ws.
+          ;; `window-state-put' accepts this.
+          (bufferlo--ws-replace-buffer-names ws renamed)
+
+          ;; We do the following to work around two problems with
+          ;; bookmark--jump-via.  In older versions, when called
+          ;; interactively and not through bufferlo commands, it calls a
+          ;; display-function which could interfere with
+          ;; window-state-put.
+          ;;
+          ;; In Emacs 31, bookmark--jump-via wraps the bookmark-handler
+          ;; call with save-window-excursion which restores the
+          ;; window-configuration after we've just restored the one from
+          ;; the bookmark.  We let bookmark--jump-via be evil and defer
+          ;; window-state-put until after bookmark--jump-via is done.
+          (let ((bm-after-jump-hook-sym (gensym "bufferlo-bm-after-jump-"))
+                (frame (selected-frame))
+                (tab-number (1+ (tab-bar--current-tab-index)))
+                (buffer (current-buffer)))
+            (fset bm-after-jump-hook-sym
+                  (lambda ()
+                    (remove-hook 'bookmark-after-jump-hook 
bm-after-jump-hook-sym)
+                    (with-selected-frame frame ; defensive
+                      (let ((tab-bar-tab-post-select-functions))
+                        (tab-bar-select-tab tab-number) ; defensive
+                       (window-state-put ws (frame-root-window) 'safe)
+                        (set-frame-parameter nil 'buffer-list bm-buffer-list)
+                        (set-frame-parameter nil 'buried-buffer-list nil)
+                        (setf (alist-get 'bufferlo-bookmark-tab-name
+                                         (cdr (bufferlo--current-tab)))
+                              (unless disconnect-tbm-p bookmark-name))
+                        (sit-for 0)
+                        (run-hook-with-args
+                         'bufferlo-bookmark-tab-handler-functions
+                         bookmark-name
+                         (unless disconnect-tbm-p bookmark-name)
+                         (bufferlo--current-tab)
+                         restored-buffer-names
+                         skipped-buffer-names)
+                        buffer))))
+            (add-hook 'bookmark-after-jump-hook bm-after-jump-hook-sym -99)
+            (when not-jump
+              (run-hooks 'bookmark-after-jump-hook))))
+
+        ;; Log message
+        (unless (or no-message bufferlo--bookmark-handler-no-message)
+          (message "Restored bufferlo tab bookmark%s%s%s%s"
+                   (if orig-bookmark-name (format ": %s" orig-bookmark-name) 
"")
+                   (or msg "")
+                   (if restored-buffer-names
+                       (format " (%s)"
+                               (mapconcat #'identity restored-buffer-names ", 
")) "")
+                   (if skipped-buffer-names
+                       (format " (skipped: %s)"
+                               (mapconcat #'identity skipped-buffer-names ", 
")) "")))
+        ;; Explicitly return success; abort returns non-nil
+        nil))))
 
 ;; We use a short name here as bookmark-bmenu-list hard codes width of 8 chars
 (put #'bufferlo--bookmark-tab-handler 'bookmark-handler-type "B-Tab")
@@ -2919,140 +2917,141 @@ Returns nil on success, non-nil on abort."
                              (not pop-up-frames)))
            (duplicate-policy)
            (load-policy)
-           (msg)
-           (msg-append (lambda (s) (setq msg (concat msg "; " s)))))
-
-      ;; Bookmark already loaded in another frame?
-      (when abm
-        (setq duplicate-policy (bufferlo--bookmark-get-duplicate-policy
-                                bookmark-name "frame"
-                                bufferlo-bookmark-frame-duplicate-policy 
'load))
-        (pcase duplicate-policy
-          ('ignore
-           (throw :abort t))
-          ('raise
-           (bufferlo--bookmark-raise abm)
-           (throw :abort t))))
-
-      ;; If new frame, no conflict; go with the bookmark's name.
-      (if new-frame-p
-          (setq fbm bookmark-name)
-        ;; No currently active bookmark in the frame?
-        (if (not fbm)
-            ;; Set active bookmark
+           (msg))
+      (cl-labels
+          ((msg-append (s) (setq msg (concat msg "; " s))))
+
+        ;; Bookmark already loaded in another frame?
+        (when abm
+          (setq duplicate-policy (bufferlo--bookmark-get-duplicate-policy
+                                  bookmark-name "frame"
+                                  bufferlo-bookmark-frame-duplicate-policy 
'load))
+          (pcase duplicate-policy
+            ('ignore
+             (throw :abort t))
+            ('raise
+             (bufferlo--bookmark-raise abm)
+             (throw :abort t))))
+
+        ;; If new frame, no conflict; go with the bookmark's name.
+        (if new-frame-p
             (setq fbm bookmark-name)
-          ;; Handle existing bookmark according to the load policy
-          (setq load-policy (bufferlo--bookmark-frame-get-load-policy))
-          (pcase load-policy
-            ('disallow-replace
-             ;; Allow reloads of existing bookmark
-             (when (not (equal fbm bookmark-name))
-               (unless no-message
-                 (message "Frame already bookmarked as %s; not loaded." fbm))
-               (throw :abort t)))
-            ('replace-frame-retain-current-bookmark
-             (funcall msg-append (format "retained existing bookmark %s." 
fbm)))
-            ('replace-frame-adopt-loaded-bookmark
-             (funcall msg-append (format "adopted loaded bookmark %s." fbm))
-             (setq fbm bookmark-name))
-            ('merge
-             (funcall msg-append (format "merged tabs from bookmark %s."
-                                         bookmark-name))))))
-
-      ;; Do the real work with the target frame selected
-      ;; (current or newly created)
-      ;; NOTE: No :abort throws after this point
-      (bufferlo--with-temp-buffer
-       (let ((frame (if new-frame-p
-                        (bufferlo--make-frame
-                         (eq bufferlo-bookmark-frame-load-make-frame
-                             'restore-geometry))
-                      (selected-frame))))
-         (with-selected-frame frame
-           ;; Restore geometry
-           (when (and new-frame-p
-                      (display-graphic-p)
-                      (eq bufferlo-bookmark-frame-load-make-frame
-                          'restore-geometry))
-             (when-let* ((fg (alist-get 'bufferlo--frame-geometry bookmark)))
-               (funcall bufferlo-set-frame-geometry-function fg)))
-
-           ;; Clear existing tabs unless merging
-           (unless (eq load-policy 'merge)
-             (if (>= emacs-major-version 28)
-                 (tab-bar-tabs-set nil)
-               (set-frame-parameter nil 'tabs nil)))
-
-           ;; Load tabs
-           (let ((first (if (eq load-policy 'merge) nil t))
-                 (tab-bar-new-tab-choice t))
-             (mapc
-              (lambda (tbm)
-                (let ((orig-buffer (current-buffer)))
-                  (unless first
-                    (tab-bar-new-tab-to))
-                  ;; NOTE: This is defensive code.  There should be no aborts
-                  ;; for an embedded-tab and bufferlo--bookmark-tab-handler
-                  ;; disallows raise for an embedded-tab to avoid selected
-                  ;; frame/tab state issues..  Embedded tabs in frames carry
-                  ;; no bookmarks of their own, so no duplicates are possible
-                  ;; and other user prompts are bypassed.
-                  ;;
-                  ;; Handler abort is non-nil.
-                  (if (bufferlo--bookmark-tab-handler tbm 'not-jump
-                                                      'no-message 
'embedded-tab)
-                      (if first
-                          (let ((switch-to-buffer-obey-display-actions))
-                            (switch-to-buffer orig-buffer 'no-record
-                                              'force-same-window))
-                        (let (tab-bar-tab-prevent-close-functions)
-                          (tab-bar-close-tab)))
-                    (when-let* ((tab-name (alist-get 'tab-name tbm)))
-                      (tab-bar-rename-tab tab-name)))
-                  (setq first nil)))
-              (alist-get 'tabs bookmark)))
-           ;; NOTE: We might not find a 'current tab if the tab handler aborts
-           ;; (should never happen).
-           (tab-bar-select-tab (alist-get 'current bookmark))
-
-           ;; Handle duplicate frame bookmark
-           (when abm
-             (pcase duplicate-policy
-               ;; Do nothing for 'allow or nil
-               ('clear
-                (setq fbm nil))
-               ('clear-warn
-                (setq fbm nil)
-                (funcall msg-append "cleared frame bookmark"))))
-
-           (set-frame-parameter nil 'bufferlo-bookmark-frame-name fbm))
-
-         ;; Select and raise the restored frame outside the context
-         ;; of with-selected-frame
-         (select-frame-set-input-focus frame)
-
-         (run-hook-with-args
-          'bufferlo-bookmark-frame-handler-functions
-          bookmark-name
-          fbm
-          new-frame-p
-          frame)))
-
-      (unless (or new-frame-p pop-up-frames)
-        ;; Switch to the to-be-selected buffer in the current frame.
-        ;; This is a workaround for bookmark-jump if called with display-func
-        ;; set to something like pop-to-buffer-same-window (the default).
-        ;; Without this, the previously selected buffer will leak into the
-        ;; loaded frame bookmark.
-        (switch-to-buffer (window-buffer (frame-selected-window nil))))
-
-      ;; Log message
-      (unless (or no-message bufferlo--bookmark-handler-no-message)
-        (message "Restored bufferlo frame bookmark%s%s"
-                 (if bookmark-name (format ": %s" bookmark-name) "")
-                 (or msg "")))
-      ;; Explicitly return success; abort returns non-nil
-      nil)))
+          ;; No currently active bookmark in the frame?
+          (if (not fbm)
+              ;; Set active bookmark
+              (setq fbm bookmark-name)
+            ;; Handle existing bookmark according to the load policy
+            (setq load-policy (bufferlo--bookmark-frame-get-load-policy))
+            (pcase load-policy
+              ('disallow-replace
+               ;; Allow reloads of existing bookmark
+               (when (not (equal fbm bookmark-name))
+                 (unless no-message
+                   (message "Frame already bookmarked as %s; not loaded." fbm))
+                 (throw :abort t)))
+              ('replace-frame-retain-current-bookmark
+               (msg-append (format "retained existing bookmark %s." fbm)))
+              ('replace-frame-adopt-loaded-bookmark
+               (msg-append (format "adopted loaded bookmark %s." fbm))
+               (setq fbm bookmark-name))
+              ('merge
+               (msg-append (format "merged tabs from bookmark %s."
+                                   bookmark-name))))))
+
+        ;; Do the real work with the target frame selected
+        ;; (current or newly created)
+        ;; NOTE: No :abort throws after this point
+        (bufferlo--with-temp-buffer
+         (let ((frame (if new-frame-p
+                          (bufferlo--make-frame
+                           (eq bufferlo-bookmark-frame-load-make-frame
+                               'restore-geometry))
+                        (selected-frame))))
+           (with-selected-frame frame
+             ;; Restore geometry
+             (when (and new-frame-p
+                        (display-graphic-p)
+                        (eq bufferlo-bookmark-frame-load-make-frame
+                            'restore-geometry))
+               (when-let* ((fg (alist-get 'bufferlo--frame-geometry bookmark)))
+                 (funcall bufferlo-set-frame-geometry-function fg)))
+
+             ;; Clear existing tabs unless merging
+             (unless (eq load-policy 'merge)
+               (if (>= emacs-major-version 28)
+                   (tab-bar-tabs-set nil)
+                 (set-frame-parameter nil 'tabs nil)))
+
+             ;; Load tabs
+             (let ((first (if (eq load-policy 'merge) nil t))
+                   (tab-bar-new-tab-choice t))
+               (mapc
+                (lambda (tbm)
+                  (let ((orig-buffer (current-buffer)))
+                    (unless first
+                      (tab-bar-new-tab-to))
+                    ;; NOTE: This is defensive code.  There should be no aborts
+                    ;; for an embedded-tab and bufferlo--bookmark-tab-handler
+                    ;; disallows raise for an embedded-tab to avoid selected
+                    ;; frame/tab state issues..  Embedded tabs in frames carry
+                    ;; no bookmarks of their own, so no duplicates are possible
+                    ;; and other user prompts are bypassed.
+                    ;;
+                    ;; Handler abort is non-nil.
+                    (if (bufferlo--bookmark-tab-handler tbm 'not-jump
+                                                        'no-message 
'embedded-tab)
+                        (if first
+                            (let ((switch-to-buffer-obey-display-actions))
+                              (switch-to-buffer orig-buffer 'no-record
+                                                'force-same-window))
+                          (let (tab-bar-tab-prevent-close-functions)
+                            (tab-bar-close-tab)))
+                      (when-let* ((tab-name (alist-get 'tab-name tbm)))
+                        (tab-bar-rename-tab tab-name)))
+                    (setq first nil)))
+                (alist-get 'tabs bookmark)))
+             ;; NOTE: We might not find a 'current tab if the tab handler 
aborts
+             ;; (should never happen).
+             (tab-bar-select-tab (alist-get 'current bookmark))
+
+             ;; Handle duplicate frame bookmark
+             (when abm
+               (pcase duplicate-policy
+                 ;; Do nothing for 'allow or nil
+                 ('clear
+                  (setq fbm nil))
+                 ('clear-warn
+                  (setq fbm nil)
+                  (msg-append "cleared frame bookmark"))))
+
+             (set-frame-parameter nil 'bufferlo-bookmark-frame-name fbm))
+
+           ;; Select and raise the restored frame outside the context
+           ;; of with-selected-frame
+           (select-frame-set-input-focus frame)
+
+           (run-hook-with-args
+            'bufferlo-bookmark-frame-handler-functions
+            bookmark-name
+            fbm
+            new-frame-p
+            frame)))
+
+        (unless (or new-frame-p pop-up-frames)
+          ;; Switch to the to-be-selected buffer in the current frame.
+          ;; This is a workaround for bookmark-jump if called with display-func
+          ;; set to something like pop-to-buffer-same-window (the default).
+          ;; Without this, the previously selected buffer will leak into the
+          ;; loaded frame bookmark.
+          (switch-to-buffer (window-buffer (frame-selected-window nil))))
+
+        ;; Log message
+        (unless (or no-message bufferlo--bookmark-handler-no-message)
+          (message "Restored bufferlo frame bookmark%s%s"
+                   (if bookmark-name (format ": %s" bookmark-name) "")
+                   (or msg "")))
+        ;; Explicitly return success; abort returns non-nil
+        nil))))
 
 ;; We use a short name here as bookmark-bmenu-list hard codes width of 8 chars
 (put #'bufferlo--bookmark-frame-handler 'bookmark-handler-type "B-Frame")
@@ -3677,59 +3676,71 @@ This closes their associated bookmarks and kills their 
buffers."
          (comps (bufferlo--bookmark-completing-read-multiple
                  "Select sets to enumerate: "
                  candidates)))
-    (let* ((abms (bufferlo--active-bookmarks))
-           (intangible-text (lambda (&rest text)
-                              (let* ((text (mapconcat #'identity text))
-                                     (len (length text)))
-                                (put-text-property 0 len 'cursor-intangible t 
text)
-                                (put-text-property 0 len 'inhibit-isearch t 
text)
-                                text))))
-      (with-current-buffer (get-buffer-create bufferlo--set-list-buffer-name)
-        (let ((buffer-undo-list t))
-          (read-only-mode -1)
-          (erase-buffer))
-        (let ((start-point))
-          (insert (funcall intangible-text
-                           "----- Bufferlo Bookmarks Sets -----"
-                           "\n"
-                           "(RET or mouse-1 to raise a bookmark, q to quit)"
-                           "\n"
-                           "\n"))
-          (dolist (set-name (sort comps #'string<))
-            (insert (funcall intangible-text
-                             (format-message "Set `%s':\n" set-name)))
-            (unless start-point (setq start-point (1+ (point))))
-            (dolist (bname (sort
-                            (alist-get 'bufferlo-bookmark-names
-                                       (assoc set-name bufferlo--active-sets))
-                            #'string<))
-              (when-let* ((abm (cadr (assoc bname abms))))
-                (let* ((type (alist-get 'type abm))
-                       (frame (alist-get 'frame abm))
-                       (fname (or (frame-parameter frame 'explicit-name)
-                                  (frame-parameter frame 'name)))
-                       (tab-number (alist-get 'tab-number abm))
-                       (text (format "  %-20s %-8s %-25s %s"
-                                     (truncate-string-to-width bname 20 nil 
nil t)
-                                     (alist-get type 
bufferlo--bookmark-type-names)
-                                     (truncate-string-to-width fname 25 nil 
nil t)
-                                     (if tab-number
-                                         (format "tab:%d" tab-number)
-                                       "")))
-                       (len (length text)))
-                  (put-text-property 0 len 'bookmark-name bname text)
-                  (put-text-property 0 len 'help-echo (format "RET or mouse-1: 
Raise bookmark %s" bname) text)
-                  (put-text-property 0 len 'kbd-help nil text) ; nil to use 
help-echo text
-                  (put-text-property 0 len 'mouse-face 'highlight text)
-                  (put-text-property 0 len 'cursor-face 'highlight text)
-                  (insert text)
-                  (insert (funcall intangible-text "\n")))))
-            (insert "\n"))
-          (insert (funcall intangible-text
-                           "----- END -----"))
-          (bufferlo--set-list-mode)
-          (goto-char start-point)
-          (pop-to-buffer (current-buffer) nil 'norecord))))))
+    (let ((abms (bufferlo--active-bookmarks)))
+      (cl-labels
+          ((intangible-text (&rest text)
+             (let* ((text (mapconcat #'identity text))
+                    (len (length text)))
+               (add-text-properties 0 len
+                                    (list
+                                     'field t
+                                     'rear-nonsticky t
+                                     'front-sticky t
+                                     'intangible t
+                                     'cursor-intangible t
+                                     'inhibit-isearch t)
+                                    text)
+               text)))
+        (with-current-buffer (get-buffer-create bufferlo--set-list-buffer-name)
+          (let ((buffer-undo-list t))
+            (read-only-mode -1)
+            (erase-buffer))
+          (let ((start-point))
+            (insert (intangible-text
+                     "----- Bufferlo Bookmarks Sets -----"
+                     "\n"
+                     "(RET or mouse-1 to raise a bookmark, q to quit)"
+                     "\n"
+                     "\n"))
+            (dolist (set-name (sort comps #'string<))
+              (insert (intangible-text
+                       (format-message "Set `%s':\n" set-name)))
+              (unless start-point (setq start-point (1+ (point))))
+              (dolist (bname (sort
+                              (alist-get 'bufferlo-bookmark-names
+                                         (assoc set-name 
bufferlo--active-sets))
+                              #'string<))
+                (when-let* ((abm (cadr (assoc bname abms))))
+                  (let* ((type (alist-get 'type abm))
+                         (frame (alist-get 'frame abm))
+                         (fname (or (frame-parameter frame 'explicit-name)
+                                    (frame-parameter frame 'name)))
+                         (tab-number (alist-get 'tab-number abm))
+                         (text (format "  %-20s %-8s %-25s %s"
+                                       (truncate-string-to-width bname 20 nil 
nil t)
+                                       (alist-get type 
bufferlo--bookmark-type-names)
+                                       (truncate-string-to-width fname 25 nil 
nil t)
+                                       (if tab-number
+                                           (format "tab:%d" tab-number)
+                                         "")))
+                         (len (length text)))
+                    (add-text-properties 0 len
+                                         (list
+                                          'bookmark-name bname
+                                          'help-echo (format "RET or mouse-1: 
Raise bookmark %s" bname)
+                                          'kbd-help nil ; nil to use help-echo 
text
+                                          'mouse-face 'highlight
+                                          'cursor-face 'region)
+                                         text)
+                    (insert text)
+                    (insert (intangible-text "\n")))))
+              (insert (intangible-text "\n")))
+            (insert (intangible-text
+                     "----- END -----"
+                     "\n"))
+            (bufferlo--set-list-mode)
+            (goto-char start-point)
+            (pop-to-buffer (current-buffer) nil 'norecord)))))))
 
 
 
@@ -3791,44 +3802,45 @@ is not recommended."
           (alist-get 'bufferlo-bookmark-tab-name (bufferlo--current-tab)))))
   (bufferlo--warn)
   (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
-                  name "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"))
-            ('ignore
-             (throw :abort t))
-            ('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)
-             (funcall msg-append "cleared frame bookmark"))
-            (_ ))))
+    (let ((abm (assoc name (bufferlo--active-bookmarks)))
+          (tbm (alist-get 'bufferlo-bookmark-tab-name
+                          (tab-bar--current-tab-find)))
+          (msg))
+      (cl-labels
+          ((msg-append (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
+                    name "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)
+               (msg-append "cleared duplicate active tab bookmark"))
+              ('ignore
+               (throw :abort t))
+              ('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)
+               (msg-append "cleared frame bookmark"))
+              (_ ))))
 
-      ;; Finally, save the bookmark
-      (bufferlo--bookmark-tab-save name no-overwrite no-message msg))))
+        ;; Finally, save the bookmark
+        (bufferlo--bookmark-tab-save name no-overwrite no-message msg)))))
 
 (defun bufferlo-bookmark-tab-load (name)
   "Load a tab bookmark.
@@ -3936,46 +3948,47 @@ but is not recommended."
           (frame-parameter nil 'bufferlo-bookmark-frame-name))))
   (bufferlo--warn)
   (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 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
-                  name "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"))
-            ('ignore
-             (throw :abort t))
-            ('raise
-             (bufferlo--bookmark-raise abm)
-             (throw :abort t))))
+    (let ((abm (assoc name (bufferlo--active-bookmarks)))
+          (fbm (frame-parameter nil 'bufferlo-bookmark-frame-name))
+          (msg))
+      (cl-labels
+          ((msg-append (s) (setq msg (concat msg "; " s))))
+
+        ;; Only check policies when 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
+                    name "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)
+               (msg-append "cleared duplicate active frame bookmark"))
+              ('ignore
+               (throw :abort t))
+              ('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))))
+               (msg-append "cleared tab bookmarks"))
+              ('allow))))
 
-        ;; 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))))
-             (funcall msg-append "cleared tab bookmarks"))
-            ('allow))))
-
-      ;; Finally, save the bookmark
-      (bufferlo--bookmark-frame-save name no-overwrite no-message msg))))
+        ;; Finally, save the bookmark
+        (bufferlo--bookmark-frame-save name no-overwrite no-message msg)))))
 
 (defun bufferlo-bookmark-frame-load (name)
   "Load a frame bookmark.

Reply via email to