Emacs I want to call execute-kbd-macro from a lisp function - emacs

I want to call a keyboard macro from a Lisp function. I hope to layer in some custom error handling.
mykey is a keyboard macro stored in a text file in (fset ...) format.
I loaded it with load-file and it works fine when called with M-x mykey.
When I execute this function and plug in mykey I get only the name of the key displayed in current buffer, not it's execution. Is there a step I'm missing?
(defun gn-batch-search (key-name)
"Execute a keyboard macro that has already been loaded."
(interactive "sName of macro key:")
(execute-kbd-macro key-name))

Try
(defun gn-batch-search (key-name)
"Execute a keyboard macro that has already been loaded."
(interactive "sName of macro key:")
(execute-kbd-macro (intern key-name)))
The issue you bumped into is that the "sName of macro key:" interactive spec prompts the user and returns a string, and you want to run the command whose name is described by this string. That explains why it didn't do what you wanted and why you need intern.
As for why it did what it did: a keyboard macro is represented as a vector of events, where events can be things like mouse clicks or key presses. And as it turns out, a string is considered as a kind of vector (a vector characters) and a character is also an event (it represents the event that is sent when you press that character on your keyboard), so the string "hi" is a valid keyboard macro which represents the act of pressing h followed by pressing i, so when you run this macro, it will (usually) end up inserting "itself" in the current buffer (except in special buffers like dired, *Help*, ... where h and i are bound to other commands).
Also, rather than execute-kbd-macro you can use command-execute which will work with "any" command, whether it's defined as a keyboard macro or a normal function.

Related

Binding a key to a command and automatically using the (interactive) default values for its interactive arguments

