1

Q:  How can I use y-or-n-p -- instead of yes-or-no-p -- when calling kill-buffer for just the duration of a particular function?

In other words, I want the behavior of (fset 'yes-or-no-p 'y-or-n-p) but only for the duration of a particular function without any lasting effect.

CAVEAT:  I would like to please avoid using (fset 'yes-or-no-p 'y-or-n-p) at the outset and (fset 'yes-or-no-p 'yes-or-no-p) at the tail end of the function, just in case I decide to exit out of the function with a 'quit signal such as C-g, in which case the effect would become long-lasting rather than merely temporary.

Here is a test snippet to start with:

(let* (
    (filename "/private/tmp/foofile")
    (buf (get-buffer-create "*foo*")))
  (with-current-buffer buf
    (write-file filename)
    (insert "Every good boy deserves fudge."))
  (kill-buffer buf)
  (delete-file filename))
3

Advice kill-buffer:

(defun yes-or-no-p->-y-or-n-p (orig-fun &rest r)
  (cl-letf (((symbol-function 'yes-or-no-p) #'y-or-n-p))
    (apply orig-fun r)))

(advice-add 'kill-buffer :around #'yes-or-no-p->-y-or-n-p)

or advice yes-or-no-p

(defun yes-or-no-p@maybe-just-y-or-n-p (orig-fun prompt)
  (funcall
   (if (eq this-command 'kill-buffer)
       #'y-or-n-p
     #'yes-or-no-p)
   prompt))

(advice-add 'yes-or-no-p :around #'yes-or-no-p@maybe-just-y-or-n-p)
1
  • I modified your example to make a type of let-bound version for just the duration of the function -- thank you very much -- greatly appreciated: (cl-letf (((symbol-function 'yes-or-no-p) #'y-or-n-p)) (let* ((filename "/private/tmp/foofile") (buf (get-buffer-create "*foo*"))) (with-current-buffer buf (write-file filename) (insert "Every good boy deserves fudge.")) (kill-buffer buf) (delete-file filename))) – lawlist May 27 '16 at 5:15
3

just in case I decide to exit out of the function with a 'quit signal such as C-g, in which case the effect would become long-lasting rather than merely temporary.

This can be solved with unwind-protect. The following function always restores yes-or-no-p's definition at the end even if you quit in the middle of it:

(defun my/kill-buffer ()
  (interactive)
  (let ((yes-or-no-def (symbol-function 'yes-or-no-p)))
    (unwind-protect
        (progn
          (fset 'yes-or-no-p 'y-or-n-p)
          (call-interactively #'kill-buffer))
      (fset 'yes-or-no-p yes-or-no-def))))
1
  • Thank you for the alternative method of handling the issue -- greatly appreciated. – lawlist May 27 '16 at 20:16
3

I think the best way to handle this is to use cl-letf, like so:

(require 'cl-lib)
(cl-letf (((symbol-function 'yes-or-no-p) #'y-or-n-p))
  (let* ((filename "~/private/tmp/foofile")
         (buf (get-buffer-create "*foo*")))
    (with-current-buffer buf
      (write-file filename)
      (insert "Every good boy deserves fudge."))
    (kill-buffer buf)
    (delete-file filename)))

This is in principle similar to whacka's answer, but avoids requiring an explicit unwind-protect.

1
  • Your answer is the best (in my opinion), and I independently came up with the same solution once I understood how the answer by xuchunyang worked in conjunction with advice. Since I accepted the answer by xuchunyang at the outset, and since it contained the ingredients that immediately helped me resolve the issue, I don't feel good taking away the check-mark. However, please definitely leave your formal answer here as it is the best answer (in my opinion) and will help other people in the future when they find this thread with Google and what not Thank you. – lawlist May 27 '16 at 20:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.