2

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.

1

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.

  • This actually worked. However I got an error which, when I searched, seemed like a Clash between bibentry and hyperref with bibstyle elsart-harv. I used the same solution and it's working but clicking the in-text citation takes me to title page instead of the reference. Can that be fixed? – Lod Nov 5 '18 at 11:06
  • @Lod What error did you get in what context? The code as posted in the answer worked without errors for me. Please consider adding an example document, a so-called MWE, that reproduces the error. – moewe Nov 5 '18 at 11:08
  • @meowe It works without huper links. the error I got was Lonely \item--perhaps a missing list environment when compiling and I fixed it by adding \usepackage{bibentry} \makeatletter\let\saved@bibitem\@bibitem\makeatother \usepackage{hyperref} \makeatletter\let\@bibitem\saved@bibitem\makeatother But when I click the green box, it takes me to page one and not the reference in the bibliography. – Lod Nov 5 '18 at 11:11
  • @Lod The example still works fine for me when I add \usepackage{hyperref} directly after \usepackage{etoolbox}. I can not reproduce the error you mention and the links work just fine. Please share a complete example document that reproduces the issue. – moewe Nov 5 '18 at 11:14
  • Oh okay, I added it at the end. Thank you it works now! – Lod Nov 5 '18 at 11:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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