How to determine whether a list of figures is empty, then not show it at all?

I want to check whether the document has any figures so as to decide whether or not to have a list of figures. Is this possible? Feasible without doing something like parsing the lof file?

Note that checking whether the lof file is empty is not a good enough solution for me, as some code may be writing things other than table lines into it (e.g. babel).

-
What about checking whether the *.lof (and *.lot) file exists at all? –  Thorsten Donig Oct 31 '11 at 18:08
@ThorstenDonig: \listoffigures calls \@starttoc{lof} which creates/writes to \jobname.lof. So \jobname.lof only exists based the call \listoffigures. Checking for its existence is therefore "too late". –  Werner Oct 31 '11 at 21:27

The idea behind this attempt is to use standard LaTeX references in order to detect whether a figure was used in the document. Here are the steps involved (with some modifications by @egreg):

1. Conjure up a label name that you won't use in your document, ever. Something like fig:was:used:in:doc.
2. Patch the figure environment to define an empty command (say) \there@is@a@figure at the end of every figure. This is possible using the etoolbox package which provides \AtEndEnvironment. More specifically, the command

\AtEndEnvironment{figure}{\gdef\there@is@a@figure{}}


will be perpetually redefined until the last figure in the document.

3. At the end of the document, we check whether \there@is@a@figure exists (is defined), and define a label \label{fig:was:used:in:doc}. It doesn't really matter what this label contains (it could be the last used figure, section, table, or whatever):

\AtEndDocument{\ifdefined\there@is@a@figure\label{fig:was:used:in:doc}\fi}

4. Write your own "conditional LoF" command using

\newcommand{\conditionalLoF}{\@ifundefined{r@fig:was:used:in:doc}{}{\listoffigures}}%


The command \conditionalLoF checks whether the macro \r@fig:was:used:in:doc is defined or not. This is the standard LaTeX referencing mechanism at work, since each label <lab> has an associated macro \r@<lab> defined. \@ifundefined{<cs>}{<undef code>}{<def code>} allows execution of <undef code> if <cs> is undefined, otherwise execute <def code>.

5. Use \conditionalLoF instead of \listoffigures.
6. Compile your document at least 3 times.

The main idea behind (1) is to have the label fig:was:used:in:doc only exist when using a figure, and not having to worry about what it is called. (2) provides the hook to the figure environment and allows a global (re)definition of \there@is@a@figure. (3) delays the definition of the fig:was:used:in:doc label until the end of the document in order to avoid causing "Multiply defined label" warnings. (4) and (5) provides a clean interface to the conditional LoF. (6) may be the only drawback. However, this comes standard with label referencing, requiring at least two compiles to work in general.

Here's a minimal working example (MWE). It uses graphicx (with the demo package option) and lipsum merely for show and is therefore actually not necessary. Compiling this MWE

\documentclass{article}
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\usepackage[demo]{graphicx}% http://ctan.org/pkg/graphicx
\usepackage{lipsum}% http://ctan.org/pkg/lipsum
\makeatletter
\AtEndEnvironment{figure}{\gdef\there@is@a@figure{}}
\AtEndDocument{\ifdefined\there@is@a@figure\label{fig:was:used:in:doc}\fi}
\newcommand{\conditionalLoF}{\@ifundefined{r@fig:was:used:in:doc}{}{\listoffigures}}%
\makeatother
\begin{document}
\conditionalLoF% Conditionally insert List of Figures
\section{First section}
\lipsum[1]
%\begin{figure}
%  \centering\includegraphics{figure}
%  \caption{This is a caption}
%\end{figure}
\end{document}


as-is produces

Uncommenting the figure environment and compiling a couple of times produces

-
This will cause spurious "Multiply defined label" messages. –  egreg Oct 31 '11 at 17:07
I've added code that won't show the problem, you can integrate it into your answer (the idea is just the same). –  egreg Oct 31 '11 at 17:16
Absolutely correct. Is there a way to append (say) a counter to the label fig:was:used:in:doc and then only check for (say) \r@fig:was:used:in:doc:1? –  Werner Oct 31 '11 at 17:17
You'll have seen my addition, by now. :) –  egreg Oct 31 '11 at 17:17
Thanks, I'll give this a try in my document, but - there are a few buts: 1. This seems only to work for figures, not for a Table of Contents or other such tables. 2. Someone might write a "myfigure" environment which adds to the list of figures using whatever sub-command used by the figure environment, and I will be none the wiser. 3. I would rather, if possible, use the mechanism the figure environment uses to add entries to the list, rather than create a new and idiosyncratic one. –  einpoklum Oct 31 '11 at 21:21

One could use the assoccnt package where you can associate a counter with some other master counter, stepping it in tandem. At the end of the document, you write out a \label that would capture the existing total count of the associated counter. Then, using refcount's expandable \getrefnumber, a conditional LoF (or other Table of Contents structure) could be printed.

\documentclass{article}
\usepackage{graphicx,lipsum,assoccnt,refcount}
\newcounter{totfigure}% This will capture the total number of figures
\DeclareAssociatedCounters{figure}{totfigure}% Step totfigure with every figure
\makeatletter
\AtEndDocument{%
\edef\@currentlabel{\arabic{totfigure}}% Update current \label value
\label{tot:figs:used:in:doc}}% Mark \label
\newcommand{\conditionalLoF}{%
\ifnum\getrefnumber{tot:figs:used:in:doc}>0 % Check whether 'totfigure' > 0
\listoffigures\fi}% If so, print \listoffigures
\makeatother
\begin{document}
\conditionalLoF% Conditionally insert List of Figures
\section{First section}
\lipsum[1]
%\begin{figure}
%\centering\includegraphics[width=.5\linewidth]{example-image}
%\caption{This is a caption}
%\end{figure}
\end{document}

-