Some LaTeX packages define environment-like structures without using the
standard ‘\begin..\end’ structure. RefTeX cannot parse
these directly, but you can write your own special-purpose parser and
use it instead of the name of an environment in an entry for
reftex-label-alist
. The function should check if point is
currently in the special environment it was written to detect. If so,
it must return a buffer position indicating the start of this
environment. The return value must be nil
on failure to detect
the environment. The function is called with one argument bound.
If non-nil
, bound is a boundary for backwards searches
which should be observed. We will discuss two examples.
Some people define abbreviations for
environments, like \be
for \begin{equation}
, and
\ee
for \end{equation}
. The parser function would have
to search backward for these macros. When the first match is
\ee
, point is not in this environment. When the first match is
\be
, point is in this environment and the function must return
the beginning of the match. To avoid scanning too far, we can also look
for empty lines which cannot occur inside an equation environment.
Here is the setup:
;; Setup entry in reftex-label-alist, using all defaults for equations (setq reftex-label-alist '((detect-be-ee ?e nil nil nil nil))) (defun detect-be-ee (bound) ;; Search backward for the macros or an empty line (if (re-search-backward "\\(^[ \t]*\n\\|\\\\ee\\>\\)\\|\\(\\\\be\\>\\)" bound t) (if (match-beginning 2) (match-beginning 2) ; Return start of environment nil) ; Return nil because env is closed nil)) ; Return nil for not found
A more complex example is the linguex.sty package which defines list macros ‘\ex.’, ‘\a.’, ‘\b.’ etc. for lists which are terminated by ‘\z.’ or by an empty line.
\ex. \label{ex:12} Some text in an exotic language ... \a. \label{ex:13} more stuff \b. \label{ex:14} still more stuff \a. List on a deeper level \b. Another item \b. and the third one \z. \b. Third item on this level. ... text after the empty line terminating all lists
The difficulty is that the ‘\a.’ lists can nest and that an empty line terminates all list levels in one go. So we have to count nesting levels between ‘\a.’ and ‘\z.’. Here is the implementation for RefTeX.
(setq reftex-label-alist '((detect-linguex ?x "ex:" "~\\ref{%s}" nil ("Example" "Ex.")))) (defun detect-linguex (bound) (let ((cnt 0)) (catch 'exit (while ;; Search backward for all possible delimiters (re-search-backward (concat "\\(^[ \t]*\n\\)\\|\\(\\\\z\\.\\)\\|" "\\(\\ex[ig]?\\.\\)\\|\\(\\\\a\\.\\)") nil t) ;; Check which delimiter was matched. (cond ((match-beginning 1) ;; empty line terminates all - return nil (throw 'exit nil)) ((match-beginning 2) ;; \z. terminates one list level - decrease nesting count (decf cnt)) ((match-beginning 3) ;; \ex. : return match unless there was a \z. on this level (throw 'exit (if (>= cnt 0) (match-beginning 3) nil))) ((match-beginning 4) ;; \a. : return match when on level 0, otherwise ;; increment nesting count (if (>= cnt 0) (throw 'exit (match-beginning 4)) (incf cnt))))))))