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?


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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.