3

How can I run a query-replace on the all the files pointed to by an arbitrary compilation-mode buffer?

I think to be usable this would need to be resumable from point in the compilation-mode buffer.

Something very nearly exactly functionally equivalent to query-replace would of course be fine, but for the purposes of this question, I'm not interested in alternative UIs such as globrep, multiple cursors etc.

Croad Langshan
  • 3,192
  • 14
  • 42

2 Answers2

1

Yes, what I'm looking for is (something close to) a command that iterates over matched files in the grep buffer and calls query-replace for each.

OK, I just added command diredp-compilation-files-other-window to Dired+, which can help with this.

You use it in a compilation buffer (any buffer, such as *grep*, that is in a mode derived from `compilation-mode').

It prompts you for the name of a new Dired buffer, and it opens Dired on all of the files corresponding to the compilation hits, regardless of what directories they are in. IOW, the files can be in different directories.

In that Dired buffer, you can then:

  1. Use t to mark all of the files.
  2. Use Q to query-replace across all of the files.

(Q is standard Dired command dired-do-query-replace-regexp).

As an alternative to using t to mark all of the files, with Dired+ you can just use C-u C-u Q to act on all files (without bothering to mark them). With Dired+, most commands that operate on the marked files let you use multiple C-u to act on all files, ignoring marks.

Instead of Q you can use A to search the files, D to delete them, P to print, Z to compress, ! to run a shell command, etc.

If you hit ? during query-replace you will see this information in buffer *Help*:

Query replacing regexp Sun with mooN.

Type Space or `y' to replace one match, Delete or `n' to skip to next,
RET or `q' to exit, Period to replace one match and exit,
Comma to replace but not move point immediately,
C-r to enter recursive edit (C-M-c to get out again),
C-w to delete match and recursive edit,
C-l to clear the screen, redisplay, and offer same replacement again,
! to replace all remaining matches in this buffer with no more questions,
^ to move point back to previous match,
E to edit the replacement string.
In multi-buffer replacements type `Y' to replace all remaining
matches in all remaining buffers with no more questions,
`N' to skip to the next buffer without replacing remaining matches
in the current buffer.
Drew
  • 75,699
  • 9
  • 109
  • 225
  • Nice addition! Note that there's something funky going on with the Emacs wiki's html right now, so be careful copy and pasting Elisp. Do a `ctrl+f` and search for `class=`. I think it's a problem with the ampersands. – nanny Mar 25 '15 at 13:40
  • @nanny: Thanks. I reported the wiki display/rendering problem. Fortunately, the code itself does not seem to contain any such "class=" occurrences. Good catch. – Drew Mar 25 '15 at 13:58
  • FYI, I just uploaded a version of `dired-do-query-replace-regexp` that lets you act on all files without bothering to mark them first. – Drew Mar 27 '15 at 03:37
  • Wow thanks! Is this "resumable" (see question)? Say during a query replace you see a questionable replacement and decide to quit the query-replace to look around. Once you decide whether to replace that instance, you then need to resume the multi-file query-replace. Some of the time that will mean continuing with the replacement in the file, other times it will mean continuing at the next file. I guess as things stand that would then require a decision from the user whether to `M-x query-replace` or to switch back to Dired+, un-mark certain files, and then `Q` again? – Croad Langshan Mar 29 '15 at 12:20
  • Yes, with `Q` you can hit `.` and then do other things - edit etc. whatever - and then resume query-replace (using `M-,`), just as for ordinary `query-replace(-regexp)`. Besides using `C-h k Q` to learn the possibilities, during query-replace you can hit `?` to learn them - see above. I think this answers your request. If so, you might consider accepting the answer. ;-) – Drew Mar 29 '15 at 14:39
0

I understand that you are most interested in "something very nearly exactly functionally equivalent to query-replace". I don't have such an answer. I think I recall seeing something about that at some point in the last few years, so hopefully someone will give you an exact answer to your question.

Anyway, here is an answer that presents an alternative that might help.

Instead of query-replace, you can use Icicles search in a *grep* or compilation buffer. The key C-c ` in these buffers is bound to icicle-compilation-search, which is a specialized version of icicle-search.

Each grep/compilation buffer hit defines a search context in the buffer it points to. You then search for text within these contexts. For grep, for example, each context is a matching line of source code.

While you search, you can replace search hits on demand. This is unlike the case for query-replace, where you are queried for each search hit and you must answer for each one (or for all that remain, together).

This is quite different from the searching and replacing you are used to, so be aware that it takes a bit of learning.

You should first become somewhat familiar with using Icicles in general, in particular using C-down etc. to act on completion candidates (which for search means navigating to search hits). You should next experiment with Icicles search, including its different possibilities (see the user options that affect it). Only when you are comfortable with these things should you try on-demand replacement during search.

Read about the various user options that affect Icicles search and replace, in particular icicle-search-replace-whole-candidate-flag, icicle-expand-input-to-common-match, and icicle-search-replace-common-match-flag, and icicle-search-highlight-all-current-flag.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • Sorry, but that's a bit too vague to be able to help. Which keys etc.? Anyway, as I said, there is a learning curve, yes. You might need to read more of the search docs, and you might need to try it a little more. Or ask more specifically for help. (Or not.) If you want to understand Icicles search, start with `C-c '` (`icicle-occur`). After you understand search well, read about replace and try it. IOW, I'd suggest *not* starting with search-and-replace. This is different from anything you are used to, and it is normal that it takes some getting used to. If it helps you, great. If not, sorry. – Drew Mar 22 '15 at 15:30
  • On further investigation I realise that the reason the bindings were not enabled is because I had not enabled icicle-mode :-) Thanks for your help, icicles looks interesting -- though I think doesn't quite fit the question, as you noted. – Croad Langshan Mar 22 '15 at 19:10
  • ;-) I almost asked whether you had turned on `icicle-mode` (wrote it but erased it, thinking it might sound snarky). As I said at the outset, I seem to recall something that responded exactly to what you requested: you can edit the compilation buffer and then have those edits transferred to the source files. I don't recall where/when I saw mention of that, however. Let's hope that someone else does, or that your googling for it is better than mine. – Drew Mar 22 '15 at 19:56
  • Googled again: *emacs grep edit*, and found these: [`grep-edit.el`](http://www.emacswiki.org/emacs-en/download/grep-edit.el), [`wgrep.el`](http://www.emacswiki.org/emacs/download/wgrep.el). Those are for `grep`, but either you might find something similar for compilation or you might be able to adapt those (or other google hits). – Drew Mar 22 '15 at 19:58
  • I would count those under "different UIs". What I'm looking for with this question is really something that does behave just like query-replace, for better or worse. (re M-x icicle-mode: well, in this case you *are* dealing with an idiot, so wouldn't be snarky ;-) – Croad Langshan Mar 22 '15 at 21:04
  • Those let you use regular `query-replace` in the `grep` buffer, to modify it. Then you can apply those changes to the source files, in one action. If you are instead wanting to use the `grep` (or compilation) output to access the source files, and then use `query-replace` there, then you can already do that, no? – Drew Mar 24 '15 at 14:02
  • Yes, what I'm looking for is (something close to) a command that iterates over matched files in the grep buffer and calls query-replace for each. I guess that wouldn't be hard to write but I was hoping it was already implemented (or if not, something sufficiently close that I could adapt to it easily). I'd prefer not to edit a grep buffer (`globrep`, referenced in my question, is another one of those). – Croad Langshan Mar 24 '15 at 18:46