From a8143035ea71376f0e53ce784991d9cd490719ee Mon Sep 17 00:00:00 2001 From: Manuel Uberti Date: Wed, 23 Feb 2022 09:25:32 +0100 Subject: [PATCH] Add project-switch-to-buffer-conditions * lisp/progmodes/project.el (project-switch-to-buffer-conditions): New defcustom. (project-switch-to-buffer): Use it (bug#54100). --- lisp/progmodes/project.el | 71 +++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 880c5b5517..e4184c69bc 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1112,16 +1112,17 @@ project-compile compilation-buffer-name-function))) (call-interactively #'compile))) -(defun project--read-project-buffer () +(defun project--read-project-buffer (&optional predicate) (let* ((pr (project-current t)) (current-buffer (current-buffer)) (other-buffer (other-buffer current-buffer)) (other-name (buffer-name other-buffer)) (buffers (project-buffers pr)) (predicate - (lambda (buffer) - ;; BUFFER is an entry (BUF-NAME . BUF-OBJ) of Vbuffer_alist. - (memq (cdr buffer) buffers)))) + (or predicate + (lambda (buffer) + ;; BUFFER is an entry (BUF-NAME . BUF-OBJ) of Vbuffer_alist. + (memq (cdr buffer) buffers))))) (read-buffer "Switch to buffer: " (when (funcall predicate (cons other-name other-buffer)) @@ -1129,6 +1130,43 @@ project--read-project-buffer nil predicate))) +(defcustom project-switch-to-buffer-conditions nil + "List of conditions to filter the buffers to be switched to. +This list is used by `project-switch-to-buffer'. +Each condition is either: +- a regular expression, to match a buffer name, +- a predicate function that takes a buffer object as argument + and returns non-nil if the buffer should be switched to, +- a cons-cell, where the car describes how to interpret the cdr. + The car can be one of the following: + * `major-mode': the buffer is switched to if the buffer's major + mode is eq to the cons-cell's cdr + * `derived-mode': the buffer is switched to if the buffer's major + mode is derived from the major mode denoted by the cons-cell's + cdr + * `not': the cdr is interpreted as a negation of a condition. + * `and': the cdr is a list of recursive conditions, that all have + to be met. + * `or': the cdr is a list of recursive conditions, of which at + least one has to be met. + +If any of these conditions are satisfied for a buffer in the +current project, `project-switch-to-buffer' switches to it." + :type '(repeat (choice regexp function symbol + (cons :tag "Major mode" + (const major-mode) symbol) + (cons :tag "Derived mode" + (const derived-mode) symbol) + (cons :tag "Negation" + (const not) sexp) + (cons :tag "Conjunction" + (const and) sexp) + (cons :tag "Disjunction" + (const or) sexp))) + :version "29.1" + :group 'project + :package-version '(project . "0.8.2")) + ;;;###autoload (defun project-switch-to-buffer (buffer-or-name) "Display buffer BUFFER-OR-NAME in the selected window. @@ -1136,7 +1174,11 @@ project-switch-to-buffer current project. Two buffers belong to the same project if their project instances, as reported by `project-current' in each buffer, are identical." - (interactive (list (project--read-project-buffer))) + (interactive + (list (project--read-project-buffer + (lambda (buffer) + (project--buffer-check + (cdr buffer) project-switch-to-buffer-conditions))))) (switch-to-buffer buffer-or-name)) ;;;###autoload @@ -1239,11 +1281,12 @@ project--buffer-list (push buf bufs))) (nreverse bufs))) -(defun project--kill-buffer-check (buf conditions) +(defun project--buffer-check (buf conditions) "Check if buffer BUF matches any element of the list CONDITIONS. -See `project-kill-buffer-conditions' for more details on the form -of CONDITIONS." - (catch 'kill +See `project-kill-buffer-conditions' or +`project-switch-to-buffer-conditions' for more details on the +form of CONDITIONS." + (catch 'match (dolist (c conditions) (when (cond ((stringp c) @@ -1258,15 +1301,15 @@ project--kill-buffer-check (buffer-local-value 'major-mode buf) (cdr c))) ((eq (car-safe c) 'not) - (not (project--kill-buffer-check buf (cdr c)))) + (not (project--buffer-check buf (cdr c)))) ((eq (car-safe c) 'or) - (project--kill-buffer-check buf (cdr c))) + (project--buffer-check buf (cdr c))) ((eq (car-safe c) 'and) (seq-every-p - (apply-partially #'project--kill-buffer-check + (apply-partially #'project--buffer-check buf) (mapcar #'list (cdr c))))) - (throw 'kill t))))) + (throw 'match t))))) (defun project--buffers-to-kill (pr) "Return list of buffers in project PR to kill. @@ -1274,7 +1317,7 @@ project--buffers-to-kill in `project-kill-buffer-conditions'." (let (bufs) (dolist (buf (project-buffers pr)) - (when (project--kill-buffer-check buf project-kill-buffer-conditions) + (when (project--buffer-check buf project-kill-buffer-conditions) (push buf bufs))) bufs)) -- 2.25.1