8

I use M-x query-replace on Emacs (M-%) quite often, and I like that I have the flexibility to choose between these options:

Spacebar               Replace text and find the next occurrence
Del                    Leave text as is and find the next occurrence
. (period)             Replace text, then stop looking for occurrences
! (exclamation point)  Replace all occurrences without asking
^ (caret)              Return the cursor to previously replaced text

Is there a way to:

  • Cycle back to the beginning of the document after we hit the end of the document?

  • Reverse the direction of the search-and-replace in the middle of the execution of the command.

3
  • 1
    query-replace-string (and its regexp sibling) only go forward, you'd have to rewrite a big chunk of code to go backward. There's no option to wrap (there might be a package out there somewhere), but that's easy to work around: M-< (beginning-of-buffer), do the replacement, C-2 C-SPC (go back to the next-to-last mark set (by M-<)). Sep 16, 2012 at 1:35
  • Interesting idea. Could be quite convenient. Ask the emacs gurus. They may like it enough, so they implement it.
    – Tom
    Sep 16, 2012 at 6:50
  • 1
    Probably you should change your post so not to make everyone confused: that's query-replace (As for your question, can't help you.) Sep 16, 2012 at 9:26

2 Answers 2

2

query-replace is a very important function, so I'm reluctant to change it globally. What I've done instead is to copy this to a new function, my-query-replace, which initially has the same behaviour. Then I advise this function to repeat the query-replace search at the beginning of the buffer once it reaches the end. This might be overly cautious - you could modify the advice to apply to query-replace instead of my-query-replace, and enable this behaviour globally.

;; copy the original query-replace-function 
(fset 'my-query-replace 'query-replace)

;; advise the new version to repeat the search after it 
;; finishes at the bottom of the buffer the first time:    
(defadvice my-query-replace 
  (around replace-wrap 
          (FROM-STRING TO-STRING &optional DELIMITED START END))
  "Execute a query-replace, wrapping to the top of the buffer 
   after you reach the bottom"
  (save-excursion
    (let ((start (point)))
      ad-do-it
      (beginning-of-buffer)
      (ad-set-args 4 (list (point-min) start))
      ad-do-it)))

;; Turn on the advice    
(ad-activate 'my-query-replace)

Once you have evaluated this code, you can call the wrapped search with M-x my-query-replace, or bind it to something convenient for you:

(global-set-key "\C-cq" 'my-query-replace)
1

I've using below for work with Emacs 24+:

;; query replace all from buffer start
(fset 'my-query-replace-all 'query-replace)
(advice-add 'my-query-replace-all
            :around
            #'(lambda(oldfun &rest args)
               "Query replace the whole buffer."
               ;; set start pos
               (unless (nth 3 args)
                 (setf (nth 3 args)
                       (if (use-region-p)
                           (region-beginning)
                         (point-min))))
               (unless (nth 4 args)
                 (setf (nth 4 args)
                       (if (use-region-p)
                           (region-end)
                         (point-max))))
               (apply oldfun args)))
(global-set-key "\C-cr" 'my-query-replace-all)

Regard the region replace case, and any START and END args passed.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .