Support a function in the BUFFER-LIST arg of list-buffers-noselect (bug#59935)

* lisp/buff-menu.el (Buffer-menu-buffer-list): New buffer-local variable.
(list-buffers-noselect): Set Buffer-menu-buffer-list to 'buffer-list'
that now keeps the buffer-local value of the provided buffer list
or a function that returns the buffer list.
(list-buffers--refresh): Handle buffer-list and Buffer-menu-buffer-list
as a function and as a list.

* lisp/progmodes/project.el (project-list-buffers): Let-bind
'buffer-list-function' used by both legacy code and the new version
of list-buffers-noselect that supports its arg BUFFER-LIST as a function.
This commit is contained in:
Juri Linkov 2022-12-13 19:47:47 +02:00
parent def51dd645
commit a99d0e7e6c
2 changed files with 38 additions and 10 deletions

View file

@ -107,6 +107,9 @@ The value should be a function of one argument; it will be
called with the buffer. If this function returns non-nil, called with the buffer. If this function returns non-nil,
then the buffer will be displayed in the buffer list.") then the buffer will be displayed in the buffer list.")
(defvar-local Buffer-menu-buffer-list nil
"The current list of buffers or function to return buffers.")
(defvar-keymap Buffer-menu-mode-map (defvar-keymap Buffer-menu-mode-map
:doc "Local keymap for `Buffer-menu-mode' buffers." :doc "Local keymap for `Buffer-menu-mode' buffers."
:parent tabulated-list-mode-map :parent tabulated-list-mode-map
@ -628,8 +631,10 @@ This behaves like invoking \\[read-only-mode] in that buffer."
This is called by `buffer-menu' and others as a subroutine. This is called by `buffer-menu' and others as a subroutine.
If FILES-ONLY is non-nil, show only file-visiting buffers. If FILES-ONLY is non-nil, show only file-visiting buffers.
If BUFFER-LIST is non-nil, it should be a list of buffers; it If BUFFER-LIST is non-nil, it should be either a list of buffers
means list those buffers and no others. or a function that returns a list of buffers; it means
list those buffers and no others.
See more at `Buffer-menu-buffer-list'.
If FILTER-PREDICATE is non-nil, it should be a function If FILTER-PREDICATE is non-nil, it should be a function
that filters out buffers from the list of buffers. that filters out buffers from the list of buffers.
See more at `Buffer-menu-filter-predicate'." See more at `Buffer-menu-filter-predicate'."
@ -639,6 +644,7 @@ See more at `Buffer-menu-filter-predicate'."
(Buffer-menu-mode) (Buffer-menu-mode)
(setq Buffer-menu-files-only (setq Buffer-menu-files-only
(and files-only (>= (prefix-numeric-value files-only) 0))) (and files-only (>= (prefix-numeric-value files-only) 0)))
(setq Buffer-menu-buffer-list buffer-list)
(setq Buffer-menu-filter-predicate filter-predicate) (setq Buffer-menu-filter-predicate filter-predicate)
(list-buffers--refresh buffer-list old-buffer) (list-buffers--refresh buffer-list old-buffer)
(tabulated-list-print)) (tabulated-list-print))
@ -665,9 +671,16 @@ See more at `Buffer-menu-filter-predicate'."
Buffer-menu-filter-predicate)) Buffer-menu-filter-predicate))
entries name-width) entries name-width)
;; Collect info for each buffer we're interested in. ;; Collect info for each buffer we're interested in.
(dolist (buffer (or buffer-list (dolist (buffer (cond
(buffer-list (if Buffer-menu-use-frame-buffer-list ((functionp buffer-list)
(selected-frame))))) (funcall buffer-list))
(buffer-list)
((functionp Buffer-menu-buffer-list)
(funcall Buffer-menu-buffer-list))
(Buffer-menu-buffer-list)
(t (buffer-list
(if Buffer-menu-use-frame-buffer-list
(selected-frame))))))
(with-current-buffer buffer (with-current-buffer buffer
(let* ((name (buffer-name)) (let* ((name (buffer-name))
(file buffer-file-name)) (file buffer-file-name))

View file

@ -1340,18 +1340,33 @@ By default, all project buffers are listed except those whose names
start with a space (which are for internal use). With prefix argument start with a space (which are for internal use). With prefix argument
ARG, show only buffers that are visiting files." ARG, show only buffers that are visiting files."
(interactive "P") (interactive "P")
(let ((pr (project-current t))) (let* ((pr (project-current t))
(buffer-list-function
(lambda ()
(seq-filter
(lambda (buffer)
(let ((name (buffer-name buffer))
(file (buffer-file-name buffer)))
(and (or (not (string= (substring name 0 1) " "))
file)
(not (eq buffer (current-buffer)))
(or file (not Buffer-menu-files-only)))))
(project-buffers pr)))))
(display-buffer (display-buffer
(if (version< emacs-version "29.0.50") (if (version< emacs-version "29.0.50")
(let ((buf (list-buffers-noselect arg (project-buffers pr)))) (let ((buf (list-buffers-noselect
arg (with-current-buffer
(get-buffer-create "*Buffer List*")
(let ((Buffer-menu-files-only arg))
(funcall buffer-list-function))))))
(with-current-buffer buf (with-current-buffer buf
(setq-local revert-buffer-function (setq-local revert-buffer-function
(lambda (&rest _ignored) (lambda (&rest _ignored)
(list-buffers--refresh (project-buffers pr)) (list-buffers--refresh
(funcall buffer-list-function))
(tabulated-list-print t)))) (tabulated-list-print t))))
buf) buf)
(list-buffers-noselect (list-buffers-noselect arg buffer-list-function)))))
arg nil (lambda (buf) (memq buf (project-buffers pr))))))))
(defcustom project-kill-buffer-conditions (defcustom project-kill-buffer-conditions
'(buffer-file-name ; All file-visiting buffers are included. '(buffer-file-name ; All file-visiting buffers are included.