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\\\\\)"))
Drew
  • 75,699
  • 9
  • 109
  • 225
wilk
  • 519
  • 2
  • 11
  • "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 Jan 05 '16 at 20:53

2 Answers2

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.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • It seems that query-replace-regexp does deactivate the mark. It cannot be used for this purpose. – wilk Jan 05 '16 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. – kkm inactive - support strike Feb 19 '20 at 07:17
  • (insert) is the culprit. – kkm inactive - support strike Feb 19 '20 at 07: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.

wilk
  • 519
  • 2
  • 11