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.

alper
  • 1,238
  • 11
  • 30

1 Answers1

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.

dalanicolai
  • 6,108
  • 7
  • 23
  • 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 02 '22 at 01: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` – dalanicolai May 02 '22 at 08: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 02 '22 at 10:13
  • It does not work with `emacs -Q` changin `gas_cost` into `gascost` :-( – alper May 02 '22 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 ;) – dalanicolai May 02 '22 at 13:18
  • Could this pattern `\([[:space:]{]\|^\)+_cost` embedded into the function and act as its default behavior? Like if I give `_cost` , the function convert it into the pattern – alper May 10 '22 at 14:04
  • Of course it can. I have updated the answer accordingly. – dalanicolai May 10 '22 at 15:04
  • thanks a lot . . – alper May 10 '22 at 15:46
  • 2nd solution does not generated wanted changes, and changes gas_costs to gascosts. The first solution does not ask what to changed with as interactive input and also it does not apply changes to complete buffer by default, when I try to apply `query-replace-region-or-from-top` generates: `The mark is not set now, so there is no region `. Is it possible to select the region as complete buffer by default and ask what to replace with? – alper Jul 04 '22 at 22:16
  • `_cost` => `cost` was just an example, it can be `_cost` => `emacs123` or anything. I just wanted apply replace operation to replace matches same as the find words/patterns in `isearch-forward-symbol-at-point` – alper Jul 04 '22 at 22:16
  • Sorry, I don't understand your questions: 'select the region as complete buffer by default' and 'apply replace operation to replace matches same as the find words/patterns in isearch-forward-symbol-at-point'. I do not understand those... – dalanicolai Jul 05 '22 at 04:26
  • When you try following solution it iterates from top of the buffer to down to apply replace https://emacs.stackexchange.com/questions/249/how-to-search-and-replace-in-the-entire-buffer/50624#50624 (which is also in my question)// and in `isearch-forward-symbol-at-point` when you search for `_cost` it does not found `_cost` in the `gas_cost` since it search for the words – alper Jul 05 '22 at 09:51
  • I have also added another example related to this – alper Jul 05 '22 at 09:56
  • You should have a look at [this](https://www.gnu.org/software/emacs/manual/html_node/emacs/Regexp-Backslash.html) and [this](https://www.gnu.org/software/findutils/manual/html_node/find_html/emacs-regular-expression-syntax.html), especially the `\b`, `\<` and `\_<`. Then practice a little/do some tests using `replace-regexp` or `regexp-builder`. – dalanicolai Jul 07 '22 at 06:17
  • I am not experienced in writing lisp language and its difficult for me to understand and debug. The question I asked should be straight to point where I just want to replace patterns as word same as `isearch` finds. Because first I always search patterns in `isearch` and than replace them but hence all diffierent matched patterns also changed in replace-all – alper Jul 07 '22 at 08:14