GNU bug report logs - #59820
[PATCH] * nadvice/nadvice.el: support non-symbol (closure/lambda) advices (old Emacs)

Previous Next

Package: emacs;

Reported by: daanturo <daanturo <at> gmail.com>

Date: Sun, 4 Dec 2022 17:16:02 UTC

Severity: wishlist

Tags: moreinfo, patch

Full log


Message #36 received at 59820 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Daan Ro <daanturo <at> gmail.com>
Cc: "59820 <at> debbugs.gnu.org" <59820 <at> debbugs.gnu.org>,
 Stefan Kangas <stefankangas <at> gmail.com>
Subject: Re: bug#59820: [PATCH] * nadvice/nadvice.el: support non-symbol
 (closure/lambda) advices (old Emacs)
Date: Wed, 11 Oct 2023 02:50:39 -0400
>> Daan, is there a specific use-case that motivates you to want to pass an
>> anonymous lambda to this compatibility library?
>
> I think lambdas are useful for temporary advices that doesn't need to be
> attached to their symbols forever.

That doesn't explain why you need to use them with the forward compatibility
library.

> For example, when pressing "C-<backspace>", or some other editing operations, I
> don't want it to modify the kill ring and the desktop's clipboard.
>
> ```elisp
> (defun my-delete-instead-of-kill-when-interactive-a (func &rest args)
> (if (called-interactively-p 'any)
> (let* ((func (lambda (beg end &rest _) (delete-region beg end))))
> (advice-add #'kill-region :override func)
> (unwind-protect
> (apply func args)
> (advice-remove #'kill-region func)))
> (apply func args)))
> (advice-add #'backward-kill-word :around #'my-delete-instead-of-kill-when-interactive-a)
> (advice-add #'subword-backward-kill :around #'my-delete-instead-of-kill-when-interactive-a)

FWIW, as a general rule I prefer to avoid such transient advice and
prefer to use a permanent advice together with an "enabling" variable:

    (defvar my-dont-kill nil)
    
    (defun my-obey-dont-kill (func beg end &rest args)
      "Obey `my-dont-kill."
      (if my-dont-kill
          (delete-region beg end)
        (apply func beg end args)))
    (advice-add 'kill-region :around #'my-obey-dont-kill)
    
    (defun my-delete-instead-of-kill-when-interactive-a (func &rest args)
      (if (called-interactively-p 'any)
          (let ((my-dont-kill t))
            (apply func args))
        (apply func args)))
    
    (advice-add #'backward-kill-word :around #'my-delete-instead-of-kill-when-interactive-a)
    (advice-add #'subword-backward-kill :around #'my-delete-instead-of-kill-when-interactive-a)

The main advantage, for me, is that `C-h o kill-region` will tell me
that the function has an advice (and I can click on it to jump to its
definition, ...) so I'll be less puzzled when it doesn't behave in "the
normal way".  Sometimes it also comes with the advantage that I can make
the variable buffer-local, contrary to the advice itself.

Of course, in this specific instance, there's another way to get "the
same" result:

    (defun my-delete-instead-of-kill-when-interactive-a (func &rest args)
      (if (called-interactively-p 'any)
          (let ((kill-ring nil)
                (kill-ring-yank-pointer nil)
                (interprogram-cut-function nil))
            (apply func args))
        (apply func args)))
    
    (advice-add #'backward-kill-word :around #'my-delete-instead-of-kill-when-interactive-a)
    (advice-add #'subword-backward-kill :around #'my-delete-instead-of-kill-when-interactive-a)

:-)


        Stefan





This bug report was last modified 1 year and 251 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.