6

I'm using the following functions to speed up some regexps replacements I frequently use. jc-replace-regexp-in-region can be called by several functions like jc-dollar-to-paren. At the moment, when one of those functions completes, the region is deactivated and I have to reactivate it to execute another replace-regexp.

query-replace-regexp doesn't seem to offer an option to save the activation of the mark, and the function jc-replace-regexp-in-region explicitly sets the dectivate-mark (I don't actually know why, I didn't write it).

Ideally I'd like to be able to chain several replace-regexp on the same region without having to mark the region between each one. How can it be done ?

(defun jc-replace-regexp-in-region (Begin End from to)
  "Replace from by to in the selected region"
   (interactive "r")
   (let (deactivate-mark)
    (query-replace-regexp from to nil Begin End)))

(defun jc-dollar-to-paren (Begin End)
      "Replace $toto$ by \\(toto\\) in selected region"
      (interactive "r")
      (jc-replace-regexp-in-region Begin End "\\$\\([\n\t [:nonascii:][:ascii:]]+?\\)\\$" "\\\\\(\\1\\\\\)"))
1
  • "jc-replace-regexp-in-region explicitly sets the dectivate-mark" - no, it's only saving and restoring it after the query-replace-regexp call.
    – npostavs
    Commented Jan 5, 2016 at 20:53

2 Answers 2

4

You need to add this at the end of your command:

(setq deactivate-mark  nil)

C-h v deactivate-mark tells you this:

deactivate-mark is a variable defined in ‘C source code’. Its value is nil

Automatically becomes buffer-local when set.

Documentation: If an editing command sets this to t, deactivate the mark afterward. The command loop sets this to nil before each command, and tests the value when the command returns. Buffer modification stores t in this variable.

3
  • It seems that query-replace-regexp does deactivate the mark. It cannot be used for this purpose.
    – wilk
    Commented Jan 5, 2016 at 20:43
  • Wow, thank you! I was banging my head against an (interactive "r") function code that simply wraps the region in a template and then resets region to the piece of the template that may likely need to be replaced (I'm using the CUA mode, so typing replaces the active region). I pared down my code to only invoke (goto-char), (insert) and (push-mark)--and this solved my issue! These 3 function seem innocuous enough not to muck with deactivate-mark, who would suspect them, but it was very set to t by the end. Commented Feb 19, 2020 at 7:17
  • (insert) is the culprit. Commented Feb 19, 2020 at 7:23
1

I had to get rid of query-replace-regexp because it deactivates the mark. Here is what I came up with:

(defun jc-replace-regexp-in-region (Begin End from to)
  (interactive "r")
  (save-excursion
    (let ((deactivate-mark nil))
      (goto-char (min Begin End))
      (while (re-search-forward from nil t)
    (replace-match to nil nil)))))

(defun jc-dollar-to-paren (Begin End)
  "Replace $toto$ by \\(toto\\) in selected region"
  (interactive "r")
  (jc-replace-regexp-in-region Begin End "\\$\\([\n\t [:nonascii:] [:ascii:]]+?\\)\\$" "\\\\\(\\1\\\\\)")
  )

(defun jc-do-all-regexps (Begin End)
  (interactive "r")
  (let ((deactivate-mark nil))
    (jc-alert-or-emph-to-stars Begin End)
    ;; any other function similar to jc-dollar-to-paren
  )

Now, jc-do-all-regexps will perform several regexps search and replace in the same region, without deactivating the mark. Also, the region can be defined from beginning to end or the other way around.

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.