Define an emacs command that calls another emacs command (preserving interactive stuff) - emacs

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?

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)

Use call-interactively:
(defun alt-query-replace ()
(interactive)
(let ((case-fold-search (not case-fold-search)))
(call-interactively 'query-replace)))

Related

Emacs lisp, How `interactive' reads buffer?

For example there is a function:
(defun testb (buf)
(interactive "bTest: ")
buf)
The question is how emacs internally reads a buffer for such interactive form?
Looks like it doesn't use read-buffer(or it calls the read-buffer as a C function(and doesn't look at symbol-function)?).
(flet ((read-buffer (&rest args) (current-buffer)))
(call-interactively #'testb))
It uses Lisp function read-buffer. The interactive spec you show is equivalent to this one:
(interactive (list (read-buffer "Test: " nil t)))
See the Elisp manual, node Using Interactive.
I guess you're referring to the fact that you got this error, or similar, which you get when you try to use flet on a built-in function. And yes, read-buffer is a subr, i.e., implemented in C. (symbol-function 'read-buffer) returns the built-in function #<subr read-buffer>.
Use ‘labels’, not ‘flet’, to rebind macro names

How to rewrite a native defun in Emacs?

Premises:
My Emacs has a small bug (cannot go up from inside of "") in one of its original defun (up-list). This defun is vital to one of my frequently used command (backward-up-list) which is bound to C-M-u.
Therefore, I wanted to achieve below objectives:
Write a NEW defun named my-up-list which has the bug fix;
RE-write the native defun backward-up-list to call the above new defun (instead of the native buggy up-list). (By RE-writing under the same defun name, I intend to preserve its original convenient key bindings.)
By following the Emacs Tutorial Here, I implemented it as below:
I wrote a new defun my-up-list inside .emacs file; (see code in the end)
I rewrote the defun backward-up-list under a the same name inside .emacs file; (see code in the end).
However, when wI tested it out by trying it in "|" (| is the cursor position), I encounter below error:
backward-up-list: Wrong number of arguments: (lambda nil (interactive) (let ((s (syntax-ppss))) (if (nth 3 s) (progn (goto-char (nth 8 s))))) (condition-case nil (progn (up-list)) (error nil))), 1 [2 times]
Question:
Is it the correct way to re-write a native defun just by putting the
new implementation with the same name in .emacs file?
What may went wrong in my code?
Reference:
(The my-up-list is from here)
;; I only changed "up-list" to "my-up-list" -modeller
(defun backward-up-list (&optional arg)
"Move backward out of one level of parentheses.
With ARG, do this that many times.
A negative argument means move forward but still to a less deep spot.
This command assumes point is not in a string or comment."
(interactive "^p")
(my-up-list (- (or arg 1))))
;; copied from solution to another question - modeller
(defun my-up-list ()
(interactive)
(let ((s (syntax-ppss)))
(when (nth 3 s)
(goto-char (nth 8 s))))
(ignore-errors (up-list)))
I guess your my-up-list function needs to accept the same arguments as the original up-list, and call up-list with them?
The simplest way to do this is with the "advice" system. This provides some simple ways to wrap and extend existing functions. There's a whole section in the elisp manual explaining how to do it.

How to convert kbd-macro to real command in Emacs? [duplicate]

This question already has answers here:
Convert Emacs macro into Elisp
(2 answers)
Closed 8 years ago.
It seems kbd-macro only records keys I pushed. But I want to record real commands(that is tied with key I pushed) and save these as function.
So my question is something like following.
How to record commands I used as executable format?
How to convert key sequence to command sequence?
How to convert my-kbd-macro to command sequence function?
Example:
F3(M-x kmacro-start-macro)
C-f
F4(M-x kmacro-end-or-call-macro)
M-x name-last-kbd-macro my-kbd-macro
M-x insert-kbd-macro my-kbd-macro
Output:
(fset 'my-kbd-macro
"\C-f")
My desired output is like following:
(defun my-kbd-macro ()
(interactive)
(forward-char)
)
Thanks.
Here's a simplistic implementation of what you want.
It will work only for simple commands that don't want input, like forward-char.
To do any more in a fully automated way seems hard / not feasible. That's why this functionality
isn't in place already, I guess.
I've added these functions to
my macro package that allows multiple anonymous macros
You can get it from github or from MELPA as centimacro.
To use it, just do your F3 ... F4 thing, and
M-x last-macro-to-defun from e.g. *scratch*.
(defun macro->defun (str)
"Convert macro representation STR to an Elisp string."
(let ((i 0)
(j 1)
(n (length str))
forms s f)
(while (< i n)
(setq s (substring str i j))
(setq f (key-binding s))
(if (keymapp f)
(incf j)
(push (list f) forms)
(setq i j)
(setq j (1+ i))))
(with-temp-buffer
(emacs-lisp-mode)
(insert
"(defun foo ()\n (interactive)")
(mapc (lambda (f)
(newline-and-indent)
(insert (prin1-to-string f)))
(nreverse forms))
(insert ")")
(buffer-string))))
(defun last-macro-to-defun ()
"Insert last macro as defun at point."
(interactive)
(insert (macro->defun last-kbd-macro)))
Do bear in mind that when writing a function there are frequently better ways to do things than to exactly mimic the interactive bindings, so while not necessary, some refactoring is likely going to be beneficial if you start out with just the commands used when the macro runs.
Anyhow, I can think of a couple of useful tools to assist with working this out manually:
Firstly, if you edit a keyboard macro, the macro editor comments each key with the function it is bound to (n.b. for the buffer in which you invoke the editor! -- if you are switching buffers while your macro executes, I would suggest checking the editor for each buffer).
Obviously you can obtain the same information in other ways, but the macro editor gives you the whole list, which could be convenient.
The other helper is repeat-complex-command bound to C-xM-:, which gives you the resulting elisp form from certain types of interactive function call ("a complex command is one which used the minibuffer"). My favourite example of this is align-regexp, as it's a case where the user's interactive arguments are further manipulated, which isn't necessarily obvious. e.g.:
M-x align-regexp RET = RET C-xM-: might tell you:
(align-regexp 1 191 "\\(\\s-*\\)=" 1 1 nil)

Programatically insert text into command that normally blocks event loop

I'd like to implement a command that types the first few characters into an existing command and lets me type the rest.
For example, a variant of icicle-execute-extended-command that starts with "icicle-" already entered.
I have tried:
keyboard macros
fail (even on simple things like M-x i c i c l e s) for no apparent reason.
functions
calling icicle-execute-extended-command block the command sequence
How would I go about doing this in a generalized manner?
Nice question.
Here's something generic you can try:
(defun no-mondays ()
(interactive)
(minibuffer-with-setup-hook
(lambda()
(insert "monday"))
(call-interactively 'query-replace)))
And here's a refactoring:
(defun with-initial-minibuffer (str fun)
`(lambda ()
(interactive)
(minibuffer-with-setup-hook
(lambda ()
(insert ,str))
(call-interactively ',fun))))
(defalias 'no-weekends
(with-initial-minibuffer
"\\(?:satur\\|sun\\)day"
'query-replace-regexp))
If you are calling completing-read yourself in your command definition, then just pass the text to insert as the INITIAL-INPUT argument. That's what it's for.
If you use icicle-define-command or icicle-define-file-command (so that your command will be a multi-command), then same thing: pass the INITIAL-INPUT arg.
If you use such a macro, be sure to put something like this in the file that defines the command, so the macro definition is available a byte-compilation time:
(eval-when-compile
(or (condition-case nil
(load-library "icicles-mac") ; Use load-library to ensure latest .elc.
(error nil))
(require 'icicles-mac)))

Emacs custom command line argument

From the documentation I can see I can access command line arguments (command-line-args).
I'd like to add my own arguments but Emacs complains at start up that it doesn't recognize them.
E.g.
emacs -my_argument
I get:
command-line-1: Unknown option `-my_argument'
What's a proper way to define my custom arguments and provide information to my Emacs session?
Is there a way to pop an argument from a command line?
Add something like this to your ~/.emacs, ~/.emacs.el, or ~/.emacs.d/init.el file:
(defun my-argument-fn (switch)
(message "i was passed -my_argument"))
(add-to-list 'command-switch-alist '("-my_argument" . my-argument-fn))
Then you can execute emacs -my_argument and it should print i was passed -my_argument to the minibuffer. You can find more information in the GNU elisp reference.
As stated in another post you can add your custom switches to command-switch-alist and emacs will call the handler function for any matching switch passed in on the command line. However, this operation is done after your .emacs file has been evaluated. This is fine for most cases but you may wish for a command line argument to alter the execution path or behaviour of your .emacs evaluation; I often do this to enable/disable configuration chunks (mainly for debugging).
To achieve this you can read command-line-args and check for your switch manually and then delete it from the list, this will stop emacs complaining about an unknown argument.
(setq my-switch-found (member "-myswitch" command-line-args))
(setq command-line-args (delete "-myswitch" command-line-args))
Which can alter your .emacs evaluation like so:
(unless my-switch-found
(message "Didn't find inhibit switch, loading some config.")
...)
And you could build this into a single step:
;; This was written in SO text-box, not been tested.
(defun found-custom-arg (switch)
(let ((found-switch (member switch command-line-args)))
(setq command-line-args (delete switch command-line-args))
found-switch))
(unless (found-custom-arg "-myswitch")
(message "Loading config...")
...)
For those who are interested, here is a code snip to show how to process custom arguments in Emacs lisp. In this case, I am processing an argument --suffix / -S to variable _suffix.
I pulled the idea from a BSD-Lite Script Emacs script.
(setq _suffix nil)
;; Process cli args
(while command-line-args-left
(setq k (car command-line-args-left))
(setq command-line-args-left (cdr command-line-args-left))
(setq command-line-args (delete k command-line-args))
(cond
(or (string-equal k "--cs-suffix")
(string-equal k "-S"))
(setq _suffix (intern (car command-line-args-left)))
(setq command-line-args-left (cdr command-line-args-left))
(setq command-line-args (delete _suffix command-line-args))
)))
This will roll through command-line-args-left and remove them all from command-line-args which will prevent Emacs from complaining.