[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#54296: Add buffer-matching functionality
From: |
Philip Kaludercic |
Subject: |
bug#54296: Add buffer-matching functionality |
Date: |
Thu, 10 Mar 2022 10:05:04 +0000 |
Lars Ingebrigtsen <larsi@gnus.org> writes:
> Philip Kaludercic <philipk@posteo.net> writes:
>
>> Either way I would consider these functions useful and would have wanted
>> to use them in my own code many times before. While difficult, it might
>> also be useful for things like display-buffer-alist (the issue is that
>> a function as a condition in display-buffer-alist has to accept two
>> arguments, while the proposed patch only takes one).
>
> Hm... how would this be used with display-buffer-alist, then? (And
> perhaps Martin has some comments; added to the CCs.)
See below.
>> To match functions such as string-match, the argument of buffer-match
>> could be reversed so that the function can be used as a testfn to
>> assoc/alist-get.
>
> I think I'd prefer to have the parameters reversed -- the condition is a
> kind of predicate, and these days we seem to prefer to have the
> predicate first.
I agree, it makes more sense.
>> +(defun buffer-match (buffer condition)
>> + "Return non-nil if BUFFER matches CONDITION.
>> +CONDITION is 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 killed,
>
> Killed?
That was a typo from copying the docstring. Here is the updated patch:
>From 6714a4dc7168e6806dba0707c9c0b80d3365b2c5 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk@posteo.net>
Date: Mon, 7 Mar 2022 20:49:42 +0100
Subject: [PATCH 1/2] Generalise buffer matching from project.el
* subr.el (buffer-match): Add function to check if a buffer satisfies
a condition.
(match-buffers): Returns all buffers that satisfy a condition.
---
lisp/subr.el | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/lisp/subr.el b/lisp/subr.el
index 2321765f95..adcd25ec14 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -6613,4 +6613,68 @@ delete-line
(forward-line 1)
(point))))
+(defun buffer-match (condition buffer-or-name &optional arg)
+ "Return non-nil if BUFFER-OR-NAME matches CONDITION.
+CONDITION is is either:
+- a regular expression, to match a buffer name,
+- a predicate function that takes a buffer object and ARG as
+ arguments and returns non-nil if the buffer matches,
+- a cons-cell, where the car describes how to interpret the cdr.
+ The car can be one of the following:
+ * `major-mode': the buffer matches if the buffer's major
+ mode is eq to the cons-cell's cdr
+ * `derived-mode': the buffer matches 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 condition, that all have
+ to be met.
+ * `or': the cdr is a list of recursive condition, of which at
+ least one has to be met."
+ (letrec
+ ((buffer (get-buffer buffer-or-name))
+ (match
+ (lambda (conditions)
+ (catch 'match
+ (dolist (condition conditions)
+ (when (cond
+ ((stringp condition)
+ (string-match-p condition (buffer-name buffer)))
+ ((functionp condition)
+ (if (eq 1 (cdr (func-arity condition)))
+ (funcall condition buffer)
+ (funcall condition buffer arg)))
+ ((eq (car-safe condition) 'major-mode)
+ (eq (buffer-local-value 'major-mode buffer)
+ (cdr condition)))
+ ((eq (car-safe condition) 'derived-mode)
+ (provided-mode-derived-p
+ (buffer-local-value 'major-mode buffer)
+ (cdr condition)))
+ ((eq (car-safe condition) 'not)
+ (not (funcall match (cdr condition))))
+ ((eq (car-safe condition) 'or)
+ (funcall match (cdr condition)))
+ ((eq (car-safe condition) 'and)
+ (catch 'fail
+ (dolist (c conditions)
+ (unless (funcall match c)
+ (throw 'fail nil)))
+ t)))
+ (throw 'match t)))))))
+ (funcall match (list condition))))
+
+(defun match-buffers (condition &optional buffers arg)
+ "Return a list of buffers that match CONDITION.
+See `buffer-match' for details on CONDITION. By default all
+buffers are checked, this can be restricted by passing an
+optional argument BUFFERS, set to a list of buffers to check.
+ARG is passed to `buffer-match', for predicate conditions in
+CONDITION."
+ (let (bufs)
+ (dolist (buf (or buffers (buffer-list)))
+ (when (buffer-match condition (get-buffer buf) arg)
+ (push buf bufs)))
+ bufs))
+
;;; subr.el ends here
--
2.34.0
martin rudalics <rudalics@gmx.at> writes:
>>> Either way I would consider these functions useful and would have
>>> wanted
>>> to use them in my own code many times before. While difficult, it
>>> might
>>> also be useful for things like display-buffer-alist (the issue is that
>>> a function as a condition in display-buffer-alist has to accept two
>>> arguments, while the proposed patch only takes one).
>>
>> Hm... how would this be used with display-buffer-alist, then? (And
>> perhaps Martin has some comments; added to the CCs.)
>
> Either add an optional second argument to 'buffer-match' or add to
> 'display-buffer-alist' an entry that uses a function as condition that
> calls 'buffer-match' with the first argument and returns non-nil if
> 'buffer-match' reports a match. I see no issue here.
This seems to work, and updating window.el was also pretty trivial
(unless I have missed something):
>From fadea32d0dc74952ca70f8d98ced59616c0e3e1a Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk@posteo.net>
Date: Thu, 10 Mar 2022 10:59:52 +0100
Subject: [PATCH 2/2] * window.el (display-buffer-assq-regexp): Use
buffer-match
---
lisp/window.el | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/lisp/window.el b/lisp/window.el
index 54c9eee5f3..4225019920 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -7497,19 +7497,12 @@ display-buffer-fallback-action
(defun display-buffer-assq-regexp (buffer-name alist action)
"Retrieve ALIST entry corresponding to BUFFER-NAME.
This returns the cdr of the alist entry ALIST if either its key
-is a string that matches BUFFER-NAME, as reported by
-`string-match-p'; or if the key is a function that returns
-non-nil when called with three arguments: the ALIST key,
-BUFFER-NAME and ACTION. ACTION should have the form of the
-action argument passed to `display-buffer'."
+satisfied a BUFFER-NAME per `buffer-match'. ACTION should have
+the form of the action argument passed to `display-buffer'."
(catch 'match
(dolist (entry alist)
- (let ((key (car entry)))
- (when (or (and (stringp key)
- (string-match-p key buffer-name))
- (and (functionp key)
- (funcall key buffer-name action)))
- (throw 'match (cdr entry)))))))
+ (when (buffer-match (car entry) buffer-name action)
+ (throw 'match (cdr entry))))))
(defvar display-buffer--same-window-action
'(display-buffer-same-window
--
2.34.0
> martin
>
--
Philip Kaludercic
- bug#54296: Add buffer-matching functionality, Philip Kaludercic, 2022/03/07
- bug#54296: Add buffer-matching functionality, Lars Ingebrigtsen, 2022/03/09
- bug#54296: Add buffer-matching functionality, martin rudalics, 2022/03/09
- bug#54296: Add buffer-matching functionality,
Philip Kaludercic <=
- bug#54296: Add buffer-matching functionality, Eli Zaretskii, 2022/03/10
- bug#54296: Add buffer-matching functionality, Philip Kaludercic, 2022/03/10
- bug#54296: [External] : bug#54296: Add buffer-matching functionality, Drew Adams, 2022/03/10
- bug#54296: Add buffer-matching functionality, Eli Zaretskii, 2022/03/10
- bug#54296: Add buffer-matching functionality, Philip Kaludercic, 2022/03/11
- bug#54296: Add buffer-matching functionality, Eli Zaretskii, 2022/03/11
- bug#54296: Add buffer-matching functionality, Philip Kaludercic, 2022/03/13
- bug#54296: Add buffer-matching functionality, Eli Zaretskii, 2022/03/13
- bug#54296: Add buffer-matching functionality, Philip Kaludercic, 2022/03/14
- bug#54296: Add buffer-matching functionality, Eli Zaretskii, 2022/03/14