"I have a mind like a steel... uh... thingy." Patrick Logan's weblog.

Search This Blog

Friday, September 26, 2008

Query Replace

Maybe emacs users should do more to promote it. Emacs has a reputation of being overwhelming. But we don't promote emacs enough. There are great reasons to learn and use it. I don't think emacs is difficult to learn, there is a great help system and an interactive tutorial to begin.

Emacs does have a ton of functionality. A co-worker asked me about the enormity of the emacs key sequences, not to mention the number of functions that can be run by name. I've used emacs for 27 years, so I'm not the one to speculate on the effort to learn it.

But one thing to remember is that across all the different editing "modes" (for editing this language or that one, or text, or email, or file systems, or what have you) most of the commands are the same and others simply apply the same concept to a specific mode. e.g. what does it mean to go forward and backward by a word or a sentence or an expression or function definition?

See an emacs command summary. I could not quote a lot of these for you without acting out the sequences with my hands. Emacs is now in my physical hand memory.

My favorite emacs function may be "query replace". This function at first may seem not unlike any kind of interactive find-and-replace dialog on a Mac or Windows.

But query replace (found on the meta-percent key combination for those following along at home) is enormously rich. First, query replace will attempt to preserve case in the replaced text. e.g. if you replace "foo" with "bar" and the function encounters "FOO" then you have the option of replacing it with "BAR" and if it encounters "Foo" then the replacement will be "Bar".

What if you want to replace a found match but then edit that particular match slightly differenty before continuing on? (Otherwise you have to remember to go back, and where to go back to, to edit that specific replacement. And what if there are several variations?)

In this case when prompted for a replacement, type control-r for a "recusrive edit". Now you are in a position to edit that specific replacement before continuing with the search for the next match. If you want to do the replace and then review the replaced text before continuing with the next match, do this: type comma "," to do the replace but remain at that spot. You can type control-r to recursively edit the replaced text or do the usual to continue on.

control-meta-c escapes the recursive edit and continues with the search.

What if you made a mistake with the previous match? Either you should have made the replacement and didn't, or you should not have made the replacement. Type "^" and query replace takes you back to the location of the previous match with the text in the state as you left it.

Enough already. Emacs is one helluva tool. There may be other tools with just as broad and deep an array of functions. If you don't have one already, give emacs a try.


Jim Menard said...

I, too, have used Emacs for 27 years. This is the first time I've learned about using recursive edit. Thank you very much for the information. Now I just have to drill it into my "Emacs memory".

ramen said...

Another great thing about query-replace is that it scopes your changes to the highlighted region if transient-mark-mode is on. This helps you from getting lost in your file when your search string matches more stuff further down in the buffer than you expected.

Also, there is query-replace-regexp, which is a whole lot less scary than replace-regexp.

Patrick Logan said...

Interesting about transient mark mode. I don't use that, but I can see it's handiness.

I've always used narrow-to-region explicitly to work within a region.

Praki Prakash said...

I have been using emacs for the last 8 years. I really appreciate the porgammability. With a few lines of elisp, I am able to do things like turn my java code into a UML diagram, view an ant build file as a dependency graph and interface with external programs of all sorts. emacs is rich with all the contributions over the years. The user base is indeed quite small but I am not complaining about that.

About the only thing I wish for in emacs is a better lisp. Something that is lexically scoped and with support for threads.

Too bad you didn't mention regular expressions with groups and the ability to use result of elisp code in replacements. That is extremely handy and wicked cool feature.

Anonymous said...

I love emacs, been using it for close to a decade now, but one thing that still confuses me to this day is why it is so hard to perform a query replace across all files in a directory(recursively) or even just all buffers.

Now I've seen solutions to this problem posted on the web involving invoking dired then selecting all the files and preforming some sort of dired search and replace. Personally, the number of keys in this sequence is a bit much for me to remember.

And it isn't like this is an uncommon thing to want to do. Every moderately sophisticated editor out there that I know of supports this functionality, I almost want to break out of my emacs word and fire up another editor simply for global search and replaces.

Am I overlooking some glaringly obvious solution to this problem? Please correct me if I am wrong or if you have an elegant solution to this, I would love to hear it.


Patrick Logan said...

I just posted a follow-up on multiple-file query / replace...


Anonymous said...

query-replace-regexp ftw!

Blog Archive

About Me

Portland, Oregon, United States
I'm usually writing from my favorite location on the planet, the pacific northwest of the u.s. I write for myself only and unless otherwise specified my posts here should not be taken as representing an official position of my employer. Contact me at my gee mail account, username patrickdlogan.