1

I am using following solution (How do I add a keybinding to use during an interactive isearch, `C-s ...`) to move over symbols in the buffer, which iterates over the matching symbols:

(define-key isearch-mode-map (kbd "C-w")
  'isearch-forward-symbol-at-point)

Is it possible to apply same manner into replace-all where instead of text it replaces the symbols (where the isearch-forward-symbol-at-point iterates over):

My query replace function, which replace all the matching query instead of only the symbols:

(defun query-replace-region-or-from-top ()
  (interactive)
  (let ((case-fold-search nil))
    (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)))))

(global-set-key "\C-x\C-r"  'query-replace-region-or-from-top)

Example_1:

gas_costs = 100
_cost = 10
log(f"==> cost={_cost}")

Replace-all _cost into cost

=> changes into:

gascosts = 100
cost = 10
log(f"==> cost={cost}")

wanted:

gas_cost = 100  # should remain unchanged
cost = 100
log(f"==> cost={cost}")

Example_2:

alper = 100
alper99 = 99

Replace-all alper into sad

=> changes into:

sad = 100
sad99 = 99

wanted:

sad = 100
alper99 = 99

I just want to replace patterns as exactly same with isearch finds. Because first I always search patterns using isearch and than replace them. But if there are diffierent matched patterns in replace-all, I get end up replacing differect results than isearch finds.

1 Answer 1

2

EDIT in response to the question in your comment

To use the regexp pattern as a default in your function, you could use the following code (note that here I have also somewhat improved the regexp and replace patterns):

(defun query-replace-region-or-from-top (pattern &optional beg end)
  (interactive "sEnter symbol: \nr")
  (let ((case-fold-search nil)
        (regexp (concat "\\([[:blank:]{]\\|^\\)" pattern)))
    (save-excursion
      (goto-char (point-min))
      (apply #'query-replace-regexp
             regexp
             (concat "\\1" (substring pattern 1))
             nil
             (when (use-region-p)
               (list beg end))))))

Note that I have also added the default replace pattern, which is the pattern minus the starting _. If you don't want that, then you could ask for a second string in the interactive form, and use that for the replacement pattern. Or you could only ask for the replacement pattern and automatically 'compose' the regexp pattern. Of course, I don't know your exact use case(s).

END EDIT

From your explanation, it is not clear to me what you are asking exactly (e.g. what is replace-all). But it looks to me that the answer to your 'main' question is that you are actually looking for (query-)replace-regexp.

E.g. to solve the problem of your example, you can use query-replace-regexp using the following regexp \([[:space:]{]\|^\)+_cost (and replace with cost).

Some comments about your function:

  • the progn is redundant, as you are already within a let (and so the second let is also redundant).
  • you are setting the orig-point and jump back to it, while you are also using save-excursion within. So to me, the save-excursion looks ineffective. To get the same effect, you can just wrap the whole if in save-excursion.

However, maybe you want something like the following:

(defun query-replace-region-or-from-top (&optional mark)
  (interactive "m")
  (let ((case-fold-search nil))
    (cond ((use-region-p)
           (call-interactively 'query-replace-regexp)
           (goto-char (min region)))
          (t
           (save-excursion
             (goto-char (point-min))
             (call-interactively 'query-replace-regexp))))))

You could alternatively use the interactive code r, if you would like to jump back to either the beginning or the end of your region.

15
  • Ah replace-all is not correct way to put it. I just wanted to search and replace in the entire buffer starting from first appearance in the buffer till end. When I tried your solution it replaces the _cost int gas_cost which I don't want
    – alper
    May 2, 2022 at 1:49
  • 1
    Well, I am not sure what you have tried, but with the regexp pattern I provided, the _cost in gas_cost should not get replaced, and it works like expected here. I am sure that the pattern is correct. Please try again, maybe using emacs -Q May 2, 2022 at 8:18
  • Let me try with a empty file ; I put to end of my init file maybe something was preventing it to work as it should be
    – alper
    May 2, 2022 at 10:13
  • It does not work with emacs -Q changin gas_cost into gascost :-(
    – alper
    May 2, 2022 at 12:36
  • 1
    You should use the pattern \([[:space:]{]\|^\)+_cost (copy-paste it) after doing M-x query-replace-region-or-from-top (the version I've posted here). Otherwise, I am not sure what kind of Emacs you are using ;) May 2, 2022 at 13:18

Your Answer

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

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