# How to peek and test whether the next character is a digit?

Background story: The Journal of Functional Programming has its own LaTeX class and we would like to use \citet (as in natbib). Unfortunately the class file is not compatible with natbib and they did not provide the style file for biblatex (which implements the natbib mode). In short, I want a magical jfphack.sty such that the following LaTeX document produces "Apple & Orange (9999)".

\RequirePackage{amsmath}
\documentclass{jfp1}
\usepackage{filecontents}
\usepackage{jfphack}

\title{}
\author{}
\affil{}
\email{}
\begin{document}

\citet{test1} % want "Apple & Orange (9999)"

\bibliographystyle{jfp}
\bibliography{test}
\begin{filecontents}{test.bib}
@article{test1,
title={Secret of the {U}niverse},
author={Angry Apple and Outraged Orange},
journal={nowhere},
year={9999}
}
\end{filecontents}
\end{document}


Edit: I came up with the following hacky .sty file and updated the question. In general I am happy except for \@addendparen (and \@ifnextdigit). Is there a way to simplify them?

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{jfphack}
\def\@ifnextdigit#1#2{%
\@ifnextchar0{#1}%
{\@ifnextchar1{#1}%
{\@ifnextchar2{#1}%
{\@ifnextchar3{#1}%
{\@ifnextchar4{#1}%
{\@ifnextchar5{#1}%
{\@ifnextchar6{#1}%
{\@ifnextchar7{#1}%
{\@ifnextchar8{#1}%
{\@ifnextchar9{#1}%
{#2}}}}}}}}}}}
\def\@removeendcomma#1, {#1}
\newif\if@outerparen \@outerparentrue
\def\@cite#1#2{\if@tempswa#2\else\if@outerparen(#1)\else#1\fi\fi\@outerparentrue}
\let\citep\cite
\let\citeyearpar\shortcite

• Welcome! Why? If you are submitting to the journal, they won't accept the hackery. If you are not, there's no reason to use their class. – cfr Aug 5 '16 at 2:06
• @cfr Our current draft using natbib was already accepted, and the reviewers seemed to be happy about the typesetting except for a broken section title due to incompatibilities. My hack would solve the problem while preserving the typesetting of the rest. I'm aware that they might not accept the hack so I'm trying to make it more elegant. :-) – favonia Aug 5 '16 at 15:25
• Do reviewers care about typesettting in your discipline? In mine, the copy-editor cares after the paper is accepted, but before it is published. The reviewers just care about the content. (Provided it is reasonable.) Indeed, usually journals ask for different formatting at the review stage (e.g. double-spaced) than is used in the final version (e.g. single-spaced). – cfr Aug 5 '16 at 15:57
• You should at least check with your copy editor before investing time and effort into this. – cfr Aug 5 '16 at 15:58
• Do you know for sure that what follows the (first) call to \@addendparen is an integer number? Must leading zeros be kept? If not, simply \def\@addendparen{\bgroup\afterassignment\@addendparen@\count0= }\def\@addendparen@{\the\count0)\egroup}. – Bruno Le Floch Oct 15 '16 at 1:50

The format of the citation received is

\citename{Apple \& Orange, }9999


So it's a matter of redefining \citename when necessary.

\begin{filecontents*}{\jobname.bib}
@article{test1,
title={Secret of the {U}niverse},
author={Angry Apple and Outraged Orange},
journal={nowhere},
year={9999}
}
\end{filecontents*}

\RequirePackage{amsmath}
\documentclass{jfp}
\usepackage{filecontents}
%\usepackage{jfphack}
\usepackage{xpatch}

\makeatletter
\newif\if@citet
\let\citet\cite
\xpretocmd{\cite}{\@citetfalse}{}{}
\xpretocmd{\citet}{\@citettrue}{}{}
\newcommand{\citetcitename}[1]{%
\citet@removecomma#1\@nil
\afterassignment\citet@year\count@
}
\def\citet@year{(\the\count@)}
\def\@cite#1#2{%
\if@tempswa
#2%
\else
\if@citet
\begingroup
\let\citename\citetcitename
#1%
\endgroup
\else
(#1)%
\fi
\fi
}
\def\citet@removecomma#1, \@nil{#1~}
\makeatother

\title{}
\author{}
\affil{}
\email{}
\begin{document}

\cite{test1} % want "Apple & Orange (9999)"

\citet{test1}
\bibliographystyle{jfp}
\bibliography{\jobname}
\end{document}


This assumes the year is present.

• Thanks. This is great! I also want to give @bruno-le-floch credit for pointing out \afterassignment in a comment to the OP. – favonia Sep 9 '17 at 14:49

You can simplify the @ifnextdigit very much by using futurelet

\def\@ifnextdigit#1{\def\@doit{#1}\futurelet\next\@finish}
\def\@finish{\ifcat3\next\expandafter\@doit\fi}


To use it, you place whatever command is to be executed on finding a digit as the argument to @ifnextdigit. It is then stored in \@doit. Then we use futurelet to peek at the next token after this macro is expanded, and store it in \next. Then we use the ifcat test to check if it has the category code of a number, and if it does, execute \@doit.

• \ifcat3\next does not distinguish digits from punctuation characters for example. – user4686 Sep 8 '17 at 6:33
• Why would there be punctuation in the beggining of a parentheses block that should make that an issue? – A Gold Man Sep 8 '17 at 9:31
• @jfbu is basically pointing out that numbers have category code 12 like many other tokens. Hence, you are not actually checking if \next is a number, but if \next has catcode 'other'. Apart from that I really like the approach. If there only would be an expandable test for numbers :) – Ruben Sep 8 '17 at 11:10
• @Ruben to be honest I hardly looked at the question here (apologies to @AGoldMan) but yes there is an expandable test for numbers \ifnum 9<1#1  will do the trick if #1 is token to be tested, however it does not work with a \next in place of such a #1. If expansion of #1 can be dangerous (i.e. contains conditional tokens for example), then \ifnum 9<\detokenize{1#1}  should work, and attention to the mandatory space token at the end I have inserted to close the number. – user4686 Sep 8 '17 at 14:37
• (in my comment above I am naturally talking about testing for a digit token, not a full number, then one can organize this on successive tokens, but for a precise answer, one needs the context to be clearly stated and the original question looks a bit vague) – user4686 Sep 8 '17 at 16:02