[Tex/LaTex] Sorting bibliography in order of appearance without Bibtex

bibliographies

Is there a way to sort bibliography in order of appearance without Bibtex? I am using the following format for the bibliography

\begin{thebibliography}{}
\bibitem{ref1}{reference1}
\bibitem{re2} {reference2}
\end{thebibliography}

I tried using \bibliographystyle{unsrt} but it had no effect.

Best Answer

Usually BibTeX takes care of sorting your bibliography. And BibTeX is pretty good at that, so I strongly suggest you let BibTeX sort your bibliography. If you use .bib files it is much easier to re-use your bibliographic data should you have to change the style.

In case of cite-order sorting (unsrt), you can get thebibliography To sort the bibliography for you automatically with some low-level hacking if you additionally accept a slight change in the syntax of \bibitem.

Normally \bibitem works like \item and takes only one argument (the entry key) and an optional argument (the fixed label), the entry data itself is not an argument of \bibitem. For the code below to work the entry data needs to be an argument of \bibitem. That means that entries in thebibliography can't look like

\bibitem{foo} Lorem Ipsum.
\bibitem[bar]{bar} Dolor sit amet.

they must look like

\bibitem{foo}{Lorem Ipsum.}
\bibitem[bar]{bar}{Dolor sit amet.}

Since you have these braces in your question already, I trust this is not a deal-breaker for you.

You may have to run LaTeX three times until all citation labels are resolved correctly, but you should get re-run warnings when a further run is required.

The main idea is that whenever you \cite an entry LaTeX writes the key to a list of all entry keys. This is implemented via the \citation macro in the .aux file, which means that the complete citation order is available at the beginning of the document, but requires two LaTeX runs.

thebibliography works in two steps, first it just collects all entries and their data (that's why we need the additional argument, so \bibitem can grab the data), then in a second step it prints the entries in the order given by the entry list.

The code is based on the standard definitions of \citation and \bibitem from the LaTeX kernel and thebibliography from article.cls. For a different document class or packages like cite or natbib the definitions may have to be tweaked a bit (the code is compatible with hyperref already, though).

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}

\usepackage{etoolbox}
%\usepackage{hyperref}

\makeatletter
\newcommand*{\lodbib@citeorder}{}
\newcommand*{\lodbib@notcited}{}% catch entries that were not cited

% macro in aux file
\def\citation{%
  \forcsvlist{\citation@i}}

\def\citation@i#1{%
  \ifinlist{#1}{\lodbib@citeorder}
    {}
    {\listxadd{\lodbib@citeorder}{#1}}}

\let\ltxorig@lbibitem\@lbibitem
\let\ltxorig@bibitem\@bibitem

% save bibitems
\def\@lbibitem[#1]#2#3{%
  \csdef{lodbib@savedlabel@#2}{#1}%
  \@bibitem{#2}{#3}}

\def\@bibitem#1#2{%
  \xifinlist{#1}{\lodbib@citeorder}
    {}
    {\listadd{\lodbib@notcited}{#1}}%
  \csdef{lodbib@savedentry@#1}{#2}}

\renewenvironment{thebibliography}[1]
     {\settowidth\labelwidth{\@biblabel{#1}}}
     {\def\@noitemerr
       {\@latex@warning{Empty `thebibliography' environment}}%
      \section*{\refname}%
      \@mkboth{\MakeUppercase\refname}{\MakeUppercase\refname}%
      \list{\@biblabel{\@arabic\c@enumiv}}%
           {\leftmargin\labelwidth
            \advance\leftmargin\labelsep
            \@openbib@code
            \usecounter{enumiv}%
            \let\p@enumiv\@empty
            \renewcommand\theenumiv{\@arabic\c@enumiv}}%
      \sloppy
      \clubpenalty4000
      \@clubpenalty \clubpenalty
      \widowpenalty4000%
      \sfcode`\.\@m
      \lodbib@biblistloop
      \endlist}

\def\lodbib@biblistloop{%
  \forlistloop{\lodbib@bibitem}{\lodbib@citeorder}%
  \ifdefvoid{\lodbib@notcited}
    {}
    {\forlistloop{\lodbib@bibitem}{\lodbib@notcited}}}

\def\lodbib@bibitem#1{%
  \ifcsundef{lodbib@savedlabel@#1}
    {\ltxorig@bibitem{#1}}
    {\ltxorig@lbibitem[\csuse{lodbib@savedlabel@#1}]{#1}}%
  \csuse{lodbib@savedentry@#1}}
\makeatother


\begin{document}
\cite{ref2} and \cite{ref3} and \cite{ref1}

\begin{thebibliography}{C}
\bibitem{ref1}{AAAA}
\bibitem{ref2}{BBBB}
\bibitem[C]{ref3}{CCCC}
\bibitem{ref4}{DDDD}
\end{thebibliography}

\cite{ref2}
\end{document}

Citations: "[1] and [C] and [2]", bibliography: "[1] BBBB//[C] CCCC//[2] AAAA//[3] DDDD"

edit: Fix for cite package, see Multiple Reference Citation in order of appearance without Bibtex.

Related Question