2

Say you have a figure in your org-mode file like the following one:

#+NAME: fig:first-figure
#+CAPTION: Some caption
#+BEGIN_figure
This is a figure.
#+END_figure

This is exported to LaTeX code where \label is put inside the argument of \caption:

\begin{figure}
This is a figure.
\caption{\label{fig:first-figure}
Some caption}
\end{figure}

However, this may cause problems in some templates such that the references to the figure will be ill-formed. This can be repaired by putting the \label command outside and after \caption:

\begin{figure}
This is a figure.
\caption{Some caption}
\label{fig:first-figure}
\end{figure}

Right now, I'm using macros to achieve this in the LaTeX file, but this doesn't feel right...

How can I adjust the export routine to change the order of \label and \caption?

1 Answer 1

3

I've met the same problem. The only way I've found is to redefine the function that handles that part of the export and to put it as a emacs-lisp source block at the beginning of my org file.

Here is what I did:

(defun org-latex--caption/label-string (element info)
  "Return caption and label LaTeX string for ELEMENT.

INFO is a plist holding contextual information.  If there's no
caption nor label, return the empty string.

For non-floats, see `org-latex--wrap-label'."
  (let* ((label (org-latex--label element info nil t))
     (main (org-export-get-caption element))
     (attr (org-export-read-attribute :attr_latex element))
     (type (org-element-type element))
     (nonfloat (or (and (plist-member attr :float)
                (not (plist-get attr :float))
                main)
               (and (eq type 'src-block)
                (not (plist-get attr :float))
                (null (plist-get info :latex-listings)))))
     (short (org-export-get-caption element t))
     (caption-from-attr-latex (plist-get attr :caption)))
    (cond
     ((org-string-nw-p caption-from-attr-latex)
      (concat caption-from-attr-latex "\n"))
     ((and (not main) (equal label "")) "")
     ((not main) label)
     ;; Option caption format with short name.
     (t
      (format (if nonfloat "\\captionof{%s}%s{%s}\n%s"
        "\\caption%s%s{%s}\n%s")
          (let ((type* (if (eq type 'latex-environment)
                   (org-latex--environment-type element)
                 type)))
        (if nonfloat
            (cl-case type*
              (paragraph "figure")
              (image "figure")
              (special-block "figure")
              (src-block (if (plist-get info :latex-listings)
                     "listing"
                   "figure"))
              (t (symbol-name type*)))
          ""))
          (if short (format "[%s]" (org-export-data short info)) "")
          (org-export-data main info)
          label)))))

The original function is on the ox-latex.el file of the org-mode package, if you want to have a look. What I've modified are the lines with "\caption" and "\captionof" and I've inverted the position of the two last elements. Hope this works for you.

2
  • This is great! I think it's very small change that is strictly an improvement on the current code. Please consider contirbuting this to Org, you can start by writing to the Org mailing list.
    – Omar
    Commented Jul 5, 2019 at 13:15
  • @Omar I agree. I don't see why \label needs to be inside \caption.
    – Timm
    Commented Jul 6, 2019 at 14:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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