1

I want to select some text somewhere in a buffer, call query-replace and then type (or paste from kill-ring) only the second argument, TO-STRING, (and make the selected text count as FROM-STRING).

I want a replacement to be performed within the entire buffer as well.

2 Answers 2

2

If you use library Replace+ (replace+.el) then you can just customize option search/replace-region-as-default-flag to non-nil. That gives you the region text as FROM text default, so you can just hit RET to accept that.

search/replace-region-as-default-flag is a variable defined in replace+.el.

Its value is nil

Documentation:

Non-nil means use the active region text as default for search/replace.

That is, if the region is currently active then use its text as the default input. All text properties are removed from the text.

Note that in this case the active region is not used to limit the search/replacement scope. But in that case you can of course just narrow the buffer temporarily to restrict the operation scope.

A non-nil value of this option takes precedence over the use of option search/replace-2nd-sel-as-default-flag. To give that option precedence over using the active region, you can set this option to nil and use region-or-non-nil-symbol-name-nearest-point as the value of option search/replace-default-fn.

You can customize this variable.

You can also use command toggle-search/replace-region-as-default anytime to toggle the option value.


But if you really want not to even have to hit RET to accept the region text then you'll need to write a command that uses that as the FROM arg to query-replace and then interactively reads the other args.

This should do that:

(defun my-q-r (from-string to-string
               &optional delimited start end backward region-noncontiguous-p)
  "Query-replace text of active region with text you're prompted for."
  (interactive
   (progn
     (barf-if-buffer-read-only)
     (let* ((from (if (use-region-p)
              (buffer-substring (region-beginning) (region-end))
            (query-replace-read-from "Query replace" nil)))
        (to (if (consp from) (prog1 (cdr from) (setq from (car from)))
          (query-replace-read-to from "Query replace" nil))))
       (list from to
         (or (and current-prefix-arg (not (eq current-prefix-arg '-)))
         (and (plist-member (text-properties-at 0 from) 'isearch-regexp-function)
                      (get-text-property 0 'isearch-regexp-function from)))
         (and current-prefix-arg (eq current-prefix-arg '-))))))
  (deactivate-mark)
  (query-replace from-string to-string delimited start end backward region-noncontiguous-p))
2
  • Thank you, sir. It'll replace only the following occurrences but I presume I just need to add the "jump to file start" somewhere.
    – achempion
    Commented Mar 25, 2021 at 19:19
  • 1
    Yes. That's the case for query-replace commands. If you want, you can put this at the beginning of the code that defines the command: (goto-char (point-min)), after the interactive spec.
    – Drew
    Commented Mar 25, 2021 at 20:10
1
M-w M-< M-% C-y RET <replacement> RET ! 

does the trick.

5
  • 1
    I want to be able to pass the <replacement> from my kill ring as well.
    – achempion
    Commented Mar 25, 2021 at 19:13
  • 1
    You can have multiple kills in the kill-ring. C-y to yank the last killed and M-y to yank the previous ones. (info "(emacs) Yanking Early Kills"). You can also use registers (info "(emacs)registers").
    – gigiair
    Commented Mar 25, 2021 at 21:50
  • 1
    Yes, indeed, but this feature doesn't work with query-replace function (I'm using counsel-yank-pop for M-y binding).
    – achempion
    Commented Mar 26, 2021 at 5:12
  • I confirm, even the default M-y keybinding which is yank-pop doesn't work that way, because it attempts to interactively ask the text to yank, which ofc doesn't work if you are already in the minibuffer. Judging by docs it seems like passing an ARG should override such behavior, but either I'm misreading it or the docs are wrong/the function is buggy, passing an ARG does not change that behavior.
    – Hi-Angel
    Commented Mar 29, 2023 at 11:52
  • gigiair, @achempion so, good news is I found a solution to the M-y problem! It is easy to define your own function that pastes the previous kill-ring content as (defun yank-prev-killring () (interactive) (insert (nth 1 kill-ring))) and then bind it with (global-set-key (kbd "M-y") #'yank-prev-killring). Feel free to add that to the answer! ^_^
    – Hi-Angel
    Commented Mar 29, 2023 at 12:00

Your Answer

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

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