0

Following this StackOverflow question, I coded this function to clean up text pasted from other sources, such as Google Docs:

(defun sanitize-md ()
  "Replace characters."
  (interactive "*")
  (save-excursion
    (let ((replacement-list '(
                              ("\\" . "/")
                              ("fi" . "fi")
                              ("“" . "\"")
                              ("”" . "\"")
                              )))
      (while (let* ((pair (pop replacement-list))
                    (to-find (car pair))
                    (to-replace (cdr pair)))
               (message "%s %s" to-find to-replace)
               (query-replace to-find to-replace nil (point-min) (point-max))
               )
        replacement-list)
      )))

My problem is the curly double quote , which I have in a document. When I run this function, I get this in the *Messages* buffer:

\ /
Mark set
Replaced 0 occurrences

If I remove the line on query-replace, then the *Messages* buffer shows all four pairs. And if I put the double-quote pair as the first element of the list, then it gets replaced.

Why does query-replace stop at the first element of the dolist, and how can I code the replacement of all pairs?

2 Answers 2

1

If you try to match the form (while COND BODY) to what you have above, you will see that COND matches

(let* ((pair (pop replacement-list))
       (to-find (car pair))
       (to-replace (cdr pair)))
       (message "%s %s" to-find to-replace)
       (query-replace to-find to-replace nil (point-min) (point-max))
)

and BODY is just replacement-list. The while evaluates the COND and loops as long as its value is t. But in this case the value of the COND is the value of the last form in the let*, i.e. the value of (query-replace ...): since that does not find anything to replace with the first pair, it returns nil - so the value of the COND is nil and the while is done.

It may be that you have misplaced some parentheses and you really meant to write this:

      (while  (let* ((pair (pop replacement-list))
                     (to-find (car pair))
                     (to-replace (cdr pair)))
        (message "%s %s" to-find to-replace)
        (query-replace to-find to-replace nil (point-min) (point-max))
        replacement-list))
1
  • 1
    Yes, it was a bug in the original StackOverflow answer and I have now edited it too.
    – emonigma
    Commented Aug 20, 2020 at 13:03
1

You are using while, not dolist, while stops when the TEST condition returns nil, not sure about the value of query-replace, but it definitely does not do what you want.

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.