0

I apologize for this question, for which I know an elementary answer exists that I can't find for the life of me. I would simply like to define a command that executes several functions sequentially. Concretely I want to make a command kill-append that does first append-next-kill, then kills the marked region. I've written the following:

(defun kill-append ()
  (interactive)
  (append-next-kill)
  (kill-region (mark) (point)))

but when I execute it, I get an error message

kill-region: Wrong number of arguments: (lambda nil (interactive) (append-next-kill) (kill-region (mark) (point))), 2

which I think comes from the fact that defun expects its body to consist of one expression, not a list. I know there is an easy command that allows one to do this, but when searching I only encountered solutions for specific cases, such as using advice (which doesn't fit here since I don't want to modify append-next-kill, only define a new function from it) or macros (which gives me an error message because I'm applying the Meta-modifier using event-apply-meta-modifier which it doesn't seem to like for some reason). I've seen a general method to do this a while ago but can't find it again and it was an unituitive command name that I don't remember. Now I would really like to know the general solution for this so I have it in my code and can look it up whenever I need it again.

2

1 Answer 1

2

There is nothing wrong with your defun, except that when you evaluate it, it would clobber the existing function kill-append. The trouble is that kill-append is called by kill-region, but it is called with two arguments (because it thinks it's calling the original kill-append which does take two arguments) - since the new kill-append takes no arguments, Emacs complains loudly.

Note that defun allows a sequence of forms in its body, so there is no need for any grouping (which you would do with progn, but there is no need to do that here).

So the problem is that you clobber an existing function. The solution is to be careful with names: first check if there is something by that name already defined, by using C-h f kill-append, and if there is, use a different name, since you never know whether some other function will be calling kill-append expecting to find the old function and getting the new one instead. A useful convention is to name your function with a prefix that is unlikely to be used by anybody else: e.g. in this case, some people would call the new function my/kill-append or my-kill-append - my preference is to use part of my name as a prefix with a / as separator, e.g. ndk/kill-append or, in your case, apr/kill-append perhaps.

So the following should work:

(defun apr/kill-append ()
  (interactive)
  (append-next-kill)
  (kill-region (mark) (point)))

This name does not conflict with an existing name (I checked with C-h f apr/TAB to make sure there is no function with an apr/ prefix in its name), so it does not interfere with kill-region's ability to call the old function with the proper number of arguments.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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