16

Search and replace, by M-% and !, is done from current position to the end of the buffer. How can I do it for the entire buffer? Thanks.

  • 2
    I suggest changing the title to "search and replace entire buffer". Globally could also be referring to entire projects. – Malabarba Sep 25 '14 at 16:01
  • 1
    This is one area where Vim/Evil is hard to beat: :%s/foo/bar – shosti Sep 25 '14 at 18:31
  • @shosti: Actually, I think your method requires more keystrokes. Just sayin' ;-) – nispio Sep 25 '14 at 20:13
13

I don't see that supported while still retaining your starting position. (I don't see a way to wrap to the beginning of the buffer when search reaches the end.)

Your best bet is using M-< to go to the start of the buffer, then do the query-replace, when you're done press C-uC-spaceC-uC-space to jump back to your starting point.

  • 1
    This works when transient-mark-mode is on. Otherwise C-SPC C-SPC will temporarily enable transient-mark-mode – nispio Sep 25 '14 at 16:43
  • 5
    No need to set the mark manually with C-SPC. M-< (and many other commands that potentially "move point a long way") does it for you. – Mathias Dahl Sep 25 '14 at 18:45
9

You could add the following command to your emacs initialization file, and bind it to the keystroke of your choice.

(defun replace-regexp-entire-buffer (pattern replacement)
  "Perform regular-expression replacement throughout buffer."
  (interactive
   (let ((args (query-replace-read-args "Replace" t)))
     (setcdr (cdr args) nil)    ; remove third value returned from query---args
     args))
  (save-excursion
    (goto-char (point-min))
    (while (re-search-forward pattern nil t)
      (replace-match replacement))))
9

You can follow the following steps:

  • C-x h — Select the whole buffer or M-< - Go to the top of the buffer
  • M-% — Initiate query-replace
  • ! — Force replace all
  • C-u C-SPC C-u C-SPC — Move back to your starting position
  • This should get more attention. – Indra May 29 at 9:05
3

You can add this to your init.el file to update the behavior of M-% to to replace the word in the entire buffer by default:

(defun my/query-replace (from-string to-string &optional delimited start end)
  "Replace some occurrences of FROM-STRING with TO-STRING.  As each match is
found, the user must type a character saying what to do with it. This is a
modified version of the standard `query-replace' function in `replace.el',
This modified version defaults to operating on the entire buffer instead of
working only from POINT to the end of the buffer. For more information, see
the documentation of `query-replace'"
  (interactive
   (let ((common
      (query-replace-read-args
       (concat "Query replace"
           (if current-prefix-arg " word" "")
           (if (and transient-mark-mode mark-active) " in region" ""))
       nil)))
     (list (nth 0 common) (nth 1 common) (nth 2 common)
       (if (and transient-mark-mode mark-active)
           (region-beginning)
         (buffer-end -1))
       (if (and transient-mark-mode mark-active)
           (region-end)
         (buffer-end 1)))))
  (perform-replace from-string to-string t nil delimited nil nil start end))
;; Replace the default key mapping
(define-key esc-map "%" 'my/query-replace)

And to get the same behavior from query-replace-regexp:

(defun my/query-replace-regexp (regexp to-string &optional delimited start end)
  "Replace some things after point matching REGEXP with TO-STRING.  As each
match is found, the user must type a character saying what to do with
it. This is a modified version of the standard `query-replace-regexp'
function in `replace.el', This modified version defaults to operating on the
entire buffer instead of working only from POINT to the end of the
buffer. For more information, see the documentation of `query-replace-regexp'"
  (interactive
   (let ((common
      (query-replace-read-args
       (concat "Query replace"
           (if current-prefix-arg " word" "")
           " regexp"
           (if (and transient-mark-mode mark-active) " in region" ""))
       t)))
     (list (nth 0 common) (nth 1 common) (nth 2 common)
       (if (and transient-mark-mode mark-active)
           (region-beginning)
         (buffer-end -1))
       (if (and transient-mark-mode mark-active)
           (region-end)
         (buffer-end 1)))))
  (perform-replace regexp to-string t t delimited nil nil start end))
;; Replace the default key mapping
(define-key esc-map [?\C-%] 'my/query-replace-regexp)
  • Very useful. Thanks. – NVaughan Feb 10 at 15:58
2

If you use Icicles then you can search-and-replace over the entire buffer (or multiple buffers or files or bookmark targets).

And unlike query-replace (e.g. C-x h M-%):

  • You can navigate the matches in any order.

  • Replacement is on demand: you need not visit each match and answer whether or not to replace it.

0

This is the solution I'm currently using, it start from the begining of the buffer and will go back to old point after replacing.

(defun query-replace-from-top ()
  (interactive)
  (let ((orig-point (point)))
    (save-excursion
      (goto-char (point-min))
      (call-interactively 'query-replace))
    (message "Back to old point.")
    (goto-char orig-point)))
(bind-key* "M-%" 'query-replace-from-top)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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