22

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.

tarsius
  • 25,298
  • 4
  • 69
  • 109
Tim
  • 4,987
  • 7
  • 31
  • 60

7 Answers7

17

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.

J David Smith
  • 2,635
  • 1
  • 16
  • 27
Jordon Biondo
  • 12,332
  • 2
  • 41
  • 62
  • 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
15

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
Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179
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))))
Sue D. Nymme
  • 1,406
  • 12
  • 13
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)
nispio
  • 8,175
  • 2
  • 35
  • 73
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.

Drew
  • 75,699
  • 9
  • 109
  • 225
1

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-region-or-from-top ()
      "If marked, query-replace for the region, else for the whole buffer (start from the top)"
      (interactive)
      (progn
        (let ((orig-point (point)))
          (if (use-region-p)
              (call-interactively 'query-replace)
            (save-excursion
              (goto-char (point-min))
              (call-interactively 'query-replace)))
          (message "Back to old point.")
          (goto-char orig-point))))
    (bind-key* "M-%" 'query-replace-region-or-from-top)
CodyChan
  • 2,599
  • 1
  • 19
  • 33
1

My very simple but effective variant, which just advises both query-replace and query-replace-regexp to start replacing from the top of the buffer if region is not active. Otherwise, replace in the region only.

So this doesn't need new keybinds - just continue to use M-% and M-C-%.


(defun jj/goto-top-if-no-region (orig-func &rest args)
  "if region is not active, go to the buffer start"
  (save-excursion
    (when (not (use-region-p))
      (goto-char (point-min)))
    (apply orig-func args)))

(advice-add 'query-replace :around #'jj/goto-top-if-no-region)
(advice-add 'query-replace-regexp :around #'jj/goto-top-if-no-region)
TheJJ
  • 153
  • 6