0

I use Vim a lot, but now I've decided to switch to emacs.

Here is one of my questions: How do I apply a command or macro to text that matches a specific pattern? Or did I use emacs correctly below?

For example, if I need to replace 'foo' with 'bar' in the current buffer: In Vim, the commands are simple and straightforward:

  1. Search 'foo'
    /foo <RET>
  1. Replace 'foo' with 'bar'
    cwbar
  1. Jump to the next match
    n
  1. Apply the last change:
    .(dot)

enter image description here

In emacs, I complete the same task with the following steps:

  1. Jump to the 1st 'foo'
    C-s foo<RET>
  1. Record a keyboard macro that replaces 'foo' with 'bar'
    <f3>c-u 3 C-d bar<f4>
  1. Jump to the next match (in order the use last pattern, press C-s twice)
    C-s C-s
  1. Apply the macro:
    <f4>

The downside of emacs' one is that when I apply a macro with emacs will exit isearch mode. So I have to enter isearch mode and input the search pattern again when I want to jump to the next match.

7
  • 2
    Is there a reason the search is not part of the recording?
    – phils
    Commented Apr 15 at 9:54
  • 2
    In any case, this particular example can trivially be a query-replace: M-%.
    – phils
    Commented Apr 15 at 9:55
  • 2
    You need to read the documentation. In this case, see Query Replace. You can read the docs within Emacs: in this case C-h i g(emacs) RET to select the Emacs manual and then i query replace RET to search for the particular section.
    – NickD
    Commented Apr 15 at 12:18
  • I know M-% or query-replace, which gives an interactive interface that allows me to skip unwanted matches using key 'n'. And I know C-w and C-r can lead to recursive editing mode. But any other keys than those provided will interrupt the interaction mode. This makes it impossible to apply a macro.
    – Stephen
    Commented Apr 16 at 1:20
  • Perhaps you could edit your question to provide a different example than "a keyboard macro that replaces 'foo' with 'bar'" -- as I think everyone reading that example is going to immediately think "query replace 'foo' with 'bar'" without involving isearch or keyboard macros at all. (Do you actually have a use-case where you need a macro?)
    – phils
    Commented Apr 16 at 6:20

1 Answer 1

3

First of all, the equivalent to Vi(m)'s :s command family is the family of replacement commands. The command that does regular syntax replacement (with a regexp syntax that's slightly different from Vim) is replace-regexp. There's also query-replace-regexp (C-M-%) which asks for confirmation (enter ! to replace all), and replace-string and query-replace-string (M-%) to replace a string rather than a regular expression.

If you want to perform a replacement that isn't a simple textual replacement, the regexp variants allow you to enter arbitrary Lisp code in the replacement text thanks to the \, escape. For example, a regexp replacement of \_<\(foo\|bar\)\[\([0-9]+\)] by \1[\,(+ 3 (string-to-number \2))] adds 3 to the the value in every occurrence of foo[NUMBER] or bar[NUMBER].

If you've managed to write a complex replacement in the form of a macro and you don't want to write Lisp code, you can use this as the replacement: \&\,(progn (call-last-kbd-macro) "") (meaning replace by the original text, but call the last keyboard macro at the end). I can't think of many cases that are simple enough for a macro but can't be written as replacement text, but you can do it if you feel the need.

If you want to separate the search part from the replacement part, repeating the last search is fairly easy: press C-s twice. Then press f4 to apply the replacement macro (you don't need to explicitly exit incremental search mode: any command will do it except for those few commands that make sense during the incremental search). Press C-s again to skip an occurrence.

For the search part, you might prefer M-x occur or M-x grep. Both of these create a list of lines containing occurrences and you can move to the next occurrence with C-x `.

1
  • What I want is interactive replacement. isearch may be the best answer. Thank you for your detailed answer.
    – Stephen
    Commented Apr 17 at 8:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.