2

I am using RefTeX to create/reference labels within LaTeX documents.

When writing definitions, I usually write the "name" of whatever I'm defining as emphasised text in the beginning of the definition environment, and I usually put the label just after \begin{definition}. Therefore, I would like RefTeX to do a forward search from the label macro for the text to use as label.

I've managed to get backward search working by following the RefTeX User Manual

Here is the relevant part of my .emacs file:

(setq reftex-label-alist
  '(
     ("theorem"    ?h "thm:" "~\\ref{%s}" t ("theorem" "thm.") )
     ("lemma"      ?l "lem:" "~\\ref{%s}" t ("lemma" "lem.") )
     ("corollary"  ?c "cor:" "~\\ref{%s}" t ("corollary" "cor." ))
     ("definition" ?d "def:" "~\\ref{%s}" "\\emph[[{]" ("definition" "def." ))
   )
  reftex-insert-label-flags '(t t))

I can find no mention of forward search in the Documentation, so I fear this is not something that is supported by default. There is the option of defining a function for the context-method, but I am not familiar enough with (Emacs) Lisp to write such a function.

Any help on this matter will be much appreciated.

As per request, here is a MWE:

\documentclass{article}

\usepackage{amsthm}
\newtheorem{definition}{Definition}

\begin{document}

\begin{definition}
  A \emph{thing} is something that has a lot of useful properties.
\end{definition}

\end{document}

I would like that when I insert a label (using RefTeX) just after \begin{definition}, RefTeX automatically uses the word thing as the label, i.e. the resulting line should read

\begin{definition}\label{def:thing}
  • 1
    Have you considered using cleverref instead? It can extract the name from the label. (I personally use a similar unreleased package, that adds the name from the label prefix, it is not as intrusive as cleverref might be) – daleif Sep 5 '17 at 8:46
  • @daleif I will have a look at cleverref. Thank you very much. – AcId Sep 5 '17 at 8:47
  • 1
    @daleif: The package is named cleveref .... I stumbled so many times over this typo myself. – user31729 Sep 5 '17 at 11:38
  • @ChristianHupfer I should have guessed. As mentioned I don't use it myself, preferring something a bit more simple. – daleif Sep 5 '17 at 12:07
  • Are you also using AUCTeX? Can you add a MWE to your question showing the final product you're looking for? – Arash Esbati Sep 6 '17 at 18:50
1

Problem

AUCTeX comes already with a style file for amsthm providing completion, parsing etc. But it is not easy to hook your requirements into that style, hence, I suggest you write a new LaTeX package myamsthm with the respective AUCTeX support file.

Prerequisite

You'll need this in your .emacs:

(setq TeX-parse-self t)

Next, you need to customize the variable TeX-style-private to a directory of your choice, e.g.:

(setq TeX-style-private "~/.emacs.d/mystyles")

I prefer to have something like this

(setq reftex-insert-label-flags '("shlcd" "sft"))

in my .emacs instead of

(setq reftex-insert-label-flags '(t t)

but that is your choice.

A wrapper package myamsthm.sty can look like this:

\ProvidesPackage{myamsthm}[2017/09/08]
\RequirePackage{amsthm}
\newtheorem{definition}{Definition}
\newtheorem{lemma}{Lemma}
% etc.
\newcommand\envcontext{}
\let\envcontext\emph

Save this file somewhere LaTeX finds it. I suggest you use a macro like \envcontext instead of plain \emph.

myamsthm.el

Save the following code as myamsthm.el in the directory mentioned above and restart Emacs.

(defun LaTeX-myamsthm-env-label (environment)
  "Insert ENVIRONMENT, an optional argument, a reference and label."
  (let ((opthead (TeX-read-string
                  (TeX-argument-prompt t nil "Heading"))))
    (LaTeX-insert-environment environment
                              (when (and opthead
                                         (not (string= opthead "")))
                                (format "[%s]" opthead))))
  (let ((envcontext (TeX-read-string
                     (TeX-argument-prompt nil nil "Environment context"))))
    (unless (zerop (length envcontext))
      (indent-according-to-mode)
      (save-excursion
        (insert TeX-esc "envcontext" TeX-grop envcontext TeX-grcl))))
  (when (LaTeX-label environment 'environment)
    (LaTeX-newline)
    (indent-according-to-mode)))

(defun LaTeX-myamsthm-reftex-label (_environment)
  "Search for context of environment and pass it to RefTeX.
ENVIRONMENT is ignored."
  (if (save-excursion
        (re-search-forward
         "\\\\envcontext{\\([^}]+\\)}"
         (save-excursion
           (re-search-forward
            (concat "\\\\end{" (LaTeX-current-environment))))
         t))
      (match-string-no-properties 1)
    (error "Could not find the \"\\envcontext\" macro")))

(TeX-add-style-hook
 "myamsthm"
 (lambda ()

   (TeX-run-style-hooks "amsthm")

   (dolist (env '(("theorem" . "thm:")
                  ("lemma"   . "lem:")
                  ("corollary"  . "cor:")
                  ("definition" . "def:")))
     (LaTeX-add-environments `(,(car env) LaTeX-myamsthm-env-label))
     (add-to-list 'LaTeX-label-alist env))

   ;; Reftex support: Use `reftex-add-label-environments'
   (when (fboundp 'reftex-add-label-environments)
     (reftex-add-label-environments
      '(("theorem"    ?h "thm:" "~\\ref{%s}" (nil . LaTeX-myamsthm-reftex-label) ("theorem" "thm."))
        ("lemma"      ?l "lem:" "~\\ref{%s}" (nil . LaTeX-myamsthm-reftex-label) ("lemma" "lem."))
        ("corollary"  ?c "cor:" "~\\ref{%s}" (nil . LaTeX-myamsthm-reftex-label) ("corollary" "cor." ))
        ("definition" ?d "def:" "~\\ref{%s}" (nil . LaTeX-myamsthm-reftex-label) ("definition" "def." )))))

   (TeX-add-symbols
    '("envcontext" t))

   ;; Fontification
   (when (and (featurep 'font-latex)
              (eq TeX-install-font-lock 'font-latex-setup))
     (font-latex-add-keywords '(("envcontext" "{"))
                              'textual)))
 LaTeX-dialect)

I will not describe the code above, but now, you can do C-c C-e definition RET and you get completion and the final code will look like this:

\begin{definition}
  \label{def:thing}
  A \envcontext{thing} is something that ...
\end{definition}

The function you were asking for is LaTeX-myamsthm-reftex-label.

  • Thank you so much! This works exactly the way I wanted; and I can imagine it must have taken quite some time to write. One question though: with the reftex-add-label-environments and LaTeX-add-environments sections in your code. Can I remove setq reftex-label-alist and LaTeX-add-environments from my .emacs file? – AcId Sep 15 '17 at 11:53
  • 1
    @AcId - You're welcome, glad it helps. Indeed, you can now remove your additions from your .emacs. You can now add any new definitions to (dolist (env '(... and (reftex-add-label-environments '(... in the .el file. They become effective each time you load a .tex file with \usepackage{myamsthm} in it. Also note that I updated my answer, please use the updated code. – Arash Esbati Sep 15 '17 at 12:33

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.