2017-09-04 LaTeX-mark-environments

Some time ago, I wrote about a simple snippet to compile only the current Beamer frame in AUCTeX. A few days ago, I’ve been asked how to compile two consecutive environments.

Of course, the tricky part is to mark them – while LaTeX-mark-environment accepts an argument, its meaning is “how far up in the environment tree do we go”. But Emacs being Emacs, it’s not too difficult to code what we want.

(defun LaTeX-mark-environments (count)
"Mark the current and COUNT-1 following LaTeX environments."
(interactive "p")
(LaTeX-find-matching-begin)
(let ((beg (point))
(n count))
(while (> n 0)
(if (not (looking-at "[ \t\n]*\\\\begin{[a-zA-Z*]+}"))
(setq n 0)
(setq n (- n 1))
(goto-char (match-end 0))
(LaTeX-mark-environment)
(exchange-point-and-mark)))
(exchange-point-and-mark)
(goto-char beg)))


The code should be pretty much self-explanatory. Also, it is fairy simplistic and I am quite sure you can trip it somehow. (Also, negative arguments don’t work.) The assumption here is that the only thing between environments is whitespace, comments “break the chain” of environments.

Marking consecutive environments in LaTeX turns out to be trickier than e.g. marking consecutive defuns in Lisp (which is a topic deserving another post in the future), because LaTeX syntax is so free-form: not everything is enclosed in an environment. Also, unlike in the case of Lisp, we don’t have functions for moving around LaTeX syntactic elements (an issue I plan to address some day).

An interesting point may be that at first, instead of putting [ \t\n]* into the regex, I wanted to (skip-syntax-forward " ") (i.e., skip whitespace). That was a bad idea, and one of the reasons was that newline does not have syntax class “whitespace”; its class is (at least in AUCTeX) is “endcomment”. Who would guess? But when I saw that skip-syntax-forward (which see) does not go past newlines, I put the point at one and pressed C-u C-x =. In a second I knew what the syntax class of newline was. This is one of the coolest things about Emacs – you can ask it about its state, and get answers in no time.

And really, my point here is not that I can write a sophisticated, bullet-proof, interactive Emacs command in twenty minutes. Frankly, I can’t. The point is that you can write such a quick-and-dirty function doing its job well enough very quickly, save yourself tedious typing, and feel good about making your favorite tool do exactly what you want.