6

When citing items using BibTeX, only the cited items show up in the bibliography (unless you use \nocite{*}). Can I have the same effect for normal \bibitems that are at the end of my .tex file? (I have a long list that I use for several longer reports.)

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
domotorp
  • 389
  • 5
    If the bibliography items are listed verbatim as \bibitems and you're not using a bibliography manager like BibTeX or BibLaTeX, then there's not much you can do... all the items will be set regardless of whether they're \cited or not. As such, removing \nocite{*} would not make any difference. "Not much" means there might be other methods, but it's just not as easy. – Werner Oct 12 '16 at 05:54
  • Perhaps we need to see which packages you're loading (see Which package version am I using?), since solutions may have to be compatible with your setup. – Werner Oct 12 '16 at 06:26
  • 3
    The usual method is to make your collection of references as a .bib file (bibtex "database") and then the job of extracting just the used citations is exactly what bibtex (and now biber) are designed to do. \nocite does nothing if you are not using bibtex. – David Carlisle Oct 12 '16 at 07:06
  • @Werner I see, I didn't know! I've updated my question accordingly. – domotorp Oct 12 '16 at 08:05
  • 1
    Short answer: No. If you are doing stuff manually, you have to do stuff manually. – Johannes_B Oct 12 '16 at 08:11
  • 1
    Is there are a specific reason why you do not want to use bibtex/biblatex/.. ? Because even though this might in principle be possible (if not using latex then using simple scripting) it will be unnecessarily cumbersome, because there already is a solution for this. – Bort Oct 12 '16 at 08:13
  • @Johannes But why? This seems like such a simple thing to solve, and I like to format each reference differently, the way I like. I don't think I would be the only one with this problem. – domotorp Oct 12 '16 at 08:14
  • The solution is BibTeX or the modern combination of Biblatex and biber. That ensures a consistently formatted bibliography. – Johannes_B Oct 12 '16 at 08:15
  • 2
    A manual solution, but you can use the refcheck package to quickly identify which items from the bibliography are actually cited, and then comment out those you don't use. – Andrew Swann Oct 12 '16 at 08:17
  • @Andrew Yes, I knew about this one, which, I think, also shows the need for a solution to my problem. I don't understand why I'm not allowed to have a long list of bibitems formatted the way I like them, and each time cite only the ones I want to cite, without the need of going through the whole list with refcheck. – domotorp Oct 12 '16 at 08:21
  • @domotorp The way the bibliography works is that it typesets the content (\bibitem entries): it was never intended to be selective about what is there. – Joseph Wright Oct 12 '16 at 08:25
  • @Joseph I can understand that that was the original intention, but what I'm asking for seems like a simple modification. – domotorp Oct 12 '16 at 08:28
  • 2
    @domotorp Not really, as there's no end marker for \bibitem so collecting stuff up would be non-trivial. Moreover, the interest in developing such a solution is likely to be low as using a .bib database and either BibTeX or Biber is very common and is selective. – Joseph Wright Oct 12 '16 at 08:31
  • @Joseph Well, my \bibitems always end in another \bibitem or with \end{bibliography}. And trust me, most of my co-authors don't use BibTeX and would appreciate such a solution. We are simple mathematicians who are terrible at coding. – domotorp Oct 12 '16 at 09:25

2 Answers2

8

If you are prepared to accept that \bibitem should be ended by a blank line, then you can modify some of the code from source2e and refcheck to make this work. You have run latex three times to get the correct numbering in the text.

Sample output

\documentclass{article}

\makeatletter
\let\@@citation@@=\citation

\renewcommand{\citation}[1]{\@@citation@@{#1}%
\@for\@tempa:=#1\do{\@ifundefined{cit@\@tempa}%
  {\global\@namedef{cit@\@tempa}{}}{}}%
}

