# Detect single initial with l3regex

Edit: Now my problem is detecting when the argument to \mkbibnamegiven is a single initial. I'm trying to do that with l3regex but I can't get it to work:

\documentclass{article}
\usepackage{lmodern}
\usepackage{xparse}
\usepackage{expl3}
\usepackage{l3regex}

\usepackage[style=authoryear]{biblatex}

\begin{filecontents*}{\jobname.bib}
@book{doe2016, author = {J. Doe}, date = {2016}}
@book{doe2017, author = {P. Doe}, date = {2017}}
@book{doe2015a, author = {John Doe}, date = {2015}}
@book{doe2015b, author = {James Doe}, date = {2015}}
\end{filecontents*}

\addbibresource{\jobname.bib}

\ExplSyntaxOn

\NewDocumentCommand{\IfInitial}{mmm}{%
\regex_match:nnTF{\w\.}{#1}{{\bfseries #2}}{#3}% Doesn't work
% \regex_match:nnTF{^\w.\$}{#1}{{\bfseries #2}}{#3}% Also doesn't work
}

\ExplSyntaxOff

\renewcommand*{\mkbibnamefamily}[1]{\MakeLowercase{\scshape#1}}%
\renewcommand*{\mkbibnamegiven}[1]{
\ifnumequal{\value{uniquename}}{2}{%
\IfInitial{#1}{\MakeLowercase{\scshape#1}}{#1}%
}{%
\MakeLowercase{\scshape#1}%
}%
}

\begin{document}

\noindent\cite{doe2015a}\\
\cite{doe2015b}\\
\cite{doe2016}\\% This gives me J. Doe, but I want j. Doe
\cite{doe2017}

\end{document}


Original question:

This is an extension of the question I asked here.

Using BibLaTeX, I'm trying to get the first name in small caps when it's just the initial, but in the normal font when it's the full name. So here's my attempt:

\documentclass{article}
\usepackage{lmodern}

\usepackage[style=authoryear]{biblatex}

\begin{filecontents*}{\jobname.bib}
@book{doe2016, author = {J. Doe}, date = {2016}}
@book{doe2017, author = {P. Doe}, date = {2017}}
@book{doe2015a, author = {John Doe}, date = {2015}}
@book{doe2015b, author = {James Doe}, date = {2015}}
\end{filecontents*}

\addbibresource{\jobname.bib}

\renewcommand*{\mkbibnamefamily}[1]{\MakeLowercase{\scshape#1}}%
\renewcommand*{\mkbibnamegiven}[1]{
\ifnumequal{\value{uniquename}}{2}{#1}{\MakeLowercase{\scshape#1}}%
}

\begin{document}

\noindent\cite{doe2015a}\\% First name is normal, like I want it
\cite{doe2015b}\\% First name is normal, like I want it
\cite{doe2016}\\% First name is normal, but I want it in small caps
\cite{doe2017}% First name is in small caps, like I want it

\end{document}


Ignoring the small caps, that gives me:

John doe 2015

James doe 2015

J. doe 2016

p. doe 2017

What I want, however, is:

John doe 2015

James doe 2015

j. doe 2016

p. doe 2017

Since the years are different, doe2016 doesn't require the full first name, so we get just the initial. But the value of uniquename is still 2, as if we needed the full name. So how can I change the format of the first name for just the cases when only the initial is printed?

• uniquename (unlike uniquelist) does not take the year into account. You will always get the same uniquename result regardless of the year. The problem is that for biblatex 'J. Doe' and 'John Doe' and 'James Doe' are three different people. Oct 23 '17 at 19:42
• @moewe Yes, I guessed that much, but is there something that takes the year into account for me to check against then? How does BibLaTeX know when it should print just the initial or the whole name? Apparently it takes the year into account then, but I couldn't figure out where or how. Oct 23 '17 at 19:44
• AFAIK there is no uniquename setting that would take the year into account. And there is no straightforward way to get it to do that from within biblatex (you'd have to essentially re-implement the entire uniquename feature, but in biblatex). biblatex gets the uniquename info from Biber. The idea here is to disambiguate names (people), it's not about labels that consist of a name and a year. What makes you thin it takes the year into account? Oct 23 '17 at 19:53
• I think you need something else. You need to detect if a given name is an initial or the full thing. Now there are two reasons why you have an initial only (1) the input was an initial, there is no full name given, (2) biblatex truncated a given name to an initial for unqiuename purposes. Case (2) is easy to detect using the uniquename counter. But case (1) is tricky - there is no built-in detection that says whether a name was only given in initials-only form Oct 23 '17 at 19:57
• @moewe Ah, my mistake! I thought it considered the year because the doe2006 entry in my example is printed as "J. doe 2016" instead of "John doe 2016", but that's because I only gave it the initial, of course. I guess I'd have to check if mkbibnamegiven's argument is composed of a single alphabetic character then. I'll try to do that. Thank you for your help, as always. :) Oct 23 '17 at 20:02

## 1 Answer

It doesn't work because #1 is \namepartgiven, which you need to expand in order to get its current value.

\documentclass{article}
\usepackage{lmodern}
\usepackage{xparse}
\usepackage{expl3}
%\usepackage{l3regex} % not needed with a recent version

\usepackage[style=authoryear]{biblatex}

\begin{filecontents*}{\jobname.bib}
@book{doe2016, author = {J. Doe}, date = {2016}}
@book{doe2017, author = {P. Doe}, date = {2017}}
@book{doe2015a, author = {John Doe}, date = {2015}}
@book{doe2015b, author = {James Doe}, date = {2015}}
\end{filecontents*}

\addbibresource{\jobname.bib}

\ExplSyntaxOn

\NewDocumentCommand{\IfInitial}{mmm}
{
\regex_match:nVTF {\w\.} \namepartgiven {{\bfseries #2}} {#3}
}
\cs_generate_variant:Nn \regex_match:nnTF { nV }

\ExplSyntaxOff

\renewcommand*{\mkbibnamefamily}[1]{\MakeLowercase{\scshape#1}}%
\renewcommand*{\mkbibnamegiven}[1]{
\ifnumequal{\value{uniquename}}{2}{%
\IfInitial{#1}{\MakeLowercase{\scshape#1}}{#1}%
}{%
\MakeLowercase{\scshape#1}%
}%
}

\begin{document}

\noindent\cite{doe2015a}\\
\cite{doe2015b}\\
\cite{doe2016}\\% This gives me J. Doe, but I want j. Doe
\cite{doe2017}

\end{document}