From bc706f9aa73034b2fe36600ceba9f9c50af3da69 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. * lisp/progmodes/project (project--switch-to-buffer-check): New function. (project-switch-to-buffer): Use it (bug#54100). --- lisp/progmodes/project.el | 81 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 880c5b5517..3c998c00f5 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,72 @@ 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")) + +(defun project--switch-to-buffer-check (buf conditions) + "Check if buffer BUF matches any element of the list CONDITIONS. +See `project-switch-to-buffer-conditions' for more details on the +form of CONDITIONS." + (catch 'switch + (dolist (c conditions) + (when (cond + ((stringp c) + (string-match-p c (buffer-name buf))) + ((symbolp c) + (funcall c buf)) + ((eq (car-safe c) 'major-mode) + (eq (buffer-local-value 'major-mode buf) + (cdr c))) + ((eq (car-safe c) 'derived-mode) + (provided-mode-derived-p + (buffer-local-value 'major-mode buf) + (cdr c))) + ((eq (car-safe c) 'not) + (not (project--switch-to-buffer-check buf (cdr c)))) + ((eq (car-safe c) 'or) + (project--switch-to-buffer-check buf (cdr c))) + ((eq (car-safe c) 'and) + (seq-every-p + (apply-partially #'project--switch-to-buffer-check + buf) + (mapcar #'list (cdr c))))) + (throw 'switch t))))) + ;;;###autoload (defun project-switch-to-buffer (buffer-or-name) "Display buffer BUFFER-OR-NAME in the selected window. @@ -1136,7 +1203,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--switch-to-buffer-check + (cdr buffer) project-switch-to-buffer-conditions))))) (switch-to-buffer buffer-or-name)) ;;;###autoload -- 2.25.1