I would like F5 to switch to the most recently used buffer. This functionality is accomplished by running M-x icicle-buffer and then hitting enter to not specify the buffer I want to switch to -- (the default behavior of icicle is to switch to the most recent buffer.)
I have tried editing my .emacs thus:
(defun most-recent-buffer-please ()
(interactive)
(icicle-buffer " "))
(global-set-key [(f5)] 'most-recent-buffer-please)
but when I evaluate this lisp, and then hit F5, I get an error that starts with Wrong number of arguments followed by a lot of gibberish characters. What am I doing wrong?
A function can have mandatory and/or optional arguments, or no arguments at all. When writing elisp, it is usually a good idea to find out what arguments are available for certain functions by typing M-x describe-function RET [name of the function] RET. Drew (the author of Icicles) has indicated in his comment underneath the original question that the function icicle-buffer is not designed to be used in conjunction with any arguments -- therefore, adding " " causes the error message that the original poster experienced.
To switch to the previous buffer, Emacs already has a built-in function called previous-buffer. Since the original poster has indicated a preference for the f5 key, the following is an example of how to configure that keyboard shortcut so that it triggers previous-buffer -- brackets are sufficient and the parentheses used by the original poster around f5 can be omitted:
(global-set-key [f5] 'previous-buffer)

Create an Emacs semi-interactive macro

I would like to create a quick Emacs macro (with C-x () which takes some user input from the minibuffer each time it's executed.
The usage scenario is this:
You have a complex text to change where the regexp query substitution just doesn't cut it, and you want to create a macro which:
does some complex changes in the current line of text
position the cursor at a specific point
asks the user for some text in the minibuffer
possibly executes some other action, then exits
I have tried using
M-x eval-expression
and
(insert-text (read-from-minibuffer ">"))
but after creation, the macro obviously (in retrospect... :) ) repeats the same keystrokes and therefore doesn't give me a chance to insert some new text.
Can this be done?
Thank you for the help!
Use kbd-macro-query, normally bound to C-x q. Specifically, you should use C-u C-x q, which enters a recursive edit mode when you're defining the query and lets you enter whatever text you like to a minibuffer prompt, but note that the text you enter here will not be part of the keyboard macro. While you're defining the macro, you'll need to hit <enter> once to end the recursive edit and then hit it again to send the text to the minibuffer prompt so you can continue defining the macro. Once you finishing defining the macro, you can then execute it and it will stop at the point you called kbd-macro-query, prompt for the text, and then hitting <enter> will work as expected.

"Press" a key from inside an interactive function

I need to programmatically press a key from inside of an interactive function. Here's an outline of what I have so far:
(defun answer-to-life-the-universe-and-everything ()
(interactive)
(insert "(* 6 7)")
;; Need to automagically press the RETURN key here
)
My use case: in a REPL buffer, I need frequently execute a long command. I can use the above code to create an interactive function that inserts the required string, but I still have to hit RETURN manually for the REPL to read it. Terminating the string with \n or \r won't do what I need it to.
How can I do this inside of my interactive function definition?
A simpler way to do this is to find out what command the enter key is bound to in the REPL and then call that command in your interactive function. (To find out, go to the REPL buffer and hit C-h k <return>.)
For example, enter is bound to inferior-ess-send-input when using the R REPL via ess, so this command inserts the string and "hits enter":
(defun try-this ()
(interactive)
(insert "print(\"hi\")")
(inferior-ess-send-input))

How can I make emacs keyboard macros work properly when pasting the results of clojure evaluation?

There's a phenomenally useful feature of emacs lisp where you can evaluate the result of an expression and paste the result directly into a buffer.
Say I want to check addition works. Then I type:
(* 3 2)
and I define the keyboard macro:
(setq last-kbd-macro
[down ?\( ?i ?s ?= ? ?\C-\M-f ? ?\C-u ?\C-x ?\C-e ?\) home])
If I then place point above the expression, and press F4 to execute the macro, the expression turns into:
(is= (* 3 2) 6)
Which makes a nice regression test.
Unfortunately the same keyboard macro executed in a clojure/nrepl buffer results in:
(* 8 9)(is= )
and an error from clojure about not being able to resolve the symbol is=
So I think that something weird is happening to the ordering of things, and the macro is trying to evaluate the wrong thing.
Can anyone get this to work with clojure? (And in fact solve the general problem so that arbitrary keyboard macros work OK with C-u C-x C-e like they do with emacs lisp)
Edit since people seem to be misunderstanding:
Doing the keypresses by hand works fine in either an elisp or a clojure buffer. In one C-u C-x C-e evals with emacs lisp and in the other evals in the external clojure process.
The problem comes when trying to run a keyboard macro (recorded in a clojure buffer) which contains C-u C-x C-e
Running the macro in the clojure buffer, things get re-ordered somehow. It looks like the macro may be carrying on executing even though the eval-paste has not completed yet.
I was wondering if there was a way of forcing the keyboard macro (or corresponding function) to execute in the same order as it would by hand.
I'm quite happy to turn the keyboard macro into a proper elisp function if necessary.
Keyboard macros are a quick and dirty way to repeat a certain sequence of actions. They are very fragile because they remember the keys pressed, not the functions they invoke, so they may produce wildly different results depending on the buffer they are invoked in, the current command history, window configuration and what not.
In your case, chances are that one of the keys in the macro invoke a different command in the clojure/nrepl buffer than in the buffer in which you tested the macro. You really need to define the macro in the buffer in which it will be used.
If you are going to re-use the macro, I suggest that you write a emacs
lisp function which does what you want instead of messing with macros.
You might find the output of (format-kbd-macro nil t) useful, but note that you should not use the commands like eval-last-sexp in your function, use a lower-level function which returns the evaluation result instead of inserting it into the current buffer.
Addressing a problem you haven't had yet, but will soon: don't forget to insert a ' character before the result of evaluating the expression: you want (= (cons 1 nil) '(1)), not (= (cons 1 nil) (1)).

Emacs Lisp: How to, an interactive buffer with REPL?

Imagine the dunnet.el game, the eliza doctor or the IELM mode...; This is, evaluating answers and prompting new questions on the main buffer, then making some actions according to their elisp rules.
I would to create something like an interactive assistant, BUT NOT prompting from minibuffer as (interactive) does (not doing M-x)... I need a kind of REPL loop. So the question i how to get interaction on the working buffer (the main screen), like any text conversational/adventure, but for call my defun'ed functions on this way.
So i need a basic elisp skeleton, to make a custom REPL. The target is to make an assistant with a natural language, then parsing the anwsers, and making some actions according the rules.
Thank you for your time,
Steve,
Check out ielm, which is an elisp repl included with emacs.
Depending on what can go on in your buffer, can you just give it a major mode with an appropriate re-binding of return? (This answer vaguely inspired by Lisp-Interaction-Mode's C-j)
You should bind all keys that use for moving in buffer like C-p C-n, Up Down Arrows/ page up/down just bind them to (lambda ()). change function for C-b and C-f (Left Right Arrows) if cursor position is in beginning or end of the line. And bind Return key to function that read current line from end to optional prompt (you can use Regex to remove the prompt) do whatever you want with that string, and then go to the next line in the buffer and print your result.