2

In LaTeX, I sometime define a command of the type \tmpcmd{TEXT\cmd{MORE TEXT}}. After I am done, I want to remove all instances of this command, so I usually do a replace-string of \tmpcmd with an empty string. However, this still leaves {TEXT\cmd{MORE TEXT}}. Is there a way to replace the previous string with TEXT\cmd{MORE TEXT} (without the braces)? I guess the main problem is matching the braces.

Also, is there a way to apply this action to multiple files at once?

3

Replacements in a single file

That is exactly the application from question "How to search/replace expressions with parantheses in emacs?" on stackoverflow.

Naturally I recommend my solution since I know that it handles the trailing sexp cleanly. I repeat that solution here since cross-site questions+answers are no duplicates and can probably be deleted on the other site.

At first install the elisp code below in your init file or evaluate it in your scratch buffer if you only need it once.

The simplest usage for replacing all occurrences within one file is to call M-x query-replace-re+sexp RET and answer what you are asked for. Use the last additional subgroup for the content of the braces.

In your special case you would input \\tmpcmd as regexp and \1 (i.e., the additional last subgoup for the sexp without the braces) as replacement.

(defun re+sexp-search-forward (regexp bound noerror)
  "Search forward for REGEXP (like `re-search-forward')
but with appended sexp."
  (when (re-search-forward regexp bound noerror)
    (let ((md (match-data))
      bsub esub)
      (setq bsub (1+ (scan-sexps (goto-char (scan-sexps (point) 1)) -1))
        esub (1- (point)))
      (setcar (cdr md) (set-marker (make-marker) (point)))
      (setq md (append md (list (set-marker (make-marker) bsub)
                (set-marker (make-marker) esub))))
      (set-match-data md)
      (point))))

(defun query-replace-re+sexp ()
  "Like `query-replace-regexp' but at each match it includes the trailing sexps
into the match as an additional subexpression (the last one)."
  (interactive)
  (let ((replace-re-search-function 're+sexp-search-forward)) (call-interactively 'query-replace-regexp)))

Replacements in multiple files

For doing that replacement in multiple files you can use re+sexp-search-forward in the same manner as re-search-forward within an elisp script.

If you don't like elisp scripting you can also use elgrep to do the replacements in multiple files.

elgrep (elisp grep) searches for matches of a regular expression within files matching a file name regular expression.

elgrep allows you to specify the actual search function. You can choose re+sexp-search-forward as search function for your objective.

The most user friendly application of elgrep is though the command elgrep-menu. It offers the menu visible in the upper window of the emacs frame depicted below. The lower window shows the matches generated by elgrep.

elgrep menu and elgrep buffer

After calling M-x elgrep-edit RET you can edit the *elgrep* buffer. Later on you can save your modifications with C-x C-s.

For safety reasons that does not really save anything on disc. It just opens the files with the matches from the *elgrep* buffer and transmits the modifications from the *elgrep* buffer there.

You can use the edit capability of the *elgrep* buffer to replace \tmpcmd{...} inclusively the braces with the content of the braces.

Do this with query-replace-re+sexp in the *elgrep* buffer as described in the above Section "Replacements in a single file".

After you have checked that the replacements meet your intention type C-x s to save the modified buffers.

At last I add the text of the test file:

\documentclass{article}

\begin{document}
In LaTeX, I sometimes define a command of the type \tmpcmd{TEXT\cmd{MORE TEXT}}.
After I am done, I want to remove all instances of this command,
so I usually do a replace-string of \tmpcmd with an empty string.
However, this still leaves {TEXT\cmd{MORE TEXT}}.
Is there a way to replace the previous string with TEXT\cmd{MORE TEXT} (without the braces)?
I guess the main problem is matching the braces.
One \tmpcmd{match that
  spans several
  lines}

Half-open and half-closed intervals \tmpcmd{ $[0,1)\cup(1,2] = [0,2]\setminus\{1\}$ }.

Also, is there a way to apply this action to multiple files at once?
\end{document}
%% Local Variables:
%% tex-master: t
%% End:
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.