1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 14:30:50 -08:00

Autoinsert: Allow condition to be a function

Currently a condition can only be a regexp or a major-mode symbol but
there's no real reason to not allow any predicate as a condition.
* doc/misc/autotype.texi: Document the new condition type in
'auto-insert-alist'.
* etc/NEWS: Announce the new condition type in 'auto-insert-alist'.
* lisp/autoinsert.el (auto-insert-alist): Add the new condition type to
the variable documentation.
(auto-insert): Change the way the condition is matched to allow for
custom predicates.
* test/lisp/autoinsert-tests.el
(autoinsert-tests-auto-insert-lambda/-nil): Add two tests for
lambdas (nil and t cases)
(autoinsert-tests-auto-insert-predicate/-nil): Add two tests for named
predicates (nil and t cases) (Bug#79178)
This commit is contained in:
mattiasdrp 2025-08-08 15:16:24 +02:00 committed by Eli Zaretskii
parent 6ffa926f90
commit bd1362b686
4 changed files with 72 additions and 12 deletions

View file

@ -273,13 +273,15 @@ empty file is visited. This is accomplished by putting
@vindex auto-insert-alist
What gets inserted, if anything, is determined by the variable
@code{auto-insert-alist}. The @sc{car} of each element of this list
is either a mode name, making the element applicable when a buffer is
in that mode, or a string, which is a regexp matched against a
buffer's file name (the latter enables you to distinguish between
different kinds of files that have the same mode in Emacs). The
@sc{car} of an element may also be a cons cell, consisting of mode
name or regexp, as above, and an additional descriptive string.
@code{auto-insert-alist}. The @sc{car} of each element of this list is
either a mode name, making the element applicable when a buffer is in
that mode, or a string, which is a regexp matched against a buffer's
file name (the latter enables you to distinguish between different kinds
of files that have the same mode in Emacs). It can also be a predicate
declared through a plist of the form @code{(predicate @var{function})}.
@var{function} should be a predicate function of no arguments. The
@sc{car} of an element may also be a cons cell, consisting of mode name
or regexp, as above, and an additional descriptive string.
When a matching element is found, the @sc{cdr} says what to do. It may
be a string, which is a file name, whose contents are to be inserted, if

View file

@ -700,6 +700,15 @@ you could already use 'C-u C-x C-n' to clear the goal column.
* Changes in Specialized Modes and Packages in Emacs 31.1
** Autoinsert
+++
*** New condition for 'auto-insert-alist'.
'auto-insert-alist' now also allows to have a predicate taking no
argument as conditions. These types of conditions should be declared
with '(predicate FUNCTION)'. This allows to trigger 'auto-insert'
with finer grained control.
** Register
*** The "*Register Preview*" buffer shows only suitable registers.

View file

@ -325,6 +325,9 @@ The document was typeset with
Elements look like (CONDITION . ACTION) or ((CONDITION . DESCRIPTION) . ACTION).
CONDITION may be a regexp that must match the new file's name, or it may be
a symbol that must match the major mode for this element to apply.
CONDITION can also be a custom predicate of no arguments declared with
'(predicate FUNCTION)'. Emacs will insert the text if the predicate
function returns non-nil.
Only the first matching element is effective.
Optional DESCRIPTION is a string for filling `auto-insert-prompt'.
ACTION may be a skeleton to insert (see `skeleton-insert'), an absolute
@ -368,12 +371,24 @@ Matches the visited file name against the elements of `auto-insert-alist'."
(pcase-lambda (`(,cond . ,action))
(if (atom cond)
(setq desc cond)
;; if `cond' is a predicate, don't split it but set `desc' to a custom string
(if (and (consp cond) (equal (car cond) 'predicate))
(setq desc "predicate")
(setq desc (cdr cond)
cond (car cond)))
(when (if (symbolp cond)
(derived-mode-p cond)
cond (car cond))))
(when (cond
;; `cond' should be a major-mode variable
((symbolp cond)
(derived-mode-p cond))
;; `cond' should be a predicate that takes no argument
((and (consp cond) (equal (car cond) 'predicate))
(funcall (cadr cond)))
;; cond should be a regexp
(t
(and buffer-file-name
(string-match cond buffer-file-name)))
(string-match cond buffer-file-name))))
action))
auto-insert-alist)))
(goto-char 1)

View file

@ -76,6 +76,40 @@
(auto-insert)
(should (equal (buffer-string) "2nd")))))
(ert-deftest autoinsert-tests-auto-insert-lambda ()
(let ((auto-insert-alist
'(((predicate (lambda () t)) . (lambda () (insert "foo")))))
(auto-insert-query nil))
(with-temp-buffer
(auto-insert)
(should (equal (buffer-string) "foo")))))
(ert-deftest autoinsert-tests-auto-insert-predicate ()
(defun predicate () t)
(let ((auto-insert-alist
'(((predicate predicate) . (lambda () (insert "foo")))))
(auto-insert-query nil))
(with-temp-buffer
(auto-insert)
(should (equal (buffer-string) "foo")))))
(ert-deftest autoinsert-tests-auto-insert-lambda-nil ()
(let ((auto-insert-alist
'(((predicate (lambda () nil)) . (lambda () (insert "foo")))))
(auto-insert-query nil))
(with-temp-buffer
(auto-insert)
(should (equal (buffer-string) "")))))
(ert-deftest autoinsert-tests-auto-insert-predicate-nil ()
(defun predicate () nil)
(let ((auto-insert-alist
'(((predicate predicate) . (lambda () (insert "foo")))))
(auto-insert-query nil))
(with-temp-buffer
(auto-insert)
(should (equal (buffer-string) "")))))
(ert-deftest autoinsert-tests-define-auto-insert-before ()
(let ((auto-insert-alist
(list (cons 'text-mode (lambda () (insert "foo")))))