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.
7 Answers
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.
-
1This works when
transient-mark-mode
is on. OtherwiseC-SPC C-SPC
will temporarily enabletransient-mark-mode
– nispioSep 25, 2014 at 16:43 -
5No 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. Sep 25, 2014 at 18:45
You can follow the following steps:
C-x h
— Select the whole buffer orM-<
- Go to the top of the bufferM-%
— Initiatequery-replace
!
— Force replace allC-u C-SPC C-u C-SPC
— Move back to your starting position
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))))
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)
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.
-
-
@alper: Thanks; corrected. Emacs Wiki changed from http to https, and added an
emacs/
subdir.– DrewFeb 6, 2020 at 16:00
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)
-
@alper Check the updated version, I personally never got any issue.– CodyChanMay 24, 2021 at 18:44
-
-
1@alper use
(let ((case-fold-search nil))
check stackoverflow.com/a/5346418/1528712– CodyChanOct 4, 2021 at 15:24
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)
:%s/foo/bar