branch: externals/bufferlo
commit 16132cefc35d9e973ce2f1d21c79af9493810440
Author: shipmints <[email protected]>
Commit: shipmints <[email protected]>
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)