2

I am writing a piece of lisp code employing the function query-replace. After this function runs, I'd like to know how many replacements were effectively done. At first this seems easy because the return value of query-replace is a list whose elements precisely describe each attempted replacement, including whether or not the user answered y or n when queried.

However, in case a user replies with q or RET, signaling their intention to exit, the return value becomes nil, even if a few replacements were performed before the exit request, so the return value says nothing about the number of replacements.

One solution I found is based on the fact that the number of replacements is shown in the mini-buffer, as well as recorded in the *Messages* buffer, regardless of whether or not the command exits prematurely. So one could parse the last line of the *Messages* buffer in search for the desired number of replacements, but I feel there might be a more elegant alternative. Any ideas?

2 Answers 2

4

As mentioned by @db48x, indeed, reporting a bug would be a good thing to do, as I guess that docstring should say "DID cancel the call". Also, there might be a small chance that the function could be changed to make it do what you require.

That said. If you are not planning to publish your code, but just want to be pragmatic, then I think there is no problem with parsing the content of the last message, you could simply advise the original function as follows:

(defun query-replace-return-count-advice-function (&rest _)
  (string-to-number (cadr (string-split (current-message)))))

(advice-add 'query-replace :after #'query-replace-return-count-advice-function)

Indeed, I could not come up with a simpler/more elegant solution, e.g. by advising the function in some other way.

3
  • This is certainly nicer than my idea of parsing the *Messages* buffer. Thanks! As you say, I believe there is no way to obtain the value of a local variable, such as replace-count within perform-replace by means of some mechanism similar to advising a function, right?
    – Ruy
    Commented Sep 29, 2022 at 19:38
  • At least I don't know of any... Commented Sep 29, 2022 at 21:37
  • 2
    FYI, the bug report has been accepted and the docstring will be fixed in Emacs 29. However, even if some developpers did acknowledge the advantage of changing the output of perform-replace, the fact that the change would have a cascading effect on several other functions, resulted in the decision that no change will be made. See debbugs.gnu.org/cgi/bugreport.cgi?bug=58177
    – Ruy
    Commented Oct 2, 2022 at 18:27
2

The documentation of perform-replace says:

This function returns nil if and only if there were no matches to
make, or the user didn't cancel the call.

So maybe you have found a bug; probably best to use M-x report-emacs-bug.

That said, parsing the content of the *Messages* buffer should never be your first solution to any problem. Read the source instead to find out how that message is produced. You may find that the source information is readily available.

2
  • Thanks for your answer and for suggesting the bug report, which I already did: debbugs.gnu.org/58177. I agree that parsing the *Messages* buffer is an awkward solution and this is precisely my reason for asking my question. Regarding the source, I did read it prior to coming here, but couldn't get any inspiration.
    – Ruy
    Commented Sep 29, 2022 at 18:20
  • It is a rather hard function to read.
    – db48x
    Commented Sep 29, 2022 at 23:19

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.