3

I'm using this answer to control the appearance and order of float captions in a document. The relevant part is:

\renewcommand{\thetable}{S\arabic{table}}
\usepackage{tocloft}
\makeatletter
\newcommand{\listfloatname}{\normalsize Contents:}
\newlistof{float}{flt}{\listfloatname}
\long\def\@caption#1[#2]#3{%
\par
\refstepcounter{float}%
\addcontentsline{\csname ext@#1\endcsname}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{\ignorespaces #2}}%
\addcontentsline{flt}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{ #2}}%
\begingroup
\@parboxrestore
\if@minipage
  \@setminipage
\fi
\normalsize
\@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
\endgroup}
\makeatother

This is used to label floats in order of appearance in a certain document. However, when I try and use \ref to reference a float, the additional S character does not appear. It works perfectly if I remove the above section, but I need to retain the functionality.

Here is a MWE:

\documentclass{article}
\usepackage{tocloft}
\renewcommand{\thetable}{S\arabic{table}}
%% TOC handling
\makeatletter
\newcommand{\listfloatname}{\normalsize Contents:}
\newlistof{float}{flt}{\listfloatname}
\long\def\@caption#1[#2]#3{%
\par
\refstepcounter{float}%
\addcontentsline{\csname ext@#1\endcsname}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{\ignorespaces #2}}%
\addcontentsline{flt}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{ #2}}%
\begingroup
\@parboxrestore
\if@minipage
  \@setminipage
\fi
\normalsize
\@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
\endgroup}
\makeatother


\begin{document}
    \begin{table}
    \caption[Short title]{A table \label{table:a_label}}
    \begin{tabular}{c|c}
        1 & 2 \\
        3 & 4
    \end{tabular}
    \end{table}
    As in \ref{table:a_label}
\end{document}
6
  • As I can see the \@caption is totally changed for all floats then? Why should \thetable be called by your 'float' counter caption at all? This is weird!
    – user31729
    Commented Jan 4, 2017 at 17:35
  • @ChristianHupfer I confess I don't really understand how the \caption is redefined. It is supposed to count the total number of floats, so that it can produce a sorted contents list in order of appearance in the document. But the caption label (in the table) does have the S, so it must call the \thetable...
    – JP Janet
    Commented Jan 4, 2017 at 17:54
  • With 'order of appearance' you mean the order in the output document, not in the order of specification?
    – user31729
    Commented Jan 4, 2017 at 19:27
  • Yes, in the output document. I needed to make a single contents list for all floats, in the order in which they appear in the final document. I got this code from Jagath's answer to the linked question, and it does exactly what is required, but it breaks \ref
    – JP Janet
    Commented Jan 4, 2017 at 19:34
  • The answer is quite easy (after thinking :D)
    – user31729
    Commented Jan 4, 2017 at 19:40

2 Answers 2

3

This took me some minutes to understand why the reference is wrong.

Well, the table counter is increased already by the \caption command, before \@caption is called, so \refstepcounter{float} will overwrite the \@currentlabel definition, which is used by \label to write the relevant information to the .aux file.

Solution: As long as your particular float shall not be referred to as float don't use \refstepcounter but \stepcounter.

\documentclass{article}
\usepackage{tocloft}
\renewcommand{\thetable}{S\arabic{table}}
%% TOC handling
\makeatletter
\newcommand{\listfloatname}{\normalsize Contents:}
\newlistof{float}{flt}{\listfloatname}
\long\def\@caption#1[#2]#3{%
\par
\stepcounter{float}% No refstepcounter here!
\addcontentsline{\csname ext@#1\endcsname}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{\ignorespaces #2}}%
\addcontentsline{flt}{#1}%
 {\protect\numberline{\csname the#1\endcsname}{ #2}}%
\begingroup
\@parboxrestore
\if@minipage
  \@setminipage
\fi
\normalsize
\@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
\endgroup}
\makeatother


\begin{document}
\listoffloat
\begin{table}
  \caption[Short title]{A table \label{table:a_label}}
  \begin{tabular}{c|c}
    1 & 2 \\
    3 & 4
  \end{tabular}
\end{table}
As in \ref{table:a_label}
\end{document}

enter image description here

1

If the only thing you're doing is creating a .flt file to contain each of your floats (perhaps a combination of figures and/or tables), you don't have to redefine the entire \@caption. Instead, insert the relevant contents addition using an etoolbox patch; it's much cleaner:

enter image description here

\documentclass{article}

\usepackage{tocloft,etoolbox}

\renewcommand{\thetable}{S\arabic{table}}

\newcommand{\listfloatname}{\normalsize Contents:}
\newlistof{float}{flt}{\listfloatname}

\makeatletter
\patchcmd{\@caption}% <cmd>
  {\addcontentsline}% <search>
  {\addcontentsline{flt}{#1}{\protect\numberline{\csname the#1\endcsname}{#2}}%
   \addcontentsline}% <replace>
  {}{}% <success><failure>
\makeatother

\begin{document}

\listoffloat

\begin{table}
  \centering
  \caption[Short title]{A table \label{table:a_label}}
  \begin{tabular}{c|c}
    1 & 2 \\
    3 & 4
  \end{tabular}
\end{table}
As in \ref{table:a_label}.

\end{document}

You may even get away with adapting \addcontentsline to insert content into an .flt file every time it is sent content that should go into the .lof or .lot:

enter image description here

\documentclass{article}

\usepackage{tocloft}

\renewcommand{\thetable}{T\arabic{table}}
\renewcommand{\thefigure}{F\arabic{figure}}

\newcommand{\listfloatname}{\normalsize Contents:}
\newlistof{float}{flt}{\listfloatname}

\let\oldaddcontentsline\addcontentsline
\renewcommand{\addcontentsline}[3]{%
  \oldaddcontentsline{#1}{#2}{#3}% Default addition to contents file
  \ifnum\pdfmatch{#1}{lot,lof}=1 % A table or figure...
    \oldaddcontentsline{flt}{#2}{#3}% ...also add to .flt
  \fi
}

\begin{document}

\listoffloat

\section{A section}

A table~\ref{tbl:table} and figure~\ref{fig:figure}.

\begin{table}
  \centering
  \caption[Short title]{A table \label{tbl:table}}
\end{table}

\begin{figure}
  \centering
  \caption[Short figure]{A Figure \label{fig:figure}}
\end{figure}

\end{document}

You must log in to answer this question.

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