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)
Related
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.
I have a defun that conveniently adds / removes parentheses to marked expressions. (see code in the end)
As a neophyte in emacs Lisp, I only know how to make simple key-bindings without argument.
However, I believe the defun would be made more convenient if its key-binding could take two optional arguments to specify whether to add / remove (), [], or {}
My current (simple) key-binding is as below, is there a trivial way to make it argument-taking as described?
(global-set-key (kbd "C-M-( )") 'end-of-statement)
Appreciate any advice or direction tips!
(Code: by Istvan Chung)
(defun surround-with-parens ()
(interactive)
(save-excursion
(goto-char (region-beginning))
(insert "("))
(goto-char (region-end))
(insert ")"))
(defun delete-surrounded-parens ()
(interactive)
(let ((beginning (region-beginning))
(end (region-end)))
(cond ((not (eq (char-after beginning) ?\())
(error "Character at region-begin is not an open-parenthesis"))
((not (eq (char-before end) ?\)))
(error "Character at region-end is not a close-parenthesis"))
((save-excursion
(goto-char beginning)
(forward-sexp)
(not (eq (point) end)))
(error "Those parentheses are not matched"))
(t (save-excursion
(goto-char end)
(delete-backward-char 1)
(goto-char beginning)
(delete-char 1))))))
I assume the question is for surround-with-parens, as delete-surrounded-parens is probably better off just guessing the parentheses used by itself.
I also assume that you are doing this for practice more so than for actually solving the problem. If you enable electric-pair-mode in recent Emacsen, configured pairs will wrap around any active region as your command does. But it's a good mid-level emacs lisp exercise.
As the comments noted, you have multiple options.
Command Argument
A command can take arguments, as you asked for. Commands are no different from other lisp functions, except that they have an interactive spec. The interactive spec tells Emacs how to run the command when it is invoked with a key or via M-x.
Simple (interactive) will pass no arguments to the function. (interactive "r") will pass the beginning and end of the region as two arguments. Etc. You can read about the different options in C-h f interactive. You can even write lisp code to calculate the arguments there.
You could use (interactive "cWrap with: "). This would prompt the user for a key, and pass the key to your function. For example, if the user types (, your function receives 40 as the argument, the character code for the opening parenthesis. ?\( is 40 as well, and (make-string 1 40) returns "(". You'll have to create a map to figure out the closing parenthesis.
The drawback here is that you need to press two keys: The first to invoke the command, and then a key to specify the parenthesis to use.
Multiple keys
You can also bind your command to different keys – for example, C-M-( and C-M-[. You can then use this-single-command-keys to get something that specifies the last key event. Sadly, this can be somewhat tricky to translate back to a key sequence. E.g. C-M-( returns [201326632].
Multiple commands
You could also just define one command per parenthesis type, all of which simply call a common function with arguments, and bind those commands to keys.
post-self-insert-hook
Finally, you can use the same method as electric-indent-mode does: Add a function to post-self-insert-hook and decide based on char-before what you want to do.
Currently i am using the load-history variable to find the file from which a feature came from.
suppose to find the file the feature gnus came from.
I execute the following code in scratch buffer which prints filename and the symbols in separate lines consecutively.
(dolist (var load-history)
(princ (format "%s\n" (car var)))
(princ (format "\t%s\n" (cdr var))))
and then search for "(provide . gnus)" and then move the point to the start of line(Ctrl+A).
The file name in the previous line is the file from which the feature came from.
Is there any thing wrong with this method, or does a better method exist.
I don't really know what you're trying to do with this, but here are some notes.
Your method is fine. Any way to hack your own solution to a problem is good in my book.
#Tom is correct that you shouldn't really need to do this, because the problem is already solved for you by the help system. i.e. C-h f
But that's not so interesting. Let's say you really want an automatic, more elegant solution. You want a function -- locate-feature with this signature:
(defun locate-feature (feature)
"Return file-name as string where `feature' was provided"
...)
Method 1 load-history approach
I'll just describe the steps I took to solve this:
You've already got the most important part -- find the variable with the information you need.
I notice immediately that this variable has a lot of data. If I insert it into a buffer as a single line, Emacs will not be happy, because it's notoriously bad at handling long lines. I know that the prett-print package will be able to format this data nicely. So I open up my *scratch* buffer and run
M-: (insert (pp-to-string load-history))
I can now see the data structure I'm dealing with. It seems to be (in pseudo code):
((file-name
((defun|t|provide . symbol)|symbol)*)
...)
Now I just write the function
(eval-when-compile (require 'cl))
(defun locate-feature (feature)
"Return file name as string where `feature' was provided"
(interactive "Sfeature: ")
(dolist (file-info load-history)
(mapc (lambda (element)
(when (and (consp element)
(eq (car element) 'provide)
(eq (cdr element) feature))
(when (called-interactively-p 'any)
(message "%s defined in %s" feature (car file-info)))
(return (car file-info))))
(cdr file-info))))
The code here is pretty straight forward. Ask Emacs about the functions you don't understand.
Method 2 help approach
Method one works for features. But what if by I want to know where any
available function is defined? Not just features.
C-h f already tells me that, but I want the file-name in a string, not all of the verbose help text. I want this:
(defun locate-function (func)
"Return file-name as string where `func' was defined or will be autoloaded"
...)
Here we go.
C-h f is my starting point, but I really want to read the code that defines describe-function. I do this:
C-h k C-h f C-x o tab enter
Now I'm in help-fns.el at the definition of describe-function. I want to work only with this function definition. So narrowing is in order:
C-x n d
I have a hunch that the interesting command will have "find" or "locate" in its name, so I use occur to search for interesting lines:
M-s o find\|locate
No matches. Hmmm. Not a lot of lines in this defun. describe-function-1 seems to be doing the real work, so we try that.
I can visit the definition of describe-function-1 via C-h f. But I already have the file open. imenu is available now:
C-x n w M-x imenu desc*1 tab enter
Narrow and search again:
C-x n d M-s o up enter
I see find-lisp-object-file-name which looks promising.
After reading C-h f find-lisp-object-file-name I come up with:
(defun locate-function (func)
"Return file-name as string where `func' was defined or will be autoloaded"
(interactive "Ccommand: ")
(let ((res (find-lisp-object-file-name func (symbol-function func))))
(when (called-interactively-p 'any)
(message "%s defined in %s" func res))
res))
Now go have some fun exploring Emacs.
There is locate-library for that.
Try...
M-: (locate-library "my-feature")
eg: (locate-library "gnus")
Just use symbol-file. It scan load-history which has format:
Each entry has the form `(provide . FEATURE)',
`(require . FEATURE)', `(defun . FUNCTION)', `(autoload . SYMBOL)',
`(defface . SYMBOL)', or `(t . SYMBOL)'. Entries like `(t . SYMBOL)'
may precede a `(defun . FUNCTION)' entry, and means that SYMBOL was an
autoload before this file redefined it as a function. In addition,
entries may also be single symbols, which means that SYMBOL was
defined by `defvar' or `defconst'.
So call it as:
(symbol-file 'scheme 'provide) ; Who provide feature.
(symbol-file 'nxml-mode-hook 'defvar) ; Where variable defined.
(symbol-file 'message-send 'defun) ; Where function defined.
(symbol-file 'scheme) ; Look for symbol despite its type.
There is nothing wrong with it, but why is it simpler than getting help on a key or a function? If you use a gnus command for example and you want to know where it comes from then you can use C-h k and it tells you from which elisp file its definition comes.
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)))
I've been using Emacs for a couple months now, and I want to get started in elisp programming. Specifically, I'd like to write my own interactive function. However, I'm more than a bit lost. (interactive ...) has tons of options and I'm not sure which one I want. Then, I don't really know the names of the functions I need. If someone could kindly help me turn my pseudocode into real code, I would be mighty appreciative! (And as always, any links to informative places would be good. Right now I've just been reading this.)
Here is pseudocode for what I'd like to do:
(defun my-func (buffer) ; I think I need the buffer as an arg?
"does some replacements"
(interactive ???) ; ?
(let (replacements (list
'("a-regexp-string" . "a-replacement-string-with-backreferences")
...)) ; more of the above
(while replacements
(let (current (car replacements)) ; get a regexp-replacement pair
(some-regexp-replace-func buffer (car current) (cdr current)) ; do the replacement
(setq replacements (cdr replacements))))))
First, from the looks of your function you would probably be doing it in the current buffer, so no, you don't need to have a 'buffer' argument. If that's a bad assumption, I can change the code. Next, in a 'let' if you are assigning to variables you need another set of parens around each pair of var/value. Finally, when looping through a list I prefer to use functional-programming-like functions (mapcar, mapc, etc.). I'll try to inline some comments here:
(defun my-func ()
"Do some replacements"
(interactive)
(let ((replacements (list '("foo" . "bar")
'("baz" . "quux"))))
(save-excursion ; So point isn't moved after this function
(mapc (lambda (x) ; Go through the list, with this 'inline' function
; being called with each element as the variable 'x'
(goto-char (point-min)) ; Start at the beginning of the buffer
(while (re-search-forward (car x) nil t) ; Search for the car of the replacement
(replace-match (cdr x)))) ; And replace it with the cdr
replacements)))) ; The list we're mapc'ing through
As for what to read, I'd suggest the Elisp manual that comes with Emacs.