25

I want to rewrite parts of an opensource project. This includes renaming methods. How can I do that efficiently in emacs across the whole project?

I would rather not use hacks such as search and replace in every buffer.

5
  • 2
    Which language?
    – phils
    Jan 21, 2015 at 10:56
  • Have you looked at ag/grep + wgrep + search/replace? You don't open buffers individually in that. Related: emacs.stackexchange.com/a/243/115 Jan 21, 2015 at 13:27
  • Python. I realize my question was not the best, sorry. Jan 21, 2015 at 13:54
  • 1
    As this question has been bumped to the top (in case anyone stumbles upon this from Google), there is a dedicated python library for refactoring called Rope. It's more intelligent than the other solutions offered as it takes into account context. It is implemented in Emacs in a package called ropemacs.
    – JCC
    Sep 30, 2016 at 17:10
  • @TheUnfunCat can you add more context to your question? As of now it's pretty vague, and adding that you want to do this in a python project would clear up a lot of things.
    – user12563
    Jan 29, 2019 at 17:24

7 Answers 7

21

I now use helm-ag to find all instances of the function name (searches in all files, incl. subdirs, not just in open buffers), and then I use C-c C-e to enter a buffer that lists all the matches and there I change the function name. When I am done I press C-c C-c (helm-ag--edit-commit) to store the changes to all the opened files.

This might sound confusing but please see https://github.com/ShingoFukuyama/helm-swoop

When you grok it you will cry tears of joy that such wonderful functionality exists.

7
  • 1
    It did run a tear down my cheek.
    – mihai
    Sep 30, 2016 at 11:54
  • 1
    literally had tears in my eyes when executing this workflow for the first time, no kidding
    – Paul
    Dec 7, 2018 at 23:41
  • Great solution!
    – fraxture
    Dec 5, 2019 at 17:32
  • I had to learn to master iedit before this solution made sense to me. I use C-c C-q to quickly edit the variables inside the buffer of matches.
    – kotchwane
    Mar 25, 2020 at 10:51
  • 6 years later and this is still by far the best behaviour I can find. Thank you! Apr 4, 2021 at 22:55
9

Since you didn't specify the language, it's hard to give better answers than “Search and Replace”.

Using wgrep

If you just want to (interactively) replace all instances of a symbol with another, wgrep is your best bet. It let's you interactively edit the grep results buffer.

  1. Do M-x package-install RET wgrep.
  2. Run M-x rgrep. It will ask you a few easy questions and then do a recursive search for the search-term inside the directory you speficied.
  3. Switch to the results buffer and do M-x wgrep-change-to-wgrep-mode. This buffer is now editable. Any changes you make here will be reflected in the files themselves.
  4. Run a replace-regexp or a query-replace-regexp in this buffer, to do the refactoring.
  5. Finish your edits with M-x wgrep-save-all-buffers and M-x wgrep-finish-edit.
0
8

You can use counsel-rg followed by C-c C-o to get a list of all candidates in a buffer. Press w to edit them with wgrep. I recommend iedit for symbol renames. Press C-c C-c to commit.

Dependencies:

4

For some generic approaches, look under the "Replace Across Files" heading on the Emacs Wiki search & replace page: http://www.emacswiki.org/emacs/CategorySearchAndReplace

Also see the answers to: Using Emacs to recursively find and replace in text files not already open.

4

You can use swiper

  1. Run M-x swiper-all type your regex, it will list all results, you can move with up/down to see a preview for each result.
  2. Now press M-q and it will ask you what you want to replace the matches with, type it and press enter.
  3. It will now walk you through an interactive replace, you can use y/n/! on each, y to replace, n to skip, and ! to replace all without asking.
2
  • It is called swiper though :) Thanks! May 28, 2020 at 11:02
  • This works for any of the counsel functions - so you can also run counsel-projectile-rg or spacemacs/search-project-rg (configuring spacemacs to use ivy) and this will work very well.
    – guibor
    Mar 29, 2021 at 9:50
1

M-x project-find-regexp could help, followed by typing r in the xref buffer.

It's not a "real" refactoring, but well along the lines of other answers here.

Or use and LSP client, such as eglot or lsp-mode, along with a suitable LSP server such as pyls. Those offer smarter rename operations.

0

Inspired by Dmitry's anwer, but searching through the entire project (not only the open buffers) and saving all the modified files in the end:

  1. Run M-x +ivy/project-search type your regex, it will list all results (I tend to use this function a lot so I bound it to C-x f).
  2. Now press M-q and it will ask you what you want to replace the matches with, type it and press enter.
  3. It will now walk you through an interactive replace, you can use y/n/! on each, y to replace, n to skip, and ! to replace all without asking.
  4. To save all the modified buffers, run C-x-s and then ! to save all of them.

Requires: Ivy.

Your Answer

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

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