repeat macro after error stops execution - emacs

My objective is to remove duplicated stanzas in xml files. I am sure I have a duplicated stanza if the first line of the stanza is found multiple times in the file.
I have created a macro that finds the first line of my stanzas through interactive search, then Ctrl-S again to go to the next occurrence. If found, I then mark the section I want to delete and delete it. My macro terminates here.
If my Ctrl-s does not find the next occurrence, my macro stops, which is exacly what I want it to do. However, when I Esc 1000 Ctrl-x e to execute my macro multiple times, when the error is found also the 1000 cycle stops. I am happy for the macro to stop, but I want to execute it again after the error. Is this possible? Or is there already a macro somewhere to remove duplicates stanzas or groups of lines from a file?
My macro:
C-s ;; isearch-forward
<Conduit ;; self-insert-command * 8
SPC ;; self-insert-command
6*C-w ;; kill-region
C-s ;; isearch-forward
C-a ;; beginning-of-line
C-SPC ;; set-mark-command
C-s ;; isearch-forward
< ;; self-insert-command
/ ;; nxml-electric-slash
Conduit> ;; self-insert-command * 8
<right> ;; forward-char
C-w ;; kill-region
Thanks
Joe

Hmm. It would be nice if Emacs provided a convenient interactive way to handle error conditions inside keyboard macros, but I suspect juanleon's answer might be your best bet at present.
A workaround in general is to not use C-s, but instead use something like M-: (search-forward "foo" nil t) RET to search for "foo" without triggering an error if it's not there. In this example there would be more to it, though.
For one-off processing, what I tend to do in these kinds of situation is generate a buffer of the results I'm interested in, and then process that with the keyboard macro.
This example is actually a bit tricky, but you could occur all the lines matching the pattern, pipe through sort | uniq --all-repeated=separate, and then eliminate the first line of each group. That leaves you with a the exact number of instances you wish to remove for each duplicate, so your keyboard macro could grab a line from that list, find the last instance of it in the original buffer, delete it, and move to the next line in the list.
If this is a common activity, a custom elisp function would seem like the way to go.

If what you want to achieve is to run a macro repeatedly regardless of errors, this would be a way to do it:
(defun repeat-macro-until-abort ()
(interactive)
(while t
(ignore-errors
(kmacro-call-macro 0))))
It will run your last macro until you hit C-g. Please notice that it won't be stopped even by reaching end-of-buffer.

There is a easy way to remove lines that match a regexp: M-x flush-lines
If you know the regexp for the stanza you want to remove, you can type C-M-% <your-regexp> RET RET and you witll iterate over the occurences chosing what to remove (type ! for removing every of them). C-M-% is the default keybinding for query-replace-regexp.

Related

Search-forward typo aborts macros

