branch: externals/bufferlo
commit 5177279f4e50856056ededb65098a896184642ec
Author: shipmints <shipmi...@gmail.com>
Commit: shipmints <shipmi...@gmail.com>

    Eliminated null-error. Better delete-frame. Added 
bufferlo-bookmarks-close-interactive.
    
    Changed null-error prone (/= (aref (buffer-name b) 0) ?\s) to
    string-prefix-p.
    
    Added bufferlo-bookmarks-close-interactive. Still need to decided if
    we offer optional saving with this method.
    
    Fixed a delete-frame buglet and improved handling when the last
    remaining frame is bookmarked.
---
 bufferlo.el | 125 +++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 85 insertions(+), 40 deletions(-)

diff --git a/bufferlo.el b/bufferlo.el
index 855445ba00..aea7e03716 100644
--- a/bufferlo.el
+++ b/bufferlo.el
@@ -915,7 +915,8 @@ argument INTERNAL-TOO is non-nil."
          (buffers (seq-filter
                    (lambda (b)
                      (not (and
-                           (or internal-too (/= (aref (buffer-name b) 0) ?\s))
+                           ;; (or internal-too (/= (aref (buffer-name b) 0) 
?\s)) ; NOTE: this can cause null reference errors
+                           (or internal-too (not (string-prefix-p " " 
(buffer-name b))))
                            (string-match-p exclude (buffer-name b)))))
                    kill-list)))
     (dolist (b buffers)
@@ -933,7 +934,8 @@ Buffers matching `bufferlo-kill-buffers-exclude-filters' 
are never killed."
          (buffers (seq-filter
                    (lambda (b)
                      (not (and
-                           (or internal-too (/= (aref (buffer-name b) 0) ?\s))
+                           ;; (or internal-too (/= (aref (buffer-name b) 0) 
?\s)) ; NOTE: this can cause null reference errors
+                           (or internal-too (not (string-prefix-p " " 
(buffer-name b))))
                            (string-match-p exclude (buffer-name b)))))
                    (bufferlo--get-orphan-buffers))))
     (dolist (b buffers)
@@ -958,7 +960,14 @@ argument INTERNAL-TOO is non-nil."
                   (concat "Kill frame and its buffers? "))))
     (when kill
       (bufferlo-kill-buffers nil frame 'all internal-too)
-      (delete-frame))))
+                       ;; TODO: Emacs 30 frame-deletable-p
+                       ;; account for top-level, non-child frames
+                       (setq frame (or frame (selected-frame)))
+                       (when (= 1 (length (seq-filter
+                                                                               
                        (lambda (x) (null (frame-parameter x 'parent-frame)))
+                                                                               
                        (frame-list))))
+                               (make-frame)) ; leave one for the user
+                       (delete-frame frame))))
 
 (defun bufferlo-tab-close-kill-buffers (&optional killall internal-too)
   "Close the current tab and kill the local buffers.
@@ -1999,6 +2008,27 @@ current or new frame according to
                (mapconcat 'identity bookmarks-loaded " ")
                (float-time (time-subtract (current-time) start-time))))))
 
+;; TODO: handle option to save? prefix arg to save or not save?
+(defun bufferlo-bookmarks-close-interactive ()
+  "Prompt for active bufferlo bookmarks to close using the minibuffer."
+  (interactive)
+  (let* ((abms (bufferlo--active-bookmarks))
+         (abm-names (mapcar #'car abms))
+         (comps
+          (completion-all-completions
+           (completing-read "Close bookmark(s) without saving: "
+                            (lambda (str pred flag)
+                              (pcase flag
+                                ('metadata
+                                 '(metadata (category . bookmark)))
+                                (_
+                                 (all-completions str abm-names pred)))))
+           abm-names nil nil))
+         (base-size (cdr (last comps))))
+    (when base-size (setcdr (last comps) nil))
+    (setq comps (seq-uniq comps))
+    (bufferlo--close-active-bookmarks comps abms)))
+
 (defun bufferlo-bookmarks-save-interactive ()
   "Prompt for active bufferlo bookmarks to save using the minibuffer."
   (interactive)
@@ -2089,46 +2119,61 @@ transient work."
       (dolist (tab (funcall tab-bar-tabs-function frame))
         (setf (alist-get 'bufferlo-bookmark-tab-name tab) nil)))))
 
-(defun bufferlo-close-active-bookmarks ()
+(defun bufferlo--close-active-bookmarks (active-bookmark-names 
active-bookmarks)
+  "Close the bookmarks in ACTIVE-BOOKMARK-NAMES indexed by ACTIVE-BOOKMARKS."
+       (let* ((abms (seq-filter
+                                                               (lambda (x) 
(member (car x) active-bookmark-names))
+                                                               
active-bookmarks))
+                                (tbms (seq-filter
+                                                               (lambda (x) (eq 
'tbm (alist-get 'type (cadr x))))
+                                                               abms))
+                                (fbms (seq-filter
+                                                               (lambda (x) (eq 
'fbm (alist-get 'type (cadr x))))
+                                                               abms)))
+               ;; do tab bookmarks first, then frame bookmarks
+               (dolist (abm tbms)
+                       (let ((abm-frame (alist-get 'frame (cadr abm)))
+                                               (abm-tab (alist-get 'tab (cadr 
abm))))
+                               (with-selected-frame abm-frame
+                                       (tab-bar-select-tab
+                                        (1+ (tab-bar--tab-index abm-tab)))
+                                       (let 
((bufferlo-close-tab-kill-buffers-save-bookmark-prompt nil)
+                                                               
(bufferlo-close-tab-kill-buffers-prompt nil))
+                                               
(bufferlo-tab-close-kill-buffers)))))
+               (dolist (abm fbms)
+                       (let ((abm-frame (alist-get 'frame (cadr abm))))
+                               (with-selected-frame abm-frame
+                                       (let 
((bufferlo-delete-frame-kill-buffers-save-bookmark-prompt nil)
+                                                               
(bufferlo-delete-frame-kill-buffers-prompt nil))
+                                               
(bufferlo-delete-frame-kill-buffers)))))))
+
+(defun bufferlo-bookmarks-close ()
   "Close all active bufferlo frame and tab bookmarks and kill their buffers.
 
 You will be offered to save bookmarks using filter predicates or
 all unless a prefix argument is specified."
   (interactive)
-  (let ((close t))
-    (unless current-prefix-arg
-      (pcase (let ((read-answer-short t))
-               (read-answer "Save bookmarks before closing them: All, 
Predicate, Don't save "
-                            '(("all" ?a "Save all active bookmarks")
-                              ("pred" ?p "Save predicate-filtered bookmarks, 
if set")
-                              ("nosave" ?d "Close without saving")
-                              ("help" ?h "Help")
-                              ("quit" ?q "Quit"))))
-        ("all"
-         (bufferlo-bookmarks-save 'all))
-        ("pred"
-         (bufferlo-bookmarks-save))
-        ("nosave")
-        (_ (setq close nil))))
-    (when close
-      ;; do tabs first to clear their buffers, then frames
-      (while-let ((abms (bufferlo--active-bookmarks nil 'tbm)))
-        (let* ((abm (car abms))
-               (abm-frame (alist-get 'frame (cadr abm))))
-          (with-selected-frame abm-frame
-            (tab-bar-select-tab
-             (1+ (tab-bar--tab-index
-                  (alist-get 'tab (cadr abm)))))
-                                               (let 
((bufferlo-close-tab-kill-buffers-save-bookmark-prompt nil)
-                                                                       
(bufferlo-close-tab-kill-buffers-prompt nil))
-                                                       
(bufferlo-tab-close-kill-buffers)))))
-      (while-let ((abms (bufferlo--active-bookmarks nil 'fbm)))
-        (let* ((abm (car abms))
-               (abm-frame (alist-get 'frame (cadr abm))))
-          (with-selected-frame abm-frame
-            (let ((bufferlo-delete-frame-kill-buffers-save-bookmark-prompt nil)
-                  (bufferlo-delete-frame-kill-buffers-prompt nil))
-              (bufferlo-delete-frame-kill-buffers))))))))
+  (let* ((close t)
+                                (abms (bufferlo--active-bookmarks))
+                                (abm-names (mapcar #'car abms)))
+               (if (null abms)
+                               (message "No active bufferlo bookmarks")
+                       (unless current-prefix-arg
+                               (pcase (let ((read-answer-short t))
+                                                                (read-answer 
"Save bookmarks before closing them: All, Predicate, No save "
+                                                                               
                                        '(("all" ?a "Save all active bookmarks")
+                                                                               
                                                ("pred" ?p "Save 
predicate-filtered bookmarks, if set")
+                                                                               
                                                ("nosave" ?n "Don't save")
+                                                                               
                                                ("help" ?h "Help")
+                                                                               
                                                ("quit" ?q "Quit"))))
+                                       ("all"
+                                        (bufferlo-bookmarks-save 'all))
+                                       ("pred"
+                                        (bufferlo-bookmarks-save))
+                                       ("nosave")
+                                       (_ (setq close nil))))
+                       (when close
+                               (bufferlo--close-active-bookmarks abm-names 
abms)))))
 
 (defun bufferlo--bookmark-raise (abm)
   "Raise ABM's frame/tab."
@@ -2180,7 +2225,7 @@ OLDFN OLD-NAME NEW-NAME"
   (if (called-interactively-p 'interactive)
       (setq old-name (bookmark-completing-read "Old bookmark name")))
   (if-let ((abm (assoc old-name (bufferlo--active-bookmarks))))
-      (user-error "%s is an active bufferlo bookmark. Close its frame/tab, or 
clear it before renaming" old-name)
+      (user-error "%s is an active bufferlo bookmark--close its frame/tab, or 
clear it before renaming" old-name)
     (if (called-interactively-p 'interactive)
         (funcall-interactively oldfn old-name new-name)
       (funcall oldfn old-name new-name))))
@@ -2194,7 +2239,7 @@ OLDFN BOOKMARK-NAME BATCH"
       (setq bookmark-name (bookmark-completing-read "Delete bookmark"
                                                    bookmark-current-bookmark)))
   (if-let ((abm (assoc bookmark-name (bufferlo--active-bookmarks))))
-      (user-error "%s is an active bufferlo bookmark. Close its frame/tab, or 
clear it before deleting" bookmark-name)
+      (user-error "%s is an active bufferlo bookmark--close its frame/tab, or 
clear it before deleting" bookmark-name)
     (if (called-interactively-p 'interactive)
         (funcall-interactively oldfn bookmark-name batch)
       (funcall oldfn bookmark-name batch))))

Reply via email to