Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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).

share|improve this question
    
What about checking whether the *.lof (and *.lot) file exists at all? –  Thorsten Donig Oct 31 '11 at 18:08
1  
@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

1 Answer 1

up vote 10 down vote accepted

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

enter image description here

Uncommenting the figure environment and compiling a couple of times produces

enter image description here

share|improve this answer
1  
This will cause spurious "Multiply defined label" messages. –  egreg Oct 31 '11 at 17:07
1  
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
1  
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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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