# LaTeX3 RenewDocumentCommand for cite with an optional argument for punctuation

When working with citations there are many distinct ways the citation must be incorporated within the text. Even when you work exclusively with number formats (this example excludes Author year style citations).

While exclusively using a number reporting system, two of the most common styles I repeatedly have to change between include

• the in-line, in-sentence, square bracket enclosed, numbers inside the sentence punctuation (IEEE)
• and the space gobbled superscript numbers outside the punctuation

natbib does a good job of letting me switch between these formats exceptionally quickly, and redirect the formatting to a different bst file.

Unfortunately, I have to go through my text manually and move the punctuation to the other side of the reference.

I keep having to do this since collaborators just can't make up their minds, and it finally has driven me to the point where I just want to write a modified version of the cite command where, if there is punctuation with the reference, I just add it as an argument to be globally assigned a position of before or after the reference itself.

In my complete document (only major exception is it includes bibunits) this compiles fine, but it doesn't recognize the [.] as an argument, it just appends it after the citation. The following MWE will fail to compile completely, but I haven't been able to identify whether it fails because of a missing package, or because of a problem with my LaTeX3 command.

I have written many DeclareDocumentCommands before, with no problems having m+ o arguments, so I don't know quite why the RenewDocumentCommand fails.

\documentclass{article}

\usepackage{filecontents}

\begin{filecontents}{\jobname.bib}
author  = "George D. Greenwade",
title   = "The {C}omprehensive {T}ex {A}rchive {N}etwork ({CTAN})",
year    = "1993",
journal = "TUGBoat",
volume  = "14",
number  = "3",
pages   = "342--351"
}

@book{goossens93,
author    = "Michel Goossens and Frank Mittelbach and Alexander Samarin",
title     = "The LaTeX Companion",
year      = "1993",
}
\end{filecontents}

\usepackage{expl3}
\usepackage{xparse}
\usepackage{xpatch}  % can exclude etoolbox. xpatch loads it anyway, since xpatch extends etoolbox
\usepackage{letltxmacro}

\usepackage[numbers,super,comma,sort&compress]{natbib}

\global\let\originalcite\cite
\ExplSyntaxOn
\RenewDocumentCommand{\cite}{ m+ o }
{
% two arguments, the citation string, and an optional argument of the punctuation
\tl_if_blank:VTF{#2}{\originalcite{#1}}%
{%
{\gobble}{#2}{\originalcite{#1}}
}%
}
\ExplSyntaxOff

\begin{document}

The original cite command \originalcite{goossens93}.

Depending on the style I work with I will have to change everything manually to:  The original cite command.\originalcite{goossens93}

But if I can create a macro, I only have to add a toggle, or change the order manually.  Of course increasing the complexity of the logic is possible to work for different types of punctuation, but this is a MWE after all.  The modified cite command I am trying to produce is \cite{goossens93}[.]

\bibliographystyle{plainnat}
\bibliography{\jobname}

\end{document}


UPDATE

In my efforts to simplify the problem I tried to remove bibunits to make it easier for others to compile. Turns out bibunits was my initial culprit in causing literal typesetting of what should have been an argument. Updated MWE below using solution recommendation.

\begin{filecontents}{\jobname.bib}
author  = "George D. Greenwade",
title   = "The {C}omprehensive {T}ex {A}rchive {N}etwork ({CTAN})",
year    = "1993",
journal = "TUGBoat",
volume  = "14",
number  = "3",
pages   = "342--351"
}

@book{goossens93,
author    = "Michel Goossens and Frank Mittelbach and Alexander Samarin",
title     = "The LaTeX Companion",
year      = "1993",
}
\end{filecontents}

\documentclass{article}

\usepackage{xparse}
\usepackage{xpatch}
\usepackage{letltxmacro}

\usepackage[numbers,super,comma,sort&compress]{natbib}
\usepackage{bibunits}
\defaultbibliographystyle{plainnat}
\defaultbibliography{\jobname}

\LetLtxMacro\originalcite\cite

\ExplSyntaxOn % just not to worry about spaces and end-of-lines
\RenewDocumentCommand{\cite}{ m o }
{
\IfValueT { #2 }{ \unskip #2 }
\originalcite { #1 }
}
\ExplSyntaxOff

\begin{document}

\begin{bibunit}
The original cite command \originalcite{goossens93}.

Depending on the style I work with I will have to change everything
manually to:  The original cite command.\originalcite{goossens93}

But if I can create a macro, I only have to add a toggle, or change
the order manually.  Of course increasing the complexity of the logic
is possible to work for different types of punctuation, but this is
a MWE after all.  The modified cite command I am trying to produce
is \cite{goossens93}[.]
\end{bibunit}

\end{document}

• Also, you have you insert the code between \ExplSyntaxOn and \ExplSyntaxOff. – Jagath Jul 7 '16 at 4:39
• @JagathAR I originally left it out because the punctuation may be interpreted incorrectly by expl3, but only intermittently do I get a problem with the underscores and colons when the Syntax tags are there or not. – EngBIRD Jul 7 '16 at 5:22
• As usual, when other packages are loaded, timing of redefinitions may be crucial. I added a workaround for bibunits. – egreg Jul 7 '16 at 15:58

If I read correctly your question, you want that the trailing optional argument is printed before the superscript.

1. \tl_if_blank:VTF is the wrong function, because the V means a variable is expected;

2. {\gobble}{#2}{\originalcite{#1}} is meaningless;

3. m+o means that the last (optional) argument is “long”, that is, it accepts \par in it; it should be read as m +o, rather than m+ o, but you don't want \par in either argument.

Correct solution: do nothing if the optional argument is absent, otherwise “\unskip” and print it before the citation. Use xparse features for dealing with arguments, rather than low level functions like \tl_if_blank:nTF.

\begin{filecontents}{\jobname.bib}
author  = "George D. Greenwade",
title   = "The {C}omprehensive {T}ex {A}rchive {N}etwork ({CTAN})",
year    = "1993",
journal = "TUGBoat",
volume  = "14",
number  = "3",
pages   = "342--351"
}

@book{goossens93,
author    = "Michel Goossens and Frank Mittelbach and Alexander Samarin",
title     = "The LaTeX Companion",
year      = "1993",
}
\end{filecontents}

\documentclass{article}

%\usepackage{expl3} % xparse loads it
\usepackage{xparse}
\usepackage{xpatch}
\usepackage{letltxmacro}

\usepackage[numbers,super,comma,sort&compress]{natbib}

\LetLtxMacro\originalcite\cite

\ExplSyntaxOn % just not to worry about spaces and end-of-lines
\RenewDocumentCommand{\cite}{ m o }
{
\IfValueT { #2 }{ \unskip #2 }
\originalcite { #1 }
}
\ExplSyntaxOff

\begin{document}

The original cite command \originalcite{goossens93}.

Depending on the style I work with I will have to change everything
manually to:  The original cite command.\originalcite{goossens93}

But if I can create a macro, I only have to add a toggle, or change
the order manually.  Of course increasing the complexity of the logic
is possible to work for different types of punctuation, but this is
a MWE after all.  The modified cite command I am trying to produce
is \cite{goossens93}[.]

\bibliographystyle{plainnat}
\bibliography{\jobname}

\end{document}


When bibunits is used, the redefinition of \cite must go before loading it, because the package in turn redefines \cite at the beginning of each bibunit environment. Or, more simply, one has to update \std@cite to use the redefined \cite command.

\begin{filecontents}{\jobname.bib}
author  = "George D. Greenwade",
title   = "The {C}omprehensive {T}ex {A}rchive {N}etwork ({CTAN})",
year    = "1993",
journal = "TUGBoat",
volume  = "14",
number  = "3",
pages   = "342--351"
}

@book{goossens93,
author    = "Michel Goossens and Frank Mittelbach and Alexander Samarin",
title     = "The LaTeX Companion",
year      = "1993",
}
\end{filecontents}

\documentclass{article}

\usepackage{xparse}
\usepackage{xpatch}
\usepackage{letltxmacro}

\usepackage[numbers,super,comma,sort&compress]{natbib}
\usepackage{bibunits}
\defaultbibliographystyle{plainnat}
\defaultbibliography{\jobname}

\ExplSyntaxOn % just not to worry about spaces and end-of-lines
\LetLtxMacro\originalcite\cite
\RenewDocumentCommand{\cite}{ m o }
{
\IfValueT { #2 }{ \unskip #2 }
\originalcite { #1 }
}
\ExplSyntaxOff

% update the command bibunits uses for the original \cite
\makeatletter
\let\std@cite\cite
\makeatother

\begin{document}

\begin{bibunit}[plainnat]
The original cite command \originalcite{goossens93}.

Depending on the style I work with I will have to change everything
manually to:  The original cite command.\originalcite{goossens93}

But if I can create a macro, I only have to add a toggle, or change
the order manually.  Of course increasing the complexity of the logic
is possible to work for different types of punctuation, but this is
a MWE after all.  The modified cite command I am trying to produce
is \cite{goossens93}[.]

\putbib

\end{bibunit}

\end{document}


The output is the same as before.

• May be give the new \cite intelligence to check the next token? That way it could be automatic \cite{foo}. \cite{foo}, \cite{foo}; etc.. – Manuel Jul 7 '16 at 10:20
• @Manuel Isn't it what fnpct does? – egreg Jul 7 '16 at 10:23
• Okey, I didn't know :) – Manuel Jul 7 '16 at 10:32
• @egreg Thanks, the point of the question is not necessarily to print the punctuation "after" the reference, its to give me a flexible function where I can define rules to print before or after depending on what the character is. So eventually there will be character comparisons, but before I could even get that far, I had to get a basic MWE working. So for your point 2, it may be useless with superscripts but the gobble was there to destroy the space if I want to control spacing on bracketed references. point 3, I thought a multiline string of references might have needed +, my mistake. – EngBIRD Jul 7 '16 at 13:23
• @EngBIRD \std@cite is the macro bibunits uses to store the current meaning of \cite. Not a well chosen name, but that's what it is. – egreg Jul 7 '16 at 16:15

A possible solution (if I understand the question right):

\documentclass{article}

\usepackage{filecontents}

\begin{filecontents}{\jobname.bib}
author  = "George D. Greenwade",
title   = "The {C}omprehensive {T}ex {A}rchive {N}etwork ({CTAN})",
year    = "1993",
journal = "TUGBoat",
volume  = "14",
number  = "3",
pages   = "342--351"
}

@book{goossens93,
author    = "Michel Goossens and Frank Mittelbach and Alexander Samarin",
title     = "The LaTeX Companion",
year      = "1993",
}
\end{filecontents}

\usepackage{letltxmacro}

%\usepackage[numbers,super,comma,sort&compress]{natbib}% Toggle this line
\usepackage[numbers,comma,sort&compress]{natbib}% Toggle this line

\global\let\originalcite\cite

\makeatletter
\def\cite#1{\Cite{#1}}
\def\Cite#1{\@ifnextchar[{\@Cite#1}{\@Cite#1[]}}
\def\@Cite#1[#2]{\ifNAT@super\unskip#2\originalcite{#1}\else\originalcite{#1}\unskip#2\fi}%
\makeatother

\begin{document}

The original cite command \originalcite{goossens93}.

Depending on the style I work with I will have to change everything
manually to:  The original cite command.\originalcite{goossens93}

But if I can create a macro, I only have to add a toggle, or change the
order manually.  Of course increasing the complexity of the logic is
possible to work for different types of punctuation, but this is a MWE
after all.  The modified cite command I am trying to produce is
\cite{goossens93}[.]

\bibliographystyle{plainnat}
\bibliography{\jobname}

\end{document}

• Thanks for the answer, this is an alternative to the MWE above, but I approached it with epl3 type syntax because I need to be able to add numerous levels of if statements to check for commas vs periods, and document Booleans for square brackets vs superscripts. I am not sure if your compact one-liner will be flexible enough for me. – EngBIRD Jul 7 '16 at 5:25