GNU Info

Info Node: (reftex)Non-Standard Environments

(reftex)Non-Standard Environments


Next: Putting it Together Prev: Using \eqref Up: Defining Label Environments
Enter node , (file) or (file)node

Non-standard Environments
-------------------------

   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 occure 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))))))))


automatically generated by info2www version 1.2.2.9