# Oxford comma only for three or more authors, but not for exactly two authors

I want to insert the Oxford Comma only if an entry has 3 or more authors, but not if the entry has exactly two authors.

e.g.

A and B (1999) [NO COMMA]

A, B, and C (1999) [COMMA before C]

I tried

author = "A and Firstname { B,} and C"


in the bib entry itself. This works for citation call-outs, but then two commas appear in the formatted bibliographic entry.

I use the aea bibliography style, which is available online here. As you can probably guess by now, this bibliography style is set up to always insert a comma between penultimate_author and and final_author -- even if an entry has exactly two authors. Is there a way to adjust this bibliography style such that the Oxford comma gets inserted only if an entry has three or more authors?

For the sake of completeness, here's the function format.names from the aea bibliography style:

FUNCTION {format.names}
{ 's :=
#1 'nameptr :=
s num.names$'numnames := numnames 'namesleft := { namesleft #0 > } { nameptr #1 = { s nameptr "{vv~}{ll}{, jj}{, ff}" format.name$ 't := }
{   s nameptr "{ff }{vv~}{ll}{, jj}" format.name$'t := } if$
nameptr #1 >
{ namesleft #1 >
{ ", " * t * }
{ t "others" =
{ ", et~al." * }
{ " and " * t * }
if$} if$
}
't
if$nameptr #1 + 'nameptr := namesleft #1 - 'namesleft := } while$
}

• Welcome to TeX.SE. A terminological convention up-front: if the list of surnames contains exactly 2 items, the comma that's inserted between first_surname and and second_surname should not be called an "Oxford comma". Incidentally, why are you employing the aea bibliography style if you don't like some of its formatting settings? – Mico Oct 7 '18 at 10:45

I suggest you proceed as follows:

• Make a copy of aea.bst and call the copy, say, aea-oxford.bst.

• Open the file aea-oxford.bst in a text editor. The program you use to edit your tex files will do fine.

• In the file, locate the function format.names. Basically, that's the function whose code you displayed in your query.

• In this function, replace the three lines

  { t "others" =
{ ", et~al." * }
{ ", and " * t * }


with the following seven lines:

      { numnames #2 >
{ "," * }
'skip$if$
t "others" =
{ " et~al." * }
{ " and " * t * }


The first part of the new code consists of a test to check if the total number of surnames is greater than 2. If yes, insert a comma; if no, do nothing. In the second part (which only ever gets executed if there are two or more surnames, one of which may be the string "others"), a plain "and" is inserted if the second surname is "real", i.e., doesn't consist of the string "others".

• Store the file aea-oxford.bst in the directory where your main tex file is located.

• In the main tex file, change the argument of \bibliographystyle from aea to aea-oxford. Then, perform a full recompile cycle -- LaTeX, BibTeX, LaTeX, and LaTeX once more -- to fully propagate all changes.

A full MWE (minimum working example) and screenshot; I've highlighted in yellow the two changes wrought in aea-oxford.bst:

\RequirePackage{filecontents}
\begin{filecontents}{mybib.bib}
@misc{a, author = "A", title  = "Thoughts", year   = 3001, }
@misc{ab, author = "A and B", title  = "Thoughts", year   = 3002, }
@misc{abc, author = "A and B and C", title  = "Thoughts", year   = 3003, }
@misc{abcd, author = "A and B and C and D", title  = "Thoughts", year   = 3004, }
@misc{abcde, author = "A and others", title  = "Thoughts", year   = 3005, }
\end{filecontents}

\documentclass{article}
\usepackage[round,authoryear]{natbib}
\bibliographystyle{aea-oxford}

\begin{document}
\noindent
\cite{a}, \cite{ab}, \cite{abc}, \cite{abcd}, \cite{abcde}
\bibliography{mybib}
\end{document}


Just for comparison, here's the output of the same MWE if the unmodified aea bibliography style were used -- note the two additional commas:

• Thank you very much, Mico! In the text, I would also like to have A,B, and C (3003). Which part of the code refers to the names in the text? – masterplan18 Oct 7 '18 at 12:13
• @masterplan18 - Find the function format.names.label.short; in that function, find the line that says { t "others" =. Inbetween { and t, insert the same new instructions as in the answer shown above, i.e., numnames #2 > { "," * } 'skip$if$. – Mico Oct 7 '18 at 12:50
• Thank you again, Mico! Saved me a lot of time. – masterplan18 Oct 7 '18 at 13:26