I was trying to add new environments to AUCTeX doing what the RefTeX's manual says, so I added the following to my .emacs:

(add-hook 'LaTeX-mode-hook 'turn-on-reftex)

(setq reftex-label-alist
   '(("axiom"   ?a "ax:"  "~\\ref{%s}" nil ("axiom"   "ax.") -2)
     ("theorem" ?h "thr:" "~\\ref{%s}" t   ("theorem" "th.") -3)))

(add-hook 'LaTeX-mode-hook
   (lambda ()
       '("axiom" LaTeX-env-label)
       '("theorem" LaTeX-env-label))))

The problem is that i have to reference these labels manually. I've tried to do what the RefTeX manual says:

For example if you write: ‘As we have shown in Theorem’and then press C-c ), RefTeX will know that you are looking for a theorem label and restrict the menu to only these labels without even asking.

But with the following MWE

  An axiom
  A theorem

As we have shown in Theorem

it does not work, because it shows me the Axiom and the Theorem and doesn't even let me choose one (so I have to press sspace and then choose one).

What could be the problem?


2 Answers 2


As a quick fix, you can set the toc variable to nil.

From the RefTeX manual :

A negative value will make unnumbered entries. Useful only for theorem- like environments which structure the document. Will be ignored for macros.

I fail to see how theorem-like environments are supposed to structure the document, but I understand that a label with negative depth in toc isn't made for crossreferencing.

A positive value works under some circumstances for me, and doesn't under others.

(setq reftex-label-alist
   '(("axiom"   ?a "ax:"  "~\\ref{%s}" nil ("axiom"   "ax."))
     ("theorem" ?h "thr:" "~\\ref{%s}" t   ("theorem" "th."))))

TL;DR: The version of reftex that comes with emacs is based on reftex 4.31. The current version of reftex is 4.34. It contains, among others, the following two changes:

2008-05-03 Ralf Angeli

  • lisp/reftex-parse.el (reftex-parse-from-file): Move backward one char if a `\' was matched after a section macro.

2008-04-13 Ralf Angeli

  • lisp/reftex-parse.el (reftex-parse-from-file): Use beginning of match instead of end as bound.

You can also see the relevant bits here:



Those two commits fix your problem. If you'd like to know more about what the problem is, please read on :)

You've associated the type "h" with theorems (through the ?h in reftex-label-alist). If you press C-c ) after the word Theorem, reftex-reference will be called and it will guess that you want a reference of type "h". You can also explicitly call (reftex-reference "h") from anywhere. reftex-reference is just a wrapper around reftex-offer-label-menu. You can thus also just call (reftex-offer-label-menu "h") to see a list of references (except that, again, it will be empty). That function is again a wrapper around reftex-insert-docstruct that is called in a temporary read-only buffer with special navigation handling.

In reftex-insert-docstruct, information on labels is retrieved from (symbol-value reftex-docstruct-symbol), which is filled through reftex-access-scan-info. The corresponding variable contains plenty of data. Here's what matters:

If you execute the following snippet of code in your minibuffer (using M-:):

(let (ls)
  (dolist (i (symbol-value reftex-docstruct-symbol) ls)
    (when (stringp (car i))
      (push (concat "Label: " (nth 0 i) ", Type: " (nth 1 i)) ls))))

you should get the following output:

("Label: thr:1, Type: s" "Label: ax:1, Type: s")

That tells you that the labels thr:1 and ax:1 have type "s" rather than "h" and "a", respectively. You can also double-check that by replacing sspace with ss in your workflow.

In the above, reftex-access-scan-info populates reftex-docstruct-symbol. It does that by tying reftex-docstruct-symbol to a variable using reftex-tie-multifile-symbols and the calling reftex-do-parse, which calls reftex-parse-from-file.

reftex-parse-from-file parses the TeX buffer by repeatedly searching using the regular expression reftex-everything-regexp; during scanning, that will look something like this:

"\\\\label{\\([^}]*\\)}\\|\\(^\\)[  ]*\\\\\\(begin{theorem}\\|begin{axiom}\\|part\\|chapter\\|section\\|subsection\\|subsubsection\\|frametitle\\|paragraph\\|subparagraph\\|addchap\\|addsec\\)\\*?\\(\\[[^]]*\\]\\)?[[{   \n]\\|\\(^\\)[  ]*\\\\\\(include\\|input\\)[{   ]+\\([^}    \n]+\\)\\|\\(^\\)[  ]*\\(\\\\appendix\\)\\|\\(\\\\glossary\\|\\\\index\\)[[{]"

Once it finds a match, it checks what pair of parentheses contains captured something. For the theorem and axiom environments and their labels, we get two matches -- that makes these environments different from e.g. equation, since there we only get a match for the label.

The first match, for the environment, comes from reftex-section-labels-all; it's what causes the problem (as already pointed out by @T.Verron). Anything matched by that will be treated as a section (and thus get a label of type "s").

That is why replacing

(setq reftex-label-alist
   '(("axiom"   ?a "ax:"  "~\\ref{%s}" nil ("axiom"   "ax.") -2)
     ("theorem" ?h "thr:" "~\\ref{%s}" t   ("theorem" "th.") -3)))


(setq reftex-label-alist
   '(("axiom"   ?a "ax:"  "~\\ref{%s}" nil ("axiom"   "ax."))
     ("theorem" ?h "thr:" "~\\ref{%s}" t   ("theorem" "th."))))

serves as a workaround: it removes the first match.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .