# Multiline regex replace within elisp function

I would like to write a elisp function that corrects a few formatting issues in my LaTeX code. Precisely, I would like to transform the following text

Some useless text
$$some math stuff$$
Further text.


into

Some useless text
%
$$some math stuff$$
%
Further text.


i.e. I want that equation environments that are not surrounded by comments get an empty comment line before and after the environment. My idea was to write a small elisp function that replaces all such occurences with some regex. With lots of trial and error I found the following regex that seems to find the \begin{equations} that are not preceeded by % in the line before.

^[[:space:]]*[^%].*\n[[:space:]]*\\\


I also found the following snippet on the internet to do search an replace:

(defun foo ()
(interactive)
(save-excursion
(beginning-of-buffer)
(while (re-search-forward "foo\nbar" nil t)
(replace-match "bar\nfoo" nil nil))))


My guess is the a clever combination of these things will give me my result, but so far all my attempts have failed. Can anybody give me some hints on how I achieve the sought substitution?

Update:

After reading: Emacs regexp groups in regex-replace I came up with the following:

(defun foo ()
(interactive)
(save-excursion
(beginning-of-buffer)
(while (re-search-forward "\$$^[[:space:]]*[^%].*\n\$$\$$[[:space:]]*\$$\$$\\\\$$" nil t)
(replace-match "\\1\\2%\n\\2\\3" nil nil))))


which seems to work for the few test cases that I tried so far. It fails when terms are nested immediately after each other, but since this is not allowed in LaTeX anyway its not a critical issue.

• Don't try to do it all in one regexp. It's much simpler to search for begin/end macros and than look at the line before or after and maybe insert a comment. – politza Apr 14 '15 at 8:21
• I'm not sure how this could solve my problem. With your suggestion I would have to search all begin\end occurences and perform a second search in their vicinity to see if there is a commented line.In my opinion its simpler to look for lines that do not contain a comment and are followed by a line containig a \begin. – Laurent Apr 14 '15 at 11:25

Here's something quick I came up with. It looks like it can catch situations when equations follow each other, but do tell if I missed some corner cases:

(defun my/wrap-equation-with-% ()
(interactive)
(save-excursion
(beginning-of-buffer)
(let ((last ""))
(while (not (eobp))
(search-forward-regexp "^.*\$" nil t)
(let ((line (match-string 0)))
(cond
((and (not (string-equal last "%"))
(s-starts-with-p "\\begin{equation" (s-trim-left line)))
(move-beginning-of-line 0)
(forward-line)
(insert "%\n"))
((and (s-starts-with-p "\\end{equation" (s-trim-left last))
(not (string-equal line "%")))
(move-end-of-line 0)
(insert "\n%")
(forward-line)))
(setf last line)
(forward-line))))))


Ah, this also uses s-starts-with from https://github.com/magnars/s.el

• I tried it with the following test case:  XXX  and got  % XXX % – Laurent Apr 14 '15 at 12:32
• New comment, because I'm struggling with the formatting and the 5 Minute time limit for editing comments: I tried it with the following test case: XXX and got % XXX % also your approach hangs on my system. I have to abort it with C-g. – Laurent Apr 14 '15 at 12:40
• @Laurent you can either add your example to the question, or try pastebin.org something in that vein. – wvxvw Apr 14 '15 at 15:18
• @Laurent I've made some edits, so that it won't get stuck, can you see if that does what you want it to when the equations are nested? – wvxvw Apr 14 '15 at 15:29
• I tried your solution. As far as I can see, it works and it looks definitely better than my regex approach. – Laurent Apr 14 '15 at 15:37