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

    Documentation updates WIP.
---
 README.org | 345 ++++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 218 insertions(+), 127 deletions(-)

diff --git a/README.org b/README.org
index e00c0c46f9..ee93cb034e 100644
--- a/README.org
+++ b/README.org
@@ -39,21 +39,28 @@ and ~ibuffer~. You can configure any command that selects a 
buffer to
 use the local buffer list via ~bufferlo-anywhere-mode~.
 
 In addition, bufferlo offers lightweight Emacs bookmarks-based
-persistence for frames and tabs to help you manage your transient
-workflows. Bufferlo bookmarks are compatible with built-in features
-such as bookmark-bmenu-list and third-party packages such as 
[[https://github.com/minad/consult][consult]]
-which offers consult-bookmark for interactive bookmark selection.
+persistence for frames, tabs, and sets of frames/tabs to help you
+manage your transient workflows. Bufferlo bookmarks are compatible
+with built-in features such as ~bookmark-bmenu-list~ and third-party
+packages such as [[https://github.com/minad/consult][consult]] which offers 
consult-bookmark for interactive
+bookmark selection.
 
 Bufferlo's mode-line indicator shows the currently active frame and/or
-tab bookmark name.
+tab bookmark name and indicates if a set is active.
 
 Note: Code examples use ~setq~ to customize options. You may also use
-~M-x customize-group bufferlo~. Emacs 29 introduced ~setopt~ which works
-correctly in the presence of ~defcustom~ setters. Currently the only
-bufferlo option with a setter is
+~M-x customize-group bufferlo~. Emacs 29 introduced ~setopt~ which
+works correctly in the presence of ~defcustom~ setters. Currently the
+only bufferlo option with such a setter is
 ~bufferlo-bookmarks-auto-save-idle-interval~ so be sure to set that
 interval timer in advance of enabling ~bufferlo-mode~.
 
+Note: Many bufferlo commands have short-hand aliases to accommodate
+the helpful ~which-key~ display (now a built-in for Emacs 30+).
+Bufferlo's menu references these aliases and not the main commands. We
+recommend that you use the short-hand aliases when binding your
+preferred keys to ensure the bufferlo menu reflects your key bindings.
+
 * Installation
 
 Bufferlo is available in [[https://elpa.gnu.org/packages/bufferlo.html][GNU 
ELPA]].
@@ -62,11 +69,11 @@ Install it via ~package-install~ and enable ~bufferlo-mode~
   (bufferlo-mode)
 #+end_src
 
-Or via ~use-package~
+Or via ~use-package~ (see below for a more comprehensive configuration example)
 #+begin_src emacs-lisp
   (use-package bufferlo
     :ensure t
-    :config
+    :init
     ;; To install ibuffer filters, set the below in advance of enabling
     ;; bufferlo-mode
     (setq bufferlo-ibuffer-bind-local-buffer-filter t)
@@ -74,6 +81,7 @@ Or via ~use-package~
     ;; frame or tab buffer lists, pick one of:
     (setq bufferlo-prefer-local-buffers t) ; frame locals
     (setq bufferlo-prefer-local-buffers 'tabs) ; frame + tab locals
+    :config
     (setq switch-to-prev-buffer-skip-regexp ; set this to filter out buffers 
in previous/next-buffer
           (concat "\\` *" ; ignore hidden buffers
                   
"\\(\\*\\(Messages\\|Ibuffer\\|scratch\\|Completions\\|Help\\|Warnings\\|Apropos\\|vc-diff\\)\\*\\)"
@@ -86,7 +94,8 @@ Note: Although the Emacs ~tab-bar-mode~ is fully supported, 
you do not
 have to use tabs to benefit from bufferlo; you can stick to a
 frame-only workflow. If you use ~tab-line-mode~ without
 ~tab-bar-mode~, your bufferlo experience will be the same as a
-frame-only user.
+frame-only user. Tab-oriented functions are active even if the tab-bar
+is hidden.
 
 * Usage
 
@@ -150,12 +159,13 @@ built-in global-buffer commands:
 - ~bufferlo-find-buffer-switch~: Switch to a frame/tab that contains
   the buffer in its local list, and select the buffer.
 
-** Bookmark management for frames and tabs
+** Bookmark management for frames, tabs, and sets
 
 Bufferlo can bookmark the buffers and windows belonging to individual
 frames and tabs for later recall between Emacs sessions or within a
-long-running session. All you need to do is provide a name for a
-bookmark and save it for later recall.
+long-running session. Sets can be defined as collections of frames
+and/or tabs to be recalled as a group. All you need to do is provide a
+name for a bookmark and save it for later recall.
 
 A tab bookmark includes the tab's window configuration, the state (not
 the contents) of all bookmarkable local buffers, and the bufferlo
@@ -164,7 +174,12 @@ local buffer list. Tabs can be restored into any frame.
 A frame bookmark saves every tab on a frame, each with the tab
 contents stated above. Frames can be restored into the current frame,
 replacing all tabs, into a new frame, or merged with the current
-frame's tabs.
+frame's tabs. Frames can also store their geometry for later
+restoration.
+
+A set bookmark saves a list of frame and tab bookmark names where
+constituent bookmarks behave as above. Sets can also store frame
+geometry.
 
 *** General bookmark commands
 
@@ -176,9 +191,10 @@ in combination with a package like 
[[https://github.com/minad/vertico][vertico]]
 - ~bufferlo-bookmarks-load-interactive~ (alias ~bufferlo-bms-load~):
   Load one or more stored saved bufferlo frame or tab bookmarks.
 
-- ~bufferlo-bookmarks-load~: load stored bufferlo bookmarks that match your
-  load predicates, or load all when using a prefix argument or when
-  you call the function using passing t as its sole argument.
+- ~bufferlo-bookmarks-load~: load stored bufferlo bookmarks that match
+  your load predicates, or load all when using a prefix argument or
+  when you call the function using passing t as its sole argument.
+  Bookmarks already loaded are ignored.
 
 - ~bufferlo-bookmarks-save-interactive~ (alias ~bufferlo-bms-save~):
   Save one or more currently active bufferlo frame or tab bookmarks.
@@ -240,6 +256,9 @@ in combination with a package like 
[[https://github.com/minad/vertico][vertico]]
   clear it and then delete). This function is also available via
   ~bookmark-bmenu-list~.
 
+Note: Bookmarks that are embedded in bufferlo bookmark sets will not
+be removed or renamed in the respective bookmark sets.
+
 *** Frame bookmark commands
 
 - ~bufferlo-bookmark-frame-save~ (alias ~bufferlo-bm-frame-save~):
@@ -520,8 +539,15 @@ similar to this can be found in your ~*Messages*~ buffer:
 
 ~Bufferlo tab: Could not restore emacs-todo.md (error 
(bookmark-error-no-filename stringp ~/.emacs/emacs-todo.md))~
 
+Please note: Emacs ~bookmark-jump-other-frame~ and
+~bookmark-jump-other-window~ commands are not compatible with bufferlo
+bookmarks. A future version of bufferlo might wrap these functions for
+convenience to either provide a warning or provide alternative jump
+functionality.
+
 It can be convenient to share bookmark files among your computers or
-among colleagues. Bookmarks can be made more "portable" with the following 
assumptions:
+among colleagues. Bookmarks can be made more "portable" with the
+following assumptions:
 
 - You share an Emacs configuration including packages, mode settings,
   etc.
@@ -607,38 +633,35 @@ You can integrate bufferlo with ~consult-buffer~.
 
 This is an example configuration:
 #+begin_src emacs-lisp
-  (defvar my-consult--source-buffer
-    `(:name "Other Buffers"
-      :narrow   ?b
-      :category buffer
-      :face     consult-buffer
-      :history  buffer-name-history
-      :state    ,#'consult--buffer-state
-      :items ,(lambda () (consult--buffer-query
-                          :predicate #'bufferlo-non-local-buffer-p
-                          :sort 'visibility
-                          :as #'buffer-name)))
-      "Non-local buffer candidate source for `consult-buffer'.")
-
-  (defvar my-consult--source-local-buffer
-    `(:name "Local Buffers"
-      :narrow   ?l
-      :category buffer
-      :face     consult-buffer
-      :history  buffer-name-history
-      :state    ,#'consult--buffer-state
-      :default  t
-      :items ,(lambda () (consult--buffer-query
-                          :predicate #'bufferlo-local-buffer-p
-                          :sort 'visibility
-                          :as #'buffer-name)))
-      "Local buffer candidate source for `consult-buffer'.")
-
-  (setq consult-buffer-sources '(consult--source-hidden-buffer
-                                 my-consult--source-local-buffer
-                                 my-consult--source-buffer
-                                 ;; ... other sources ...
-                                 ))
+  (defvar my:bufferlo-consult--source-local-buffer
+    (list :name "Bufferlo Local Buffers"
+          :narrow   ?l
+          :category 'buffer
+          :face     'consult-buffer
+          :history  'buffer-name-history
+          :state    #'consult--buffer-state
+          :default  t
+          :items    (lambda () (consult--buffer-query
+                                :predicate #'bufferlo-local-buffer-p
+                                :sort 'visibility
+                                :as #'buffer-name)))
+    "Local Bufferlo buffer candidate source for `consult-buffer'.")
+
+  (defvar my:bufferlo-consult--source-buffer
+    (list :name "Bufferlo Other Buffers"
+          :narrow   ?b
+          :category 'buffer
+          :face     'consult-buffer
+          :history  'buffer-name-history
+          :state    #'consult--buffer-state
+          :items    (lambda () (consult--buffer-query
+                                :predicate #'bufferlo-non-local-buffer-p
+                                :sort 'visibility
+                                :as #'buffer-name)))
+    "Non-local Bufferlo buffer candidate source for `consult-buffer'.")
+
+  (add-to-list 'consult-buffer-sources 
'my:bufferlo-consult--source-local-buffers)
+  (add-to-list 'consult-buffer-sources 
'my:bufferlo-consult--source-other-buffers)
 #+end_src
 
 [[./img/consult1.svg]]
@@ -646,38 +669,36 @@ Fig.1: All buffers are shown; the local buffers are 
grouped separately.
 
 You can also configure ~consult-buffer~ to hide the non-local buffers by 
default:
 #+begin_src emacs-lisp
-  (defvar my-consult--source-buffer
-    `(:name "All Buffers"
-      :narrow   ?a
-      :hidden   t
-      :category buffer
-      :face     consult-buffer
-      :history  buffer-name-history
-      :state    ,#'consult--buffer-state
-      :items ,(lambda () (consult--buffer-query
-                          :sort 'visibility
-                          :as #'buffer-name)))
-    "All buffer candidate source for `consult-buffer'.")
-
-  (defvar my-consult--source-local-buffer
-    `(:name nil
-      :narrow   ?b
-      :category buffer
-      :face     consult-buffer
-      :history  buffer-name-history
-      :state    ,#'consult--buffer-state
-      :default  t
-      :items ,(lambda () (consult--buffer-query
-                          :predicate #'bufferlo-local-buffer-p
-                          :sort 'visibility
-                          :as #'buffer-name)))
-    "Local buffer candidate source for `consult-buffer'.")
-
-  (setq consult-buffer-sources '(consult--source-hidden-buffer
-                                 my-consult--source-buffer
-                                 my-consult--source-local-buffer
-                                 ;; ... other sources ...
-                                 ))
+  (defvar my:bufferlo-consult--source-all-buffers
+    (list :name "Bufferlo All Buffers"
+          :narrow   ?a
+          :hidden   t
+          :category 'buffer
+          :face     'consult-buffer
+          :history  'buffer-name-history
+          :state    #'consult--buffer-state
+          :items    (lambda () (consult--buffer-query
+                                :sort 'visibility
+                                :as #'buffer-name)))
+    "All Bufferlo buffer candidate source for `consult-buffer'.")
+
+  (defvar my:bufferlo-consult--source-local-buffers
+    (list :name "Bufferlo Local Buffers"
+          :narrow   ?l
+          :category 'buffer
+          :face     'consult-buffer
+          :history  'buffer-name-history
+          :state    #'consult--buffer-state
+          :default  t
+          :items    (lambda () (consult--buffer-query
+                                :predicate #'bufferlo-local-buffer-p
+                                :sort 'visibility
+                                :as #'buffer-name)))
+    "Local Bufferlo buffer candidate source for `consult-buffer'.")
+
+  (add-to-list 'consult-buffer-sources #'consult--source-hidden-buffer)
+  (add-to-list 'consult-buffer-sources 
#'my:bufferlo-consult--source-all-buffers)
+  (add-to-list 'consult-buffer-sources 
#'my:bufferlo-consult--source-local-buffers)
 #+end_src
 
 [[./img/consult2.svg]]
@@ -722,9 +743,13 @@ buffer-position history, overriding bufferlo's saved 
bookmark
 positions, add this to your configuration:
 
 #+begin_src emacs-lisp
-  (setq bufferlo-bookmark-prefer-saveplace-point t)
+  (setq bufferlo-bookmark-inhibit-bookmark-point t)
 #+end_src
 
+This takes effect when saving or updating a Bufferlo bookmark.
+Existing bookmarks with embedded point will remain in force until
+saved.
+
 ** Complete configuration sample
 
 #+begin_src emacs-lisp
@@ -735,53 +760,93 @@ positions, add this to your configuration:
     :after (ibuffer consult) ; also mark these :demand t or use explicit 
require
     :bind
     (
-     ;; ibuffer
-     ("C-z i i" . bufferlo-ibuffer)
-     ("C-z i b" . bufferlo-ibuffer)
-     ("C-z i B" . bufferlo-ibuffer-orphans)
+     ;; buffer / ibuffer
+     ("C-z C-b" . bufferlo-ibuffer)
+     ("C-z M-C-b" . bufferlo-ibuffer-orphans)
+     ("C-z b -" . bufferlo-remove)
      ;; interactive
      ("C-z i l" . bufferlo-bms-load)
      ("C-z i s" . bufferlo-bms-save)
      ("C-z i c" . bufferlo-bms-close)
-     ("C-z i -" . bufferlo-remove)
      ("C-z i r" . bufferlo-bm-raise)
+     ;; dwim frame or tab bookmarks
+     ("C-z d s" . bufferlo-bm-save)
+     ("C-z d l" . bufferlo-bm-load)
+     ("C-z d 0" . bufferlo-bm-close)
      ;; tabs
      ("C-z t s" . bufferlo-bm-tab-save)               ; save
      ("C-z t u" . bufferlo-bm-tab-save-curr)          ; update
      ("C-z t l" . bufferlo-bm-tab-load)               ; load
      ("C-z t r" . bufferlo-bm-tab-load-curr)          ; reload
-     ("C-z t 0" . bufferlo-tab-close-kill-buffers)    ; kill
+     ("C-z t 0" . bufferlo-bm-tab-close-curr)         ; kill
      ;; frames
      ("C-z f s" . bufferlo-bm-frame-save)             ; save
      ("C-z f u" . bufferlo-bm-frame-save-curr)        ; update
      ("C-z f l" . bufferlo-bm-frame-load)             ; load
      ("C-z f r" . bufferlo-bm-frame-load-curr)        ; reload
      ("C-z f m" . bufferlo-bm-frame-load-merge)       ; merge
-     ("C-z f 0" . bufferlo-delete-frame-kill-buffers) ; kill
+     ("C-z f 0" . bufferlo-bm-frame-close-curr)       ; kill
+     ;; sets
+     ("C-z s s" . bufferlo-set-save)                  ; save
+     ("C-z s u" . bufferlo-set-save-curr)             ; update
+     ("C-z s l" . bufferlo-set-load)                  ; load
+     ("C-z s 0" . bufferlo-set-close)                 ; kill
+     ("C-z s c" . bufferlo-set-clear)                 ; clear
      )
     :init
     ;; these must be set before the bufferlo package is loaded
+    (setq bufferlo-menu-bar-show t)
+    (setq bufferlo-menu-bar-list-buffers 'ibuffer)
     (setq bufferlo-prefer-local-buffers 'tabs)
     (setq bufferlo-ibuffer-bind-local-buffer-filter t)
     (setq bufferlo-ibuffer-bind-keys t)
     :config
-    (setq bufferlo-mode-line-lighter-prefix " 🐮")
+    (setq bufferlo-mode-line-prefix "🐃") ; "🐮"
+    (setq bufferlo-mode-line-set-active-prefix "Ⓢ")
+    (setq bufferlo-mode-line-frame-prefix "Ⓕ")
+    (setq bufferlo-mode-line-tab-prefix "Ⓣ")
+    (setq bufferlo-mode-line-left-prefix nil)
+    (setq bufferlo-mode-line-right-suffix nil)
     (setq switch-to-prev-buffer-skip-regexp
           (concat "\\` *"
-                  
"\\(\\*\\(Messages\\|Ibuffer\\|scratch\\|Completions\\|Help\\|Warnings\\|Apropos\\|vc-diff\\)\\*\\)"
+                  "\\(\\*\\(" ; earmuffs
+                  (mapconcat #'identity
+                             '("Messages"
+                               "Buffer List"
+                               "Ibuffer"
+                               "Local Buffer List" ; bufferlo
+                               "scratch"
+                               "Occur"
+                               "Completions"
+                               "Help"
+                               "Warnings"
+                               "Apropos"
+                               "Bookmark List"
+                               "Async-native-compile-log"
+                               "Flymake log"
+                               "ruff-format errors"
+                               "vc-diff")
+                             "\\|")
+                  "\\)\\*\\)"
+                  "\\|" (rx "*" (1+ anything) " Ibuffer*")
                   "\\|" (rx "*helpful " (1+ anything) "*")
+                  "\\|" (rx "magit" (* anything) ": " (1+ anything))
                   "\\'"))
     (setq bufferlo-kill-buffers-prompt t)
-    (setq bufferlo-bookmark-prefer-saveplace-point t)
+    (setq bufferlo-kill-modified-buffers-policy 
'retain-modified-kill-without-file-name) ; nil 'retain-modified 
'retain-modified-kill-without-file-name 'kill-modified
+    (setq bufferlo-bookmark-inhibit-bookmark-point t)
     (setq bufferlo-delete-frame-kill-buffers-prompt t)
+    (setq bufferlo-bookmark-frame-save-on-delete 'when-bookmarked)
+    (setq bufferlo-bookmark-tab-save-on-close 'when-bookmarked)
     (setq bufferlo-close-tab-kill-buffers-prompt t)
-    (setq bufferlo-bookmark-frame-load-make-frame t)
+    (setq bufferlo-bookmark-frame-load-make-frame 'restore-geometry)
     (setq bufferlo-bookmark-frame-load-policy 'prompt)
     (setq bufferlo-bookmark-frame-duplicate-policy 'prompt)
     (setq bufferlo-bookmark-frame-clone-policy 'prompt)
     (setq bufferlo-bookmark-tab-replace-policy 'new)
     (setq bufferlo-bookmark-tab-duplicate-policy 'prompt)
-    (setq bufferlo-bookmark-tab-load-into-bookmarked-frame-policy 'prompt)
+    (setq bufferlo-bookmark-tab-in-bookmarked-frame-policy 'prompt)
+    ;; +++ (setq bufferlo-bookmark-tab-load-into-bookmarked-frame-policy 
'prompt)
     (setq bufferlo-bookmarks-save-duplicates-policy 'prompt)
     (setq bufferlo-bookmarks-save-frame-policy 'all)
     (setq bufferlo-bookmarks-load-tabs-make-frame t)
@@ -790,6 +855,32 @@ positions, add this to your configuration:
     (setq bufferlo-bookmarks-load-at-emacs-startup-tabs-make-frame nil)
     (setopt bufferlo-bookmarks-auto-save-idle-interval (* 60 5)) ; 5 minutes
     (setq bufferlo-bookmarks-auto-save-messages 'saved)
+    (setq bufferlo-set-restore-geometry-policy 'all)
+    (setq bufferlo-set-restore-tabs-reuse-init-frame 'reuse) ; nil 'reuse 
'reuse-reset-geometry
+    (setq bufferlo-frameset-restore-geometry 'bufferlo)
+    (setq bufferlo-frame-geometry-function #'bufferlo-frame-geometry-default)
+
+    (defun my/bufferlo-frameset-restore-parameters ()
+      "Function to create parameters for `frameset-restore', which see."
+      (cond (my:on-linux-gnome
+             (list :reuse-frames nil
+                   :force-display nil ; default t
+                   :force-onscreen (display-graphic-p)
+                   :cleanup-frames nil))
+            (t
+             (bufferlo-frameset-restore-parameters-default))))
+    (setq bufferlo-frameset-restore-parameters-function 
#'my/bufferlo-frameset-restore-parameters)
+
+    (setq bufferlo-frameset-save-filter
+          '(my:frame-id
+            zoom--frame-snapshot))
+
+    (setq bufferlo-frameset-restore-filter nil)
+
+    (defun my/bufferlo-frameset-restore-function (frameset)
+      (let ((my:frame-maximize nil))
+        (bufferlo-frameset-restore-default frameset)))
+    (setq bufferlo-frameset-restore-function 
#'my/bufferlo-frameset-restore-function)
 
     (setq bufferlo-bookmark-buffers-exclude-filters
           (list
@@ -814,49 +905,49 @@ positions, add this to your configuration:
       (string-match-p (rx "=al") bookmark-name))
     (add-hook 'bufferlo-bookmarks-load-predicate-functions 
#'my/bufferlo-bookmarks-load-p)
 
-    (defvar my:bufferlo-consult--source-all-buffers
-      `(:name "All Buffers"
-              :narrow   ?a
-              :hidden   t
-              :category buffer
-              :face     consult-buffer
-              :history  buffer-name-history
-              :state    ,#'consult--buffer-state
-              :items ,(lambda () (consult--buffer-query
+    (defvar my:bufferlo-consult--source-local-buffers
+      (list :name "Bufferlo Local Buffers"
+            :narrow   ?l
+            :category 'buffer
+            :face     'consult-buffer
+            :history  'buffer-name-history
+            :state    #'consult--buffer-state
+            :default  t
+            :items    (lambda () (consult--buffer-query
+                                  :predicate #'bufferlo-local-buffer-p
                                   :sort 'visibility
                                   :as #'buffer-name)))
-      "All buffer candidate source for `consult-buffer'.")
+      "Local Bufferlo buffer candidate source for `consult-buffer'.")
 
     (defvar my:bufferlo-consult--source-other-buffers
-      `(:name "Other Buffers"
-              :narrow   ?b
-              :category buffer
-              :face     consult-buffer
-              :history  buffer-name-history
-              :state    ,#'consult--buffer-state
-              :items ,(lambda () (consult--buffer-query
+      (list :name "Bufferlo Other Buffers"
+            :narrow   ?o
+            :category 'buffer
+            :face     'consult-buffer
+            :history  'buffer-name-history
+            :state    #'consult--buffer-state
+            :items    (lambda () (consult--buffer-query
                                   :predicate #'bufferlo-non-local-buffer-p
                                   :sort 'visibility
                                   :as #'buffer-name)))
-      "Non-local buffer candidate source for `consult-buffer'.")
+      "Non-local Bufferlo buffer candidate source for `consult-buffer'.")
 
-    (defvar my:bufferlo-consult--source-local-buffers
-      `(:name "Local Buffers"
-              :narrow   ?l
-              :category buffer
-              :face     consult-buffer
-              :history  buffer-name-history
-              :state    ,#'consult--buffer-state
-              :default  t
-              :items ,(lambda () (consult--buffer-query
-                                  :predicate #'bufferlo-local-buffer-p
+    (defvar my:bufferlo-consult--source-all-buffers
+      (list :name "Bufferlo All Buffers"
+            :narrow   ?a
+            :hidden   t
+            :category 'buffer
+            :face     'consult-buffer
+            :history  'buffer-name-history
+            :state    #'consult--buffer-state
+            :items    (lambda () (consult--buffer-query
                                   :sort 'visibility
                                   :as #'buffer-name)))
-      "Local buffer candidate source for `consult-buffer'.")
+      "All Bufferlo buffer candidate source for `consult-buffer'.")
 
-    (add-to-list 'consult-buffer-sources 
'my:bufferlo-consult--source-all-buffers)
-    (add-to-list 'consult-buffer-sources 
'my:bufferlo-consult--source-other-buffers)
     (add-to-list 'consult-buffer-sources 
'my:bufferlo-consult--source-local-buffers)
+    (add-to-list 'consult-buffer-sources 
'my:bufferlo-consult--source-other-buffers)
+    (add-to-list 'consult-buffer-sources 
'my:bufferlo-consult--source-all-buffers)
 
     (bufferlo-mode)
     (bufferlo-anywhere-mode)

Reply via email to