Search-forward seems to not work well inside emacs macros. For example, say I want to use a macro to help replace FOO with BAR in the following string:
aoeuFOOsnutehaFOOsanotehuFOO
I might begin recording a macro, search-forward for FOO, and then hit backspace a few times and type BAR. Then I can replay this macro to replace the rest of the occurrences. Pretty simple.
Suppose I hit the wrong key and search-forward for FOOO. I hit Backspace to remove the extra O, and finish recording the macro. But when I replay it, nothing happens. FOOO is not in the document, so the macro replay is immediately aborted when the search fails.
This gets annoying in longer macros. As it is, whenever I record a macro, I have to make sure I type in the search text for my search-forwards perfectly. If I make even one mistake, I have to cancel recording my macro and start over; otherwise, the macro will just abort when I replay it.
To sum up, if you use search-forward and commit a typo while recording a macro, the macro will not replay properly because it will abort as soon as it replays your typo.
Any workarounds or solutions to this problem?
You don't have to abort the macro: The easiest thing to do is to simply finish recording the macro (typos and all) and then edit it via C-x C-k C-e (kmacro-edit-macro-repeat) to remove the typo(s).
For instance, when you call this command after defining a macro that is supposed to simply search for occurrences of foo in the current buffer but contains a typo in the search (you typed fooo instead of foo before fixing the typo), the buffer for editing it would look like this:
C-s ;; isearch-forward
f ;; self-insert-command
ooo ;; self-insert-command * 3
DEL ;; delete-backward-char
RET ;; newline
To fix the macro, delete one of the os from the third line and remove the fourth line:
C-s ;; isearch-forward
f ;; self-insert-command
oo ;; self-insert-command * 2
RET ;; newline
Note that you don't have to change self-insert-command * 3 to self-insert-command * 2, I just did that to avoid confusion.
When you're done, hit C-c C-c to recompile the macro and close the *Edit macro* buffer.
The documentation of the ding function says (emphasis mine):
(ding &optional ARG)
Beep, or flash the screen.
Also, unless an argument is given, terminate any keyboard macro currently executing.
Digging into the source we can see that all isearch-* functions that call ding do so without passing a non-nil ARG. You could redefine these functions to change the way they call ding (not sure if it would be good idea to remove the calls to ding entirely), but there is an easier way to achieve what you want:
You can make sure ding is always called with a non-nil ARG by advising it as follows:
(defadvice ding (before be-nice activate compile)
(ad-set-arg 0 t))
As documented here, the ad-set-arg macro
sets the value of the actual argument at position to value.
So what the advice does is tell Emacs to set ARG to t before running the body of the original ding function, causing ding to be nice and not terminate keyboard macros anymore.
With the advice in place, you can now transform
aoeuFOOsnutehaFOOsanotehuFOO
into
aoeuBARsnutehaBARsanotehuBAR
with a "faulty" macro that contains a corrected typo:
C-s ;; isearch-forward
F ;; self-insert-command
OOO ;; self-insert-command * 3
DEL ;; delete-backward-char
RET ;; newline
3*DEL ;; delete-backward-char
BAR ;; self-insert-command * 3
EDIT
As #phils mentions in the comments below, allowing macro execution to continue regardless of errors can lead to unwanted consequences, so use this solution with care. If you want to be able to quickly enable or disable the advice so that you can use it selectively (i.e., in situations where you are sure it won't mess things up), define it like this:
(defadvice ding (before be-nice) ; advice not activated by default
(ad-set-arg 0 t))
and add a command for turning it on and off to your .emacs:
(defun toggle-ding-advice ()
(interactive)
(if (ad-is-active 'ding)
(ad-disable-advice 'ding 'before 'be-nice)
(ad-enable-advice 'ding 'before 'be-nice))
(ad-activate 'ding))
(global-set-key (kbd "C-c a") 'toggle-ding-advice)
You can then toggle the advice by simply pressing C-c a.

A quick way to repeatedly enter a variable name in Emacs?

I was just typing in this sort of code for Nth time:
menu.add_item(spamspamspam, "spamspamspam");
And I'm wondering if there's a faster way to do it.
I'd like a behavior similar to yasnippet's mirrors, except
I don't want to create a snippet: the argument order varies from
project to project and from language to language.
The only thing that's constant is the variable name that needs to be
repeated several times on the same line.
I'd like to type in
menu.add_item($,"")
and with the point between the quotes, call the shortcut and start typing,
and finally exit with C-e.
This seems advantageous to me, since there's zero extra cursor movement.
I have an idea of how to do this, but I'm wondering if it's already done,
or if something better/faster can be done.
UPD The yasnippet way after all.
Thanks to thisirs for the answer. This is indeed the yasnippet code I had initially in mind:
(defun yas-one-line ()
(interactive)
(insert "$")
(let ((snippet
(replace-regexp-in-string
"\\$" "$1"
(substring-no-properties
(delete-and-extract-region
(line-beginning-position)
(line-end-position))))))
(yas/expand-snippet snippet)))
But I'm still hoping to see something better/faster.
yasnippet can actually be used to create a snippet on-the-fly:
(defun yas-one-line ()
(interactive)
(let ((snippet (delete-and-extract-region
(line-beginning-position)
(line-end-position))))
(yas-expand-snippet snippet)))
Now just type:
menu.add_item($1,"$1")
and call yas-one-line. The above snippet is expanded by yasnippet!
You could try
(defvar sm-push-id-last nil)
(defun sm-push-id ()
(interactive)
(if (not sm-push-id-last)
(setq sm-push-id-last (point))
(text-clone-create sm-push-id-last sm-push-id-last
t "\\(?:\\sw\\|\\s_\\)*")
(setq sm-push-id-last nil)))
after which you can do M-x sm-push-id RET , SPC M-x sm-push-id RET toto and that will insert toto, toto. Obviously, this would make more sense if you bind sm-push-id to a convenient key-combo. Also this only works to insert a duplicate pair of identifiers. If you need to insert something else, you'll have to adjust the regexp. Using too lax a regexp means that the clones will tend to overgrow their intended use, so they may become annoying (e.g. you type foo") and not only foo but also ") gets mirrored on the previous copy).
Record a macro. Hit F3 (or possibly C-x (, it depends) to begin recording. Type whatever you want and run whatever commands you need, then hit F4 (or C-x )) to finish. Then hit F4 again the next time you want to run the macro. See chapter 17 of the Emacs manual for more information (C-h i opens the info browser, the Emacs manual is right at the top of the list).
So, for example, you could type the beginning of the line:
menu.add_item(spamspamspam
Then, with point at the end of that line, record this macro:
F3 C-SPC C-left M-w C-e , SPC " C-y " ) ; RET F4
This copies the last word on the line and pastes it back in, but inside of the quotes.

Repeat-like copycat function for Emacs

I would like some copycat function, that takes the previous input and repeats it (like repeat), but does not get written over when something else is done, and thus remains repeatable. Anyone has any ideas?
EDIT: The way I intend this is to have some mode in which D keypress will act exactly like repeat (if some other input has been done, repeat that), while d will repeat the last thing assigned to the last D key press.
EDIT2: If I would yank, and then press C-x z (in my mode also bound to D), then it will repeat the yank. However, when I would move the cursor down, and I try to press D, it then repeats the down cursor. In this case, I would like the small d to do the behavior of the last repeat (that is, yank) while D would repeat the down cursor command. So, d would store the last repeated command, while D would repeat the last command.
This was just too long for a comment:
It feels like you essentially want a shorter version of keyboard macros? I'll try to explain briefly, and see if it is close:
C-x ( - start recording the macro.
Do whatever you want (may be just a single command). For example, yank something, i.e. M-d
C-x ) - finish recording the macro.
Now you can C-x e to replay the macro (you can do other stuff after you've recorded the macro, C-x e will do what you have previously recorded (i.e. M-d in this case).
Maybe you can create a shorthand version of start-macro end-macro recording, if you are sure there will be only one command, but these are really minor improvements. Once you get used to macros, you'll do it unconsciously, so that one keystroke saved won't matter really.
Also, if I didn't guess what you were after, this may prove to be interesting to you: http://www.gnu.org/software/emacs/manual/html_node/elisp/Command-History.html
My best attempt. It works, though it didn't incorporate all the error handling that repeat has.
(defun Navi-repeat ()
;; Checks whether the last repeatable command is the same as repeat var.
;; If yes, set repeat-navi to that command, and call it.
;; If no, check whether the Navi-repeat variable has been set before:
;; If bound, call it.
;; If not bound,
;; give it the value of the last-repeatable command, and call it.
(interactive)
(if (eq last-repeatable-command 'repeat)
(progn (setq repeat-navi repeat-previous-repeated-command)
(call-interactively repeat-navi))
(if (boundp 'repeat-navi)
(call-interactively repeat-navi)
(progn (setq repeat-navi last-repeatable-command)
(call-interactively repeat-navi))
)
)
)

Emacs close paren jumps to already existing close-paren when editing clojure code

If having this piece of code in an emacs buffer:
(if (> x 5
true
false))
When I try to edit it in order to fix the parenthesis, something very annoying is happening! When I try to add a closing parenthesis to the if condition, emacs is making the cursor jump to the closing parenthesis after 'false' instead of adding a new parenthesis after 5.
Is this part of some mode, maybe clojure-mode? Do you know how may I fix this? What is this useful for?
It sounds like you're using paredit. Did you install it like recommended on the project page?
As to what it's good for? It's good for editing lists. But you have to buy
into whe whole system, or you'll end up really confused. See the wiki
page.
Do you have this section in your ~/.emacs.el? Just remove it.
;; (require 'paredit) if you didn't install via package.el
(defun turn-on-paredit () (paredit-mode 1))
(add-hook 'clojure-mode-hook 'turn-on-paredit)
Yes, paredit is "different". It will always make sure your parenthesis balance. See http://www.emacswiki.org/emacs/PareditCheatsheet .
For your code, place the cursor beneath the first closing parenthesis and press C-left. Repeat the exercise and it will have moved to where you want it.
Cut&paste (kill & yank in emacs lingo) also allow you to manually screw with the balanced parenthesis, so until you get used to paredit it may be easier to use. Good luck!
how to verify that paredit is the offender
You can type C-h k ) while in your Lisp buffer to see what ) is bound to. If it is bound to paredit-close-round then yes paredit is the offender.
how to disable paredit when you don't know what's triggering it
Try auramo's answer in another thread
or if that doesn't work, try this:
(eval-after-load 'paredit
'(defalias 'paredit-mode 'ignore))
If you are curious about what is triggering paredit-mode in your Emacs, use M-x debug-on-entry RET paredit-mode RET
learning to live with paredit
But still I must encourage you to continue using paredit. Let's keep using paredit and let's see solutions for problems you posed. You asked "Do you know how may I fix this?" I'll just assume you are asking how to fix that if form. Marius Kjeldahl gave you solution which uses paredit-forward-barf-sexp, now in general, if you have some Lisp code where you see that some parens are in wrong places and you want to fix that, you can simply temporarily disable paredit-mode in that buffer (by typing M-x paredit-mode) and then fix your code and then enable paredit-mode again (by typing M-x paredit-mode again). Another thing to consider is that Emacs has undo, so if you arrive at (if (> x 5 true false)) through some action, you can undo that action and start over. Undo is bound to C-z if you use CUA mode.
Still you might find bindings of C-left, C-right to be weird, so you might want to use the following setup:
(eval-after-load 'paredit
'(progn
;; paredit-forward-barf-sexp is usually bound to <C-left>, C-}.
;; here we unbind it from <C-left>
;; so that one can continue to use <C-left> for movement.
(define-key paredit-mode-map (kbd "<C-left>") nil)
;; paredit-forward-slurp-sexp is usually bound to <C-right>, C-).
;; here we unbind it from <C-right>
;; so that one can continue to use <C-right> for movement.
(define-key paredit-mode-map (kbd "<C-right>") nil)
;; paredit-backward-kill-word is bound to M-DEL but not to <C-backspace>.
;; here we bind it to <C-backspace> as well
;; because most people prefer <C-backspace> to M-DEL.
(define-key paredit-mode-map (kbd "<C-backspace>") 'paredit-backward-kill-word)))
You asked "What is this useful for?" by which you may be asking two things:
Why is paredit-close-round useful?
Why does paredit have to bind paredit-close-round to ) when it could have bound it to better keys?
Best way to think of paredit-close-round is to think of it as a counterpart to C-M-u. Move point to | in the following code and try press C-M-u several times to see what happens, and then move point to | again and try press C-M-- C-M-u (i.e. type -u while Control and Alt are on) several times to see what happens.
(when t
(when t
(blah)
(blah))
(when t
(blah | blah)
(blah))
(when t
(blah)
(blah)))
C-M-u is useful for selecting expressions; in order to select an enclosing form or forms, you press C-M-u several times and then C-M-SPC several times. C-M-- C-M-u is useful for evaluating an enclosing form; you press C-M-- C-M-u several times and then C-x C-e to eval the enclosing form.
paredit-close-round basically does what C-M-- C-M-u does.
Why is it an OK thing that paredit binds ) to a command that does something other than simply inserting a close paren? Because you are not supposed to insert a closing parenthesis by yourself. Whenever you insert an open paren, a close paren is also inserted automatically. Whenever you want to change (blah) (blah) to ((blah) (blah)), you simply select the two blah forms and press (.

Emacs copy with regex

I have a text file. Can Emacs select text based on regex and put it in kill-ring, so I can copy it somewhere else? Something like regex-kill-ring-save?
inspired by the already given comments (the Charles answer doesn't work as I would want it), I added a new function to the isearch/isearch-regexp mode map which puts only the matching string into the kill ring (whereas Charles proposal kills from current point to end of matching string):
(defun hack-isearch-kill ()
"Push current matching string into kill ring."
(interactive)
(kill-new (buffer-substring (point) isearch-other-end))
(isearch-done))
(define-key isearch-mode-map (kbd "M-w") 'hack-isearch-kill)
The nice thing about the isearch/isearch-regexp approach (which you can enable with C-s and C-M-s respectively) is that you can see your search string growing and you can copy it with M-w as soon as you are satisfied (and go back to where you have been before with C-u C-Space).
This works for me with Emacs 23.1. Don't know if it will work in all situations. Anyway I hope you find it useful :)
UPDATE: going through the emacswiki I stumbled over KillISearchMatch which suggests more or less the same (plus some more tips ...).
Cheers,
Daniel
I'm not sure if there is such a function already, but what you can do it with a keyboard macro:
Start recording a kbd macro: C-x (
Search for your regexp with search-forward-regexp
Move to the beginning of your match (the text you want to kill) with the various emacs navigation commands, e.g. search or backward-word etc.
Mark: C-spc
Move to the end of your match
Kill the text: C-w
You can then name the keyboard macro with M-x name-last-kbd-macro so that you can execute the macro with a name rather than with C-x e.
If you want to save the macro for future sessions, you can open your .emacs and insert the macro into the buffer with M-x insert-kbd-macro. After than you can bind a key to the macro just like you bind keys to normal emacs functions, e.g. (global-set-key "\C-c m" 'funky-macro-macro).
More about emacs keyboard macros
Isearch+ does this already. It optionally sets the region around the search target. You can use C-SPC C-SPC or M-= C-SPC at any time during Isearch to toggle this.
isearchp-deactivate-region-flag is a variable defined in isearch+.el.
Its value is t
Documentation:
Non-nil means isearching deactivates the region.
See also option isearchp-restrict-to-region-flag.
You can toggle this option using M-= C-SPC during Isearch.
You can customize this variable.