2

I want to print the Bibliography slide only if there were any citations in the presentation. To that end I have redefined the \cite command to include the toggling of a boolean. I tried multiple versions to redefine the command as well as different ways to define booleans. The redefined version of the command contains a \typeout for debugging purposes and that's triggered as shown by pdflatex' log. Nevertheless the MWE below does print showbib false and I am probably missing something obvious but can't figure it out. :( If I toggle the boolean manually in the text with \showbibtrue it actually works.

Why doesn't \showbibtrue work within \cite?

FWIW, I have tested it to be not related to beamer (feel free to test/provide a solution with article instead).

\documentclass{beamer}
\usepackage[utf8]{inputenc}
\usepackage{filecontents}

\begin{filecontents*}{bib.bib}
@misc{foo,
  author="foo bar",
  title="getting things done",
}
\end{filecontents*}

\let\oldcite\cite
\newif\ifshowbib
\showbibfalse
\renewcommand{\cite}{\showbibtrue\typeout{within cite}\oldcite}

\begin{document}

\begin{frame}{sigh}
  \cite{foo}
\end{frame}

\ifshowbib
  \begin{frame}[c,allowframebreaks]{Bibliography}
    \typeout{showbib true}
    showbib true
    \bibliography{bib}
  \end{frame}
\else
  \typeout{showbib false}
  showbib false
\fi

\end{document}
stefanct
  • 841
  • 6
  • 16
  • Related: https://tex.stackexchange.com/questions/146348/conditional-bibliography-insertion and https://tex.stackexchange.com/questions/74476/how-to-avoid-empty-thebibliography-environment-bibtex-if-there-are-no-refere?rq=1 – Mars May 13 '19 at 20:39

1 Answers1

2

The trouble here is the grouping implicit in at least the frame environment of the example

\renewcommand{\cite}{\global\showbibtrue\typeout{within cite}\oldcite}

works.

A very simple example based on the article class can avoid grouping and can get away without the \global.

\documentclass{article}
\bibliographystyle{plain}

\let\oldcite\cite
\newif\ifshowbib
\showbibfalse
\renewcommand{\cite}{\showbibtrue\typeout{within cite}\oldcite}

\begin{document}
\cite{doody}

\ifshowbib
  showbib true
  \bibliography{biblatex-examples}
\else  
  showbib false
\fi
\end{document}

Here is an alternative that avoids patching \cite (it might require one more LaTeX run to show the bibliography than the version that patches \cite). The \global is still required since the command \citation is read from the .aux and executed in a group.

\documentclass{beamer}
\usepackage[utf8]{inputenc}

\bibliographystyle{plain}

\newif\ifshowbib
\showbibfalse
\def\citation#1{\global\showbibtrue}

\begin{document}

\begin{frame}{sigh}
  \cite{doody}
\end{frame}

\ifshowbib
  \begin{frame}[c,allowframebreaks]{Bibliography}
    \typeout{showbib true}
    showbib true
    \bibliography{biblatex-examples}
  \end{frame}
\else
  \typeout{showbib false}
  showbib false
\fi

\end{document}
moewe
  • 175,683
  • Oh, scoping! ;) Why can we just \def \citation, isn't it used for something (else)? – stefanct Dec 06 '18 at 15:57
  • 1
    @stefanct The LaTeX kernel has \let\citation\@gobble, so it is not used for something else there. It seems to be a sort of universal hook that other packages can use (though source2e does not say that) and some do (e.g. bibtopic, revtex4). – moewe Dec 06 '18 at 16:09
  • Not an issue for me, but just to be clear: this would break when these packages are used? – stefanct Dec 06 '18 at 17:18
  • 1
    @stefanct Depends on the package code: Either my answer breaks, the package breaks or the package uses a clever way to avoid that. – moewe Dec 06 '18 at 18:05