Skip to main content
5 of 5
added 21 characters in body
NickD
  • 33.6k
  • 3
  • 30
  • 47

Expanding @lawlist's comment above, here's how to do it with cl-letf.

Let's start with a simple example: you have a function foo which calls a function bar with an argument (foo is the analog of the yas-new-snippet function in your case and bar is the analog of switch-to-buffer) and I want to change foo to call a different function baz instead (the analog of switch-to-buffer-other-window in your case), but from the "outside". So here are the three functions:

  (defun foo ()
    (bar "foo"))

  (defun bar (x)
    (message (format "%s:%s" "bar" x)))

  (defun baz (x)
    (message (format "%s:%s" "baz" x)))

  (foo) ---> "bar:foo"

Define a new function that (effectively) calls baz instead of bar - that's the analog of your my/yas-new-snippet function:

  (defun my/foo ()
    (cl-letf (((symbol-function 'bar) #'baz))
      (foo)))

Now when I call my-foo, it calls baz instead of bar:

(my-foo) ----> "baz:foo"

Note that we are not touching foo at all. We are just temporarily modifying the function cell of the bar symbol to hold the baz function instead. We then call foo which thinks it's calling bar, but we have pulled a switcheroo and it's (effectively) calling baz instead. And then we are out of scope of cl-letf and everything is back the way it was.

So in your case, you can do this:

(defun my/yas-new-snippet (&optional no-template)
  (interactive "P")
  (cl-letf (((symbol-function 'switch-to-buffer) #'switch-to-buffer-other-window))
     (yas-new-snippet no-template)))

I haven't actually tested this (I did test the toy example above), so I hope this works but I'm reasonably sure that it will. EDIT: As the OP points out in a comment, in order for the new function to be compatible with the old function, not only does it have to have the same signature, but it also has to have the same interactive specification, so that the optional argument is handled the same way.

Since we are using the old yas-new-snippet function inside the new function, you should not override the old function with the new one: that would cause an infinite descent. The new function calls the old functions so you need both functions to stick around in Emacs's memory. Instead of the overriding advice, just bind the new function to whatever key the old function was bound to.

Here's a question with more information and here is Malabarba's article that is linked from one of the answers to that question. I found both of these very illuminating.

NickD
  • 33.6k
  • 3
  • 30
  • 47