[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/bufferlo 1360e91d9d 1/2: Add "bufferlo anywhere"
|
From: |
ELPA Syncer |
|
Subject: |
[elpa] externals/bufferlo 1360e91d9d 1/2: Add "bufferlo anywhere" |
|
Date: |
Fri, 5 Jan 2024 15:57:27 -0500 (EST) |
branch: externals/bufferlo
commit 1360e91d9dd099ab4d7afc0780c1809a06e65d4a
Author: Florian Rommel <mail@florommel.de>
Commit: Florian Rommel <mail@florommel.de>
Add "bufferlo anywhere"
---
README.org | 23 +++++++++-
bufferlo.el | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 157 insertions(+), 2 deletions(-)
diff --git a/README.org b/README.org
index e5baba1d79..d7c9e69df4 100644
--- a/README.org
+++ b/README.org
@@ -7,7 +7,7 @@ This gives you separate buffer lists per frame and per
(tab-bar) tab.
Bufferlo is a lightweight wrapper around Emacs's buffer-list frame
parameter. In contrast to similar solutions, it integrates seamlessly
with the standard frame and tab management facilities, including
-undeletion of frame and tabs, tab duplication and moving, frame
+undeletion of frames and tabs, tab duplication and moving, frame
cloning, and persisting sessions (via desktop.el).
A buffer is added to the local buffer list when it is displayed in the
@@ -236,3 +236,24 @@ Of course, you can also set an arbitrary buffer as the
initial frame buffer:
(switch-to-buffer "<BUFFER_NAME>")))
(add-hook 'after-make-frame-functions #'my-set-initial-frame-buffer)
#+END_SRC
+
+
+** Bufferlo Anywhere
+
+"Bufferlo anywhere" is an optional feature that lets you have
+bufferlo's frame/tab-local buffer list anywhere you like, i.e. in any
+command with interactive buffer selection (via ~read-buffer~,
+e.g., ~diff-buffers~, ~make-indirect-buffer~, ...) -- not just in the
+switch-buffer facilities. You can configure which commands use
+bufferlo's local list and which use the global list.
+
+Enable ~bufferlo-anywhere-mode~ to use bufferlo's local buffer list by
+default. Customize ~bufferlo-anywhere-filter~ and
+~bufferlo-anywhere-filter-type~ to restrict the commands that use the
+local list. With the command prefix ~bufferlo-anywhere-disable-prefix~,
+you can temporarily disable ~bufferlo-anywhere-mode~ for the next
+command.
+
+Instead the minor mode, you can use the command prefix
+~bufferlo-anywhere-enable-prefix~, which only temporarily enables
+bufferlo's local buffer list for the next command.
diff --git a/bufferlo.el b/bufferlo.el
index 9b3844eaf2..2f707c8057 100644
--- a/bufferlo.el
+++ b/bufferlo.el
@@ -1,6 +1,6 @@
;;; bufferlo.el --- Manage frame/tab-local buffer lists -*- lexical-binding: t
-*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Florian Rommel <mail@florommel.de>
;; Maintainer: Florian Rommel <mail@florommel.de>
@@ -134,6 +134,26 @@ You can set this to \"*scratch*\"."
If nil, the local scratch buffers' major mode is set to `initial-major-mode'."
:type 'function)
+(defcustom bufferlo-anywhere-filter '(switch-to-buffer
bufferlo-switch-to-buffer)
+ "The functions that use the local buffer list in `bufferlo-anywhere-mode'.
+If `bufferlo-anywhere-filter-type' is set to `exclude', this is an exclude
+filter (i.e., determines the functions that do not use the local buffer list).
+If `bufferlo-anywhere-filter-type' is set to `include' (or any other value),
+this is an include filter.
+The value can either be a list of functions, or t (for all functions),
+or a custom filter function that takes a function symbol as its argument and
+returns whether the probed function should be filtered (non-nil) or
+not-filtered (nil)."
+ :type '(choice (repeat :tag "Filter specific functions" function)
+ (const :tag "All functions" t)
+ (function :tag "Custom filter function")))
+
+(defcustom bufferlo-anywhere-filter-type 'exclude
+ "Determines whether `bufferlo-anywhere-filter' is an include or exclude
filter.
+Set this to `include' or `exclude'."
+ :type '(radio (const :tag "Include filter" include)
+ (const :tag "Exclude filter" exclude)))
+
(defvar bufferlo--desktop-advice-active nil)
(defvar bufferlo--desktop-advice-active-force nil)
@@ -776,6 +796,120 @@ The parameters OTHER-WINDOW-P NOSELECT SHRINK are passed
to `ibuffer'."
(ibuffer other-window-p name '((bufferlo-orphan-buffers . nil))
noselect shrink)))
+(define-minor-mode bufferlo-anywhere-mode
+ "Frame/tab-local buffer lists anywhere you like.
+Enables bufferlo's local buffer list for any function that interactively
prompts
+for buffers via `read-buffer'. By default this enables the local buffer list
+for (almost) all functions. Customize `bufferlo-anywhere-filter' and
+`bufferlo-anywhere-filter-type' to adapt the behavior.
+This minor mode requires `bufferlo-mode' to be enabled.
+You can use `bufferlo-anywhere-disable' to disable the local buffer list for
+the next command, when the mode is enabled."
+ :global t
+ :require 'bufferlo
+ :init-value nil
+ :lighter nil
+ :keymap nil
+ (if bufferlo-anywhere-mode
+ (advice-add #'call-interactively :around #'bufferlo--interactive-advice)
+ (advice-remove #'call-interactively #'bufferlo--interactive-advice)))
+
+(defvar bufferlo--anywhere-tmp-enabled nil)
+(defvar bufferlo--anywhere-tmp-disabled nil)
+(defvar bufferlo--anywhere-old-read-buffer-function nil)
+(defvar bufferlo--anywhere-nested nil)
+
+(defun bufferlo--interactive-advice (oldfn function &optional record-flags
keys)
+ "Advice function for `call-interactively' for `bufferlo-anywhere-mode'.
+Temporarily overrides the `read-buffer-function' to filter the
+available buffers to bufferlo's local buffer list.
+OLDFN is the original function.
+FUNCTION is the interactively called functions.
+RECORD-FLAGS and KEYS are passed to `call-interactively'."
+ (if (or bufferlo--anywhere-tmp-enabled
+ (and (not bufferlo--anywhere-tmp-disabled)
+ (xor (eq bufferlo-anywhere-filter-type 'exclude)
+ (cond
+ ((eq bufferlo-anywhere-filter t) t)
+ ((listp bufferlo-anywhere-filter)
+ (memq function bufferlo-anywhere-filter))
+ ((functionp bufferlo-anywhere-filter)
+ (funcall bufferlo-anywhere-filter function))))))
+ (let* ((bufferlo--anywhere-old-read-buffer-function
+ ;; Preserve the original `read-buffer-function' but not for
+ ;; nested calls; otherwise we would save our own function.
+ (if bufferlo--anywhere-nested
+ bufferlo--anywhere-old-read-buffer-function
+ read-buffer-function))
+ (bufferlo--anywhere-nested t)
+ (read-buffer-function
+ (lambda (prompt &optional def require-match predicate)
+ (let ((read-buffer-function
+ bufferlo--anywhere-old-read-buffer-function))
+ (read-buffer prompt def require-match
+ (lambda (b)
+ (and (bufferlo-local-buffer-p
+ (get-buffer
+ (if (stringp b) b (car b))))
+ (or (not predicate)
+ (funcall predicate b)))))))))
+ (apply oldfn (list function record-flags keys)))
+ ;; `call-interactively' can be nested, e.g., on M-x invocations.
+ ;; Therefore, we restore the original value of the `read-buffer-function'
+ ;; if we do not use bufferlo's local buffer list for this call.
+ (let ((read-buffer-function
+ (if bufferlo--anywhere-nested
+ bufferlo--anywhere-old-read-buffer-function
+ read-buffer-function)))
+ (apply oldfn (list function record-flags keys)))))
+
+(defun bufferlo-anywhere-disable-prefix ()
+ "Disable `bufferlo-anywhere-mode' only for the next command.
+Has no effect if `bufferlo-anywhere-mode' is not enabled.
+Has no effect if the next command does not query for a buffer."
+ (interactive)
+ (let* ((command this-command)
+ (minibuffer-depth (minibuffer-depth))
+ (postfun (make-symbol "bufferlo--anywhere-reenable-next-command")))
+ (fset postfun
+ (lambda ()
+ (unless (or
+ ;; from window.el:display-buffer-override-next-command
+ (> (minibuffer-depth) minibuffer-depth)
+ (eq this-command command))
+ (setq bufferlo--anywhere-tmp-disabled nil)
+ (remove-hook 'post-command-hook postfun))))
+ (setq bufferlo--anywhere-tmp-disabled t)
+ (add-hook 'post-command-hook postfun)))
+
+(defun bufferlo-anywhere-enable-prefix ()
+ "Use bufferlo's local buffer list for the next command.
+Has a similar effect as `bufferlo-anywhere-mode' but only for the next command.
+Has no effect if the next command does not query for a buffer.
+Can be used with or without `bufferlo-anywhere-mode' enabled.
+In contrast to `bufferlo-anywhere-mode', this does not adhere to
+`bufferlo-anywhere-filter'. Therefore, you can use it in conjunction with
+`bufferlo-anywhere-mode' to temporarily disable the configured filters."
+ (interactive)
+ (let* ((command this-command)
+ (minibuffer-depth (minibuffer-depth))
+ (postfun (make-symbol "bufferlo--anywhere-disable-next-command")))
+ (fset postfun
+ (lambda ()
+ (unless (or
+ ;; from window.el:display-buffer-override-next-command
+ (> (minibuffer-depth) minibuffer-depth)
+ (eq this-command command))
+ (setq bufferlo--anywhere-tmp-enabled nil)
+ (unless bufferlo-anywhere-mode
+ (advice-remove #'call-interactively
+ #'bufferlo--interactive-advice))
+ (remove-hook 'post-command-hook postfun))))
+ (setq bufferlo--anywhere-tmp-enabled t)
+ (unless bufferlo-anywhere-mode
+ (advice-add #'call-interactively :around #'bufferlo--interactive-advice))
+ (add-hook 'post-command-hook postfun)))
+
(provide 'bufferlo)
;;; bufferlo.el ends here