views:

161

answers:

2

How can I define an emacs command X that does something and then calls another emacs command Y and also copying the interactive interface of the command Y too?

I want to define an altenative version of query-replace with temporarilly toggled value of case-fold-search:

(defun alt-query-replace (a b c d e)
  (interactive)
  (let ((case-fold-search (not case-fold-search))
    (query-replace a b c d e)))

This doesn't work. When I call alt-query-replace, it says "wrong number of arguments". I want the interactive interface of alt-query-replace to be the same as query-replace. Do I need to inspect the source code of query-replace or is there a general approach?

+2  A: 

Use call-interactively:


(defun alt-query-replace ()
  (interactive)
  (let ((case-fold-search (not case-fold-search)))
    (call-interactively 'query-replace)))
remvee
Will that code magically pass all args through to `query-replace` as though it were called directly?
Ryan Thompson
+5  A: 

You may advise the original function, if you want to modify its behavior instead of calling a separate function.

From chapter 17.3 Around-Advice of the GNU Emacs Lisp Reference Manual:

Around-advice lets you “wrap” a Lisp expression “around” the original function definition.

 (defadvice foo (around foo-around)
   "Ignore case in `foo'."
   (let ((case-fold-search t))
     ad-do-it))

In your case, you can write:

(defadvice query-replace (around alt-query-replace (from-string to-string &optional delimited start end))
    (let ((case-fold-search (not case-fold-search)))
      ad-do-it))
(ad-activate 'query-replace)
Török Gábor
I've noticed folks having `ad-activate` done separately from the original advice, but you can have activate in the original line `around alt-query-replace (...) activate`.
Trey Jackson