\def\@lbibitem[#1]#2#3\par{%
  \@ifundefined{cit@#2}{}{\item[\@biblabel{#1}\hfill]}%
  \if@filesw
      {\let\protect\noexpand
       \immediate
       \write\@auxout{\string\bibcite{#2}{#1}}}\fi\ignorespaces
  \@ifundefined{cit@#2}{}{#3}}
\def\@bibitem#1#2\par{%
  \@ifundefined{cit@#1}{}{\item}%
  \if@filesw \immediate\write\@auxout
    {\string\bibcite{#1}{\the\value{\@listctr}}}\fi\ignorespaces
  \@ifundefined{cit@#1}{}{#2}}
\makeatother

\begin{document}

Test a citation \cite{one} and another \cite{three}.  Also one more
for luck: \cite{five}.

\begin{thebibliography}{9}

\bibitem{one} Reference one.

\bibitem{two} Reference two.

\bibitem[Special]{three} Reference three.

\bibitem{four} Reference four.

\bibitem{five} Reference five.

\bibitem[Unusual]{six} Reference six.

\end{thebibliography}

\end{document}

The first part of the code is refchecks modification to the \cite command so that use of a bibitem is recorded. The second part is a modification of the core latex \bibitem, so that it always records the label in the .aux file, but only prints out the body if the item has been cited.

If you need to use this with hyperref so there are links to the bibliography, then the coding has to be adapted to hyperref's versions on \@lbibitem and \@bibitem, since hyperref simply overwrites the current definition. This is given as follows, notice the positioning of the loading of the hyperref package:

\documentclass{article}

\makeatletter
\let\@@citation@@=\citation

\renewcommand{\citation}[1]{\@@citation@@{#1}%
\@for\@tempa:=#1\do{\@ifundefined{cit@\@tempa}%
  {\global\@namedef{cit@\@tempa}{}}{}}%
}
\makeatother

\usepackage{hyperref}

\makeatletter
\def\@lbibitem[#1]#2#3\par{%
  \@ifundefined{cit@#2}{}{\@skiphyperreftrue
  \H@item[%
    \ifx\Hy@raisedlink\@empty
      \hyper@anchorstart{cite.#2\@extra@b@citeb}%
        \@BIBLABEL{#1}%
      \hyper@anchorend
    \else
      \Hy@raisedlink{%
        \hyper@anchorstart{cite.#2\@extra@b@citeb}\hyper@anchorend
      }%
      \@BIBLABEL{#1}%
    \fi
    \hfill
  ]%
  \@skiphyperreffalse}%
  \if@filesw
    \begingroup
      \let\protect\noexpand
      \immediate\write\@auxout{%
        \string\bibcite{#2}{#1}%
      }%
    \endgroup
  \fi
  \ignorespaces
  \@ifundefined{cit@#2}{}{#3}}

\def\@bibitem#1#2\par{%
  \@ifundefined{cit@#1}{}{\@skiphyperreftrue\H@item\@skiphyperreffalse
  \Hy@raisedlink{%
    \hyper@anchorstart{cite.#1\@extra@b@citeb}\relax\hyper@anchorend
    }}%
  \if@filesw
    \begingroup
      \let\protect\noexpand
      \immediate\write\@auxout{%
        \string\bibcite{#1}{\the\value{\@listctr}}%
      }%
    \endgroup
  \fi
  \ignorespaces
  \@ifundefined{cit@#1}{}{#2}}
\makeatother

\begin{document}

Test a citation \cite{one} and another \cite{three}.  Also one more
for luck: \cite{five}.

\begin{thebibliography}{9}

\bibitem{one} Reference one.

\bibitem{two} Reference two.

\bibitem[Special]{three} Reference three.

\bibitem{four} Reference four.

\bibitem{five} Reference five.

\bibitem[Unusual]{six} Reference six.

\end{thebibliography}

\end{document}
Andrew Swann
  • 95,762
  • Thanks, this seems to work! I still have one error message tough. Should I have a blank line before and after each \bibitem? – domotorp Oct 12 '16 at 10:59
  • OK, after half an hour I've figured out that I need a linebreak also after the last \bibitem which was there in bibliography.tex, but after I input it in the main file, it apparently gets ignored, so a linebreak is needed in the main file after the input. – domotorp Oct 12 '16 at 11:18
  • You just need each \bibitem to end with a blank line (or a \par) – Andrew Swann Oct 12 '16 at 11:28
  • I've just noticed a slight problem with this approach; when I click on a reference in the pdf, it doesn't take me to the cited item. – domotorp Oct 16 '16 at 19:38
  • 1
    @domotorp Well, to get clickable links you have to load the hyperref package. As usual make sure you do this as late as possible in your preamble, in particular after the modifications above. Then it works for me. – Andrew Swann Oct 17 '16 at 09:36
  • I tried and the links also work for me if I swap the order, but all citations are shown. – domotorp Oct 17 '16 at 20:54
  • 1
    @domotorp Update for working with hyperref now provided. – Andrew Swann Oct 18 '16 at 14:35
2

You could change your input format to put the text in an argument. Then it is rather easy to suppress one entry:

\documentclass{article}
\usepackage{xpatch}
\makeatletter
\xpretocmd\@citex{\csgdef{used@cite@#2}{x}}{}{\failed}
\newcommand\checkbibentry[2]{\ifcsdef{used@cite@#1}{\bibitem{#1}{#2}}{}}
\makeatletter
\begin{document}

\cite{a} \cite{c}

\begin{thebibliography}{99}

\checkbibentry{a}{some text to a}

\checkbibentry{b}{some text to b}

\checkbibentry{c}{some text to c}
\end{thebibliography}

\end{document}

enter image description here

Ulrike Fischer
  • 327,261
  • This works well for me for \cite{A} but not for \cite{A,B,...}, whenever I cite more than one ref at once they seem to be omitted as well. How does one adapt the code to ensure this works? Thanks a lot – Hercule Poirot Feb 22 '22 at 23:09