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

    Streamline set loading and saving
---
 bufferlo.el | 429 ++++++++++++++++++++++++++++++------------------------------
 1 file changed, 214 insertions(+), 215 deletions(-)

diff --git a/bufferlo.el b/bufferlo.el
index 9655bacf48..ef2468c5ac 100644
--- a/bufferlo.el
+++ b/bufferlo.el
@@ -2093,73 +2093,58 @@ Ask the user if DEFAULT-POLICY is set to \\='prompt.
 MODE can be one of \\='load \\='save \\='undelete, depending on the
 invoking action.
 This functions throws :abort when the user quits."
-  (cond
-   (bufferlo--bookmark-set-loading
-    (if (not (eq default-policy 'prompt))
-        ;; transform default raise policy to clear
-        (if (eq default-policy 'raise)
-            'clear
-          default-policy)
-      (pcase (let ((read-answer-short t))
-               (with-local-quit
-                 (read-answer
-                  (format "%s bookmark name \"%s\" already active: Allow, %s "
-                          (capitalize thing)
-                          bookmark-name
-                          (pcase mode
-                            ('save
-                             "Clear other bookmark")
-                            ('load
-                             "Clear bookmark after loading")
-                            ('undelete ; invalid under 
bufferlo--bookmark-set-loading, but here anyway
-                             "Clear bookmark after undeleting/undoing close")))
-                  `(("allow" ?a "Allow duplicate")
-                    ("clear" ?c
-                     ,(pcase mode
+  (if (not (eq default-policy 'prompt))
+      ;; Return the default policy
+      (if (and bufferlo--bookmark-set-loading
+               (eq default-policy 'raise))
+          'clear ; change the default policy from 'raise to 'clear on set 
loading
+        default-policy)
+
+    ;; Prompt for a policy
+    (let* ((mode-text (pcase mode
                         ('save
-                         (format "Clear the other %s's bookmark association" 
thing))
+                         "Clear other bookmark")
                         ('load
-                         (format "Clear this %s's bookmark association after 
loading" thing))
-                        ('undelete
-                         (format "Clear this %s's bookmark association after 
undeleting/undoing" thing)))
-                     ("help" ?h "Help")
-                     ("quit" ?q "Quit to clear"))))))
-        ("allow" 'allow)
-        ("clear" 'clear)
-        (_ 'clear))))
-   (t
-    (if (not (eq default-policy 'prompt))
-        default-policy
+                         "Clear bookmark after loading")
+                        ('undelete ; invalid in bufferlo--bookmark-set-loading
+                         "Clear bookmark after undeleting/undoing")))
+           (question (concat (format "%s bookmark name \"%s\" already active: "
+                                     (capitalize thing)
+                                     bookmark-name)
+                             (format "Allow, %s, Raise existing "
+                                     mode-text)))
+           (a-allow `("allow" ?a "Allow duplicate"))
+           (a-clear `("clear" ?c
+                      ,(pcase mode
+                         ('save
+                          (format "Clear the other %s's bookmark association"
+                                  thing))
+                         ('load
+                          (format "Clear this %s's bookmark association after 
loading"
+                                  thing))
+                         ('undelete
+                          (format "Clear this %s's bookmark association after 
undeleting/undoing"
+                                  thing)))))
+           (a-raise `("raise" ?r
+                      ,(format "Raise the %s with the active bookmark and quit"
+                               thing)))
+           (a-help `("help" ?h "Help"))
+           (a-quit `("quit" ?q ,(format "Quit to %s"
+                                        (if bufferlo--bookmark-set-loading
+                                            "clear"
+                                          "abort"))))
+           (answers (if bufferlo--bookmark-set-loading
+                        (list a-allow a-clear a-help a-quit)
+                      (list a-allow a-clear a-raise a-help a-quit))))
       (pcase (let ((read-answer-short t))
                (with-local-quit
-                 (read-answer
-                  (format "%s bookmark name \"%s\" already active: Allow, %s, 
Raise existing "
-                          (capitalize thing)
-                          bookmark-name
-                          (pcase mode
-                            ('save
-                             "Clear other bookmark")
-                            ('load
-                             "Clear bookmark after loading")
-                            ('undelete
-                             "Clear bookmark after undeleting/undoing")))
-                  `(("allow" ?a "Allow duplicate")
-                    ("clear" ?c
-                     ,(pcase mode
-                        ('save
-                         (format "Clear the other %s's bookmark association" 
thing))
-                        ('load
-                         (format "Clear this %s's bookmark association after 
loading" thing))
-                        ('undelete
-                         (format "Clear this %s's bookmark association after 
undeleting/undoing" thing))))
-                    ("raise" ?r
-                     ,(format "Raise the %s with the active bookmark and quit" 
thing))
-                    ("help" ?h "Help")
-                    ("quit" ?q "Quit to abort")))))
+                 (read-answer question answers)))
         ("allow" 'allow)
         ("clear" 'clear)
         ("raise" 'raise)
-        (_ (throw :abort t)))))))
+        (_ (if bufferlo--bookmark-set-loading
+               'clear
+             (throw :abort t)))))))
 
 (defun bufferlo--bookmark-tab-get-replace-policy ()
   "Get the replace policy for tab bookmarks.
@@ -2693,78 +2678,93 @@ The argument BOOKMARK-RECORD is the to-be restored 
bookmark set created via
 `bufferlo--bookmark-set-make'. The optional argument NO-MESSAGE inhibits
 the message after successfully restoring the bookmark."
   (let* ((bookmark-name (bookmark-name-from-full-record bookmark-record))
-         (bufferlo-bookmark-names (bookmark-prop-get bookmark-record 
'bufferlo-bookmark-names))
-         (abm-names (mapcar #'car (bufferlo--active-bookmarks)))
-         (active-bookmark-names (seq-intersection bufferlo-bookmark-names 
abm-names))
-         (bufferlo--bookmark-set-loading t))
-    (if (assoc bookmark-name bufferlo--active-sets)
-        (message "Bufferlo set \"%s\" is already active" bookmark-name)
-      (let ((tabsets-str (bookmark-prop-get bookmark-record 'bufferlo-tabsets))
-            (tabsets))
-        (if (not (readablep tabsets-str))
-            (message "Bufferlo bookmark set %s: unreadable tabsets" 
bookmark-name)
-          (setq tabsets (car (read-from-string tabsets-str)))
-          (when tabsets ; could be readable and nil
-            (let ((first-tab-frame t))
-              (bufferlo--with-temp-buffer
-               (dolist (tab-group tabsets)
-                 (when (or (not first-tab-frame)
-                           (and first-tab-frame (not 
bufferlo-set-restore-tabs-reuse-init-frame)))
-                   (select-frame
-                    (bufferlo--make-frame
-                     (eq bufferlo-set-restore-tabs-reuse-init-frame 
'reuse-reset-geometry))))
-                 (when-let* ((fg (alist-get 'bufferlo--frame-geometry 
tab-group)))
-                   (when (and
-                          (display-graphic-p)
-                          (memq bufferlo-set-restore-geometry-policy '(all 
tab-frames))
-                          (or (not first-tab-frame)
-                              (and first-tab-frame (eq 
bufferlo-set-restore-tabs-reuse-init-frame 'reuse-reset-geometry))))
-                     (funcall bufferlo-set-frame-geometry-function fg)))
-                 (when-let* ((tbm-names (alist-get 'bufferlo--tbms tab-group)))
-                   (let ((bufferlo-bookmark-tab-replace-policy 'replace) ; we 
handle making tabs in this loop
-                         (tab-bar-new-tab-choice t)
-                         (first-tab (or
-                                     (not first-tab-frame)
-                                     (and first-tab-frame (not 
bufferlo-set-restore-tabs-reuse-init-frame)))))
-                     (dolist (tbm-name tbm-names)
-                       (unless first-tab
-                         (tab-bar-new-tab-to))
-                       (bufferlo--bookmark-jump tbm-name)
-                       (setq first-tab nil))))
-                 (setq first-tab-frame nil)))
-              (raise-frame)))))
-      (let ((frameset-str (bookmark-prop-get bookmark-record 
'bufferlo-frameset))
-            (frameset))
-        (if (not (readablep frameset-str))
-            (message "Bufferlo bookmark set %s: unreadable frameset" 
bookmark-name)
-          (setq frameset (car (read-from-string frameset-str)))
-          (if (and frameset (not (frameset-valid-p frameset)))
-              (message "Bufferlo bookmark set %s: invalid frameset" 
bookmark-name)
-            (when frameset ; could be readable and nil
-              (funcall bufferlo-frameset-restore-function frameset)
-              (dolist (frame (frame-list))
-                (with-selected-frame frame
-                  (when (frame-parameter nil 'bufferlo--frame-to-restore)
-                    (when-let* ((fbm-name (frame-parameter nil 
'bufferlo--bookmark-frame-name)))
-                      (let ((bufferlo-bookmark-frame-load-make-frame nil)
-                            (bufferlo-bookmark-frame-load-policy 
'replace-frame-adopt-loaded-bookmark)
-                            (bufferlo--bookmark-handler-no-message t))
-                        (bufferlo--bookmark-jump fbm-name))
-                      (when (and
-                             (display-graphic-p frame)
-                             (memq bufferlo-set-restore-geometry-policy '(all 
frames)))
-                        (when-let* ((fg (frame-parameter nil 
'bufferlo--frame-geometry)))
-                          (funcall bufferlo-set-frame-geometry-function fg)))
-                      (set-frame-parameter nil 'bufferlo--frame-to-restore 
nil))
-                    (raise-frame))))))
-          (push
-           `(,bookmark-name (bufferlo-bookmark-names . 
,bufferlo-bookmark-names))
-           bufferlo--active-sets)
-          (unless (or no-message bufferlo--bookmark-handler-no-message)
-            (message "Restored bufferlo bookmark set %s %s"
-                     bookmark-name bufferlo-bookmark-names)))))))
-
-(put #'bufferlo--bookmark-set-handler 'bookmark-handler-type "B-Set") ; short 
name here as bookmark-bmenu-list hard codes width of 8 chars
+         (bufferlo-bookmark-names (bookmark-prop-get bookmark-record
+                                                     'bufferlo-bookmark-names))
+         (bufferlo--bookmark-set-loading t)
+         (tabsets-str (bookmark-prop-get bookmark-record 'bufferlo-tabsets))
+         (frameset-str (bookmark-prop-get bookmark-record 'bufferlo-frameset)))
+
+    (when (assoc bookmark-name bufferlo--active-sets)
+      (user-error "Bufferlo set \"%s\" is already active" bookmark-name))
+
+    (unless (readablep tabsets-str)
+      (error "Bufferlo bookmark set %s: unreadable tabsets"
+             bookmark-name))
+
+    (unless (readablep frameset-str)
+      (error "Bufferlo bookmark set %s: unreadable frameset"
+             bookmark-name))
+
+    ;; Restore tabsets (tabsets can be nil despite readablep)
+    (when-let ((tabsets (car (read-from-string tabsets-str)))
+               (first-tab-frame t))
+      (bufferlo--with-temp-buffer
+       (dolist (tab-group tabsets)
+         (when (or (not first-tab-frame)
+                   (and first-tab-frame
+                        (not bufferlo-set-restore-tabs-reuse-init-frame)))
+           (select-frame (bufferlo--make-frame
+                          (eq bufferlo-set-restore-tabs-reuse-init-frame
+                              'reuse-reset-geometry))))
+         (when-let* ((fg (alist-get 'bufferlo--frame-geometry tab-group)))
+           (when (and
+                  (display-graphic-p)
+                  (memq bufferlo-set-restore-geometry-policy '(all tab-frames))
+                  (or (not first-tab-frame)
+                      (and first-tab-frame
+                           (eq bufferlo-set-restore-tabs-reuse-init-frame
+                               'reuse-reset-geometry))))
+             (funcall bufferlo-set-frame-geometry-function fg)))
+         (when-let* ((tbm-names (alist-get 'bufferlo--tbms tab-group)))
+           (let ((bufferlo-bookmark-tab-replace-policy 'replace)
+                 (tab-bar-new-tab-choice t)
+                 (first-tab
+                  (or (not first-tab-frame)
+                      (and first-tab-frame
+                           (not bufferlo-set-restore-tabs-reuse-init-frame)))))
+             (dolist (tbm-name tbm-names)
+               (unless first-tab
+                 (tab-bar-new-tab-to))
+               (bufferlo--bookmark-jump tbm-name)
+               (setq first-tab nil))))
+         (setq first-tab-frame nil)))
+      (raise-frame))
+
+    ;; Restore framesets (framesets can be nil despite readablep)
+    (when-let ((frameset (car (read-from-string frameset-str))))
+      (unless (frameset-valid-p frameset)
+        (error "Bufferlo bookmark set %s: invalid frameset"
+               bookmark-name))
+      (funcall bufferlo-frameset-restore-function frameset)
+      (dolist (frame (frame-list))
+        (with-selected-frame frame
+          (when (frame-parameter nil 'bufferlo--frame-to-restore)
+            (when-let* ((fbm-name (frame-parameter
+                                   nil 'bufferlo--bookmark-frame-name)))
+              (let ((bufferlo-bookmark-frame-load-make-frame nil)
+                    (bufferlo-bookmark-frame-load-policy
+                     'replace-frame-adopt-loaded-bookmark)
+                    (bufferlo--bookmark-handler-no-message t))
+                (bufferlo--bookmark-jump fbm-name))
+              (when (and
+                     (display-graphic-p frame)
+                     (memq bufferlo-set-restore-geometry-policy
+                           '(all frames)))
+                (when-let* ((fg (frame-parameter nil 
'bufferlo--frame-geometry)))
+                  (funcall bufferlo-set-frame-geometry-function fg)))
+              (set-frame-parameter nil 'bufferlo--frame-to-restore nil))
+            (raise-frame)))))
+
+    ;; Add the set to the active list
+    (push `(,bookmark-name (bufferlo-bookmark-names . 
,bufferlo-bookmark-names))
+          bufferlo--active-sets)
+
+    (unless (or no-message bufferlo--bookmark-handler-no-message)
+      (message "Restored bufferlo bookmark set %s %s"
+               bookmark-name bufferlo-bookmark-names))))
+
+;; We use a short name here as bookmark-bmenu-list hard codes width of 8 chars
+(put #'bufferlo--bookmark-set-handler 'bookmark-handler-type "B-Set")
 
 (defun bufferlo--set-save (bookmark-name active-bookmark-names 
active-bookmarks &optional no-overwrite)
   "Save a bufferlo bookmark set for the specified active bookmarks.
@@ -2794,62 +2794,67 @@ message."
          (fbms (seq-filter
                 (lambda (x) (eq (alist-get 'type (cadr x)) 'fbm))
                 abms))
-         (fbm-frames (mapcar (lambda (x) (alist-get 'frame (cadr x))) fbms)))
-    (if (= (length abms) 0)
-        (message "Specify at least one active bufferlo bookmark")
-      (let ((tabsets)
-            (frameset))
-        (dolist (group tbm-frame-groups)
-          (let ((tbm-frame (car group))
-                (tbm-names (mapcar #'car (cdr group))))
-            (push `((bufferlo--frame-geometry
-                     . ,(funcall bufferlo-frame-geometry-function tbm-frame))
-                    (bufferlo--tbms . ,tbm-names))
-                  tabsets)))
-        (when fbm-frames
-          ;; Set a flag we can use to identify restored frames (this
-          ;; is removed in the handler during frame restoration). Save
-          ;; frame geometries for more accurate restoration than
-          ;; frameset-restore provides.
-          ;;
-          ;; Squirrel away 'bufferlo-bookmark-frame-name which we ask
-          ;; frameset-save to filter out to avoid restored frames
-          ;; being considered bookmarked as they need duplicate
-          ;; detection.
-          (dolist (frame fbm-frames)
-            (set-frame-parameter frame 'bufferlo--frame-to-restore t)
-            (set-frame-parameter frame 'bufferlo--frame-geometry
-                                 (funcall bufferlo-frame-geometry-function
-                                          frame))
-            (set-frame-parameter frame 'bufferlo--bookmark-frame-name
-                                 (frame-parameter frame
-                                                  
'bufferlo-bookmark-frame-name)))
-          ;; frameset-save squirrels away width/height text-pixels iff
-          ;; fullscreen is not nil and frame-resize-pixelwise is t.
-          (let ((frame-resize-pixelwise t))
-            (setq frameset
-                  (frameset-save
-                   fbm-frames
-                   :app 'bufferlo
-                   :name bookmark-name
-                   :predicate (lambda (x)
-                                (not (frame-parameter x 'parent-frame)))
-                   :filters
-                   (let ((filtered-alist
-                          (copy-tree frameset-persistent-filter-alist)))
-                     (mapc (lambda (sym)
-                             (setf (alist-get sym filtered-alist) :never))
-                           (seq-union bufferlo--frameset-save-filter
-                                      bufferlo-frameset-save-filter))
-                     filtered-alist)))))
-        (bookmark-store bookmark-name
-                        (bufferlo--bookmark-set-location
-                         (bufferlo--bookmark-set-make
-                          active-bookmark-names tabsets frameset))
-                        no-overwrite)
-        (message "Saved bookmark set \"%s\" containing: %s"
-                 bookmark-name
-                 (mapconcat #'identity active-bookmark-names " "))))))
+         (fbm-frames (mapcar (lambda (x) (alist-get 'frame (cadr x))) fbms))
+         (tabsets)
+         (frameset))
+
+    (when (= (length abms) 0)
+      (user-error "Specify at least one active bufferlo bookmark"))
+
+    (setq tabsets
+          (mapcar (lambda (group)
+                    (let ((tbm-frame (car group))
+                          (tbm-names (mapcar #'car (cdr group))))
+                      `((bufferlo--frame-geometry
+                         . ,(funcall bufferlo-frame-geometry-function 
tbm-frame))
+                        (bufferlo--tbms . ,tbm-names))))
+                  tbm-frame-groups))
+
+    (when fbm-frames
+      ;; Set a flag we can use to identify restored frames (this
+      ;; is removed in the handler during frame restoration). Save
+      ;; frame geometries for more accurate restoration than
+      ;; frameset-restore provides.
+      ;;
+      ;; Squirrel away 'bufferlo-bookmark-frame-name which we ask
+      ;; frameset-save to filter out to avoid restored frames
+      ;; being considered bookmarked as they need duplicate
+      ;; detection.
+      (dolist (frame fbm-frames)
+        (set-frame-parameter frame 'bufferlo--frame-to-restore t)
+        (set-frame-parameter frame 'bufferlo--frame-geometry
+                             (funcall bufferlo-frame-geometry-function
+                                      frame))
+        (set-frame-parameter frame 'bufferlo--bookmark-frame-name
+                             (frame-parameter frame
+                                              'bufferlo-bookmark-frame-name)))
+      ;; frameset-save squirrels away width/height text-pixels iff
+      ;; fullscreen is not nil and frame-resize-pixelwise is t.
+      (let ((frame-resize-pixelwise t))
+        (setq frameset
+              (frameset-save
+               fbm-frames
+               :app 'bufferlo
+               :name bookmark-name
+               :predicate (lambda (x)
+                            (not (frame-parameter x 'parent-frame)))
+               :filters
+               (let ((filtered-alist
+                      (copy-tree frameset-persistent-filter-alist)))
+                 (mapc (lambda (sym)
+                         (setf (alist-get sym filtered-alist) :never))
+                       (seq-union bufferlo--frameset-save-filter
+                                  bufferlo-frameset-save-filter))
+                 filtered-alist)))))
+
+    (bookmark-store bookmark-name
+                    (bufferlo--bookmark-set-location
+                     (bufferlo--bookmark-set-make
+                      active-bookmark-names tabsets frameset))
+                    no-overwrite)
+    (message "Saved bookmark set \"%s\" containing: %s"
+             bookmark-name
+             (mapconcat #'identity active-bookmark-names " "))))
 
 (defun bufferlo-set-save-interactive (bookmark-name &optional no-overwrite)
   "Save a bufferlo bookmark set for the specified active bookmarks.
@@ -2879,24 +2884,27 @@ throwing away the old one."
      `(,bookmark-name (bufferlo-bookmark-names . ,comps))
      bufferlo--active-sets)))
 
+(defun bufferlo--set-get-constituents (bsets abms)
+  "Get the constituents of the given bookmark sets from the list of bookmarks."
+  (let* ((abm-names (mapcar #'car abms))
+         (abm-names (seq-mapcat
+                     (lambda (set-name)
+                       (seq-intersection
+                        (alist-get 'bufferlo-bookmark-names
+                                   (assoc set-name bufferlo--active-sets))
+                        abm-names))
+                     bsets)))
+    (seq-uniq abm-names)))
+
 (defun bufferlo-set-save-current-interactive ()
   "Save active constituents in selected bookmark sets."
   (interactive)
   (let* ((candidates (mapcar #'car bufferlo--active-sets))
          (comps (bufferlo--bookmark-completing-read "Select sets to save: "
-                                                    candidates)))
-    (let* ((abms (bufferlo--active-bookmarks))
-           (abm-names (mapcar #'car abms))
-           (abm-names-to-save))
-      (dolist (set-name comps)
-        (setq abm-names-to-save
-              (append abm-names-to-save
-                      (seq-intersection
-                       (alist-get 'bufferlo-bookmark-names
-                                  (assoc set-name bufferlo--active-sets))
-                       abm-names))))
-      (setq abm-names-to-save (seq-uniq abm-names-to-save))
-      (bufferlo--bookmarks-save abm-names-to-save abms))))
+                                                    candidates))
+         (abms (bufferlo--active-bookmarks))
+         (abm-names-to-save (bufferlo--set-get-constituents comps abms)))
+    (bufferlo--bookmarks-save abm-names-to-save abms)))
 
 (defun bufferlo-set-load-interactive ()
   "Prompt for bufferlo set bookmarks to load."
@@ -2933,20 +2941,11 @@ This closes their associated bookmarks and kills their 
buffers."
   (interactive)
   (let* ((candidates (mapcar #'car bufferlo--active-sets))
          (comps (bufferlo--bookmark-completing-read "Select sets to 
close/kill: "
-                                                    candidates)))
-    (let* ((abms (bufferlo--active-bookmarks))
-           (abm-names (mapcar #'car abms))
-           (abm-names-to-close))
-      (dolist (set-name comps)
-        (setq abm-names-to-close
-              (append abm-names-to-close
-                      (seq-intersection
-                       (alist-get 'bufferlo-bookmark-names
-                                  (assoc set-name bufferlo--active-sets))
-                       abm-names))))
-      (setq abm-names-to-close (seq-uniq abm-names-to-close))
-      (bufferlo--close-active-bookmarks abm-names-to-close abms)
-      (bufferlo--set-clear comps))))
+                                                    candidates))
+         (abms (bufferlo--active-bookmarks))
+         (abm-names-to-close (bufferlo--set-get-constituents comps abms)))
+    (bufferlo--close-active-bookmarks abm-names-to-close abms)
+    (bufferlo--set-clear comps)))
 
 (defvar-keymap bufferlo-set-list-mode-map
   :parent special-mode-map

Reply via email to