# Multiple options for Pseudonyms

I'm looking for something fairly similar to this problem, of defining macros to print pseudonyms for people, but I'm not sure how to modify it (or if it is actually the right approach for what I'm after).

What I'm hoping for is to have a macros that are identifiers for people like \AnGo

When issued as is it should print a pseudonym, so
\AnGo >> "Edwin Smith"

When issued with an option [sh] to print a short form
\AnGo[sh] >> "Ted"

Another option [real] to print the actual name...
\AnGo[real] >> "Antonio Gonzales"

What would be the best approach here?

This is a possible solution:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\definepseudonym}{mmmm}
{% #1 = command, #2 = pseudonym, #3 = short name, #4 = real name
\NewDocumentCommand{#1}{O{pseudonym}}
{
\str_case:nn { ##1 }
{
{pseudonym}{#2}
{sh}{#3}
{real}{#4}
}
}
}
\ExplSyntaxOff

\definepseudonym{\AnGo}{Edwin Smith}{Ted}{Antonio Gonzalez}

\begin{document}

\AnGo[real] was known as \AnGo\ abbreviated in \AnGo[sh].

\end{document}


Here's an extensible solution. You can define as many attributes you wish, besides the pseudonym.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\definepseudonym}{mmm}
{% #1 = command name, #2 = pseudonym, #3 = other names
\cs_new:cpn { #1 } { \genericpseudonym{#1} }
\prop_gclear_new:c { g_pseudonym_#1_prop }
\prop_gset_from_keyval:cn { g_pseudonym_#1_prop } { #3 }
\prop_gput:cnn { g_pseudonym_#1_prop } { pseudonym } { #2 }
}
\NewDocumentCommand{\genericpseudonym}{mO{pseudonym}}
{
\pseudonym_get:nn { #1 } { #2 }
}

\cs_new:Nn \pseudonym_get:nn
{
\prop_item:cn { g_pseudonym_#1_prop } { #2 }
}
\ExplSyntaxOff

\definepseudonym{AnGo}{Edwin Smith}{
sh=Ted,
real=Antonio Gonzalez,
birthplace=Somewhere,
}

\begin{document}

\AnGo[real] was known as \AnGo\ abbreviated in \AnGo[sh].
He was born in \AnGo[birthplace].

\end{document}


• The second extensible version is great as the options can be optional. The only thing I liked about the first option was that the input was simpler (if I'm starting with a list of tab delimited names and turn it into a list with lines of \definepseudonym{}{}{}{} ...). A way to have it both ways? So I could do \definepseudonym{AnGo}{Edwin Smith}{Ted}{}{Somewhere} leaving blank those arguments I don't need/want to reveal. – jan Apr 29 at 13:55
• @jan I'd prefer the key-value syntax rather than multiplying the arguments, making it difficult to remember which is which. With key-value, the order is irrelevant. – egreg Apr 29 at 14:38
• It's probably better ... I can see the point. Just one last question: What would speak against also defining the Pseudonym with the key-value syntax like pseudonym=Edwin Smith (so that only the command itself is mandatory)? – jan Apr 29 at 16:44
• @jan No problem in doing that, of course. – egreg Apr 29 at 16:54

An approach which does without additional packages:

\documentclass[a4paper]{article}
\makeatletter
%%----------------------------------------------------------------------
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%   The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
\UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
\UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%----------------------------------------------------------------------
%% Check whether argument contains no exclamation mark which is not nested
%% in braces:
%%......................................................................
%% \UD@CheckWhetherNoExclam{<Argument which is to be checked>}%
%%                         {<Tokens to be delivered in case that argument
%%                           contains no exclamation mark>}%
%%                         {<Tokens to be delivered in case that argument
%%                           contains exclamation mark>}%
%%
\newcommand\UD@GobbleToExclam{}\long\def\UD@GobbleToExclam#1!{}%
\newcommand\UD@CheckWhetherNoExclam[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToExclam#1!}%
}%
%%----------------------------------------------------------------------
%%  \@PseudonymFork grabs the first thing behind a
%%  a token-sequence of pattern  !!pseudonym!sh!real!
%%......................................................................
\newcommand\@PseudonymFork{}
\long\def\@PseudonymFork#1!!pseudonym!sh!real!#2#3!!!!{#2}%
%%----------------------------------------------------------------------
%% \PseudonymFork
%%......................................................................
\newcommand\PseudonymFork[5]{%
\UD@CheckWhetherNoExclam{#1}{%
\@PseudonymFork!#1!pseudonym!sh!real!{%
\PseudonymForkError
{No identifier in optional argument}%
{#2}%
\PseudonymFork{#2}{#2}{#3}{#4}{#5}%
}%<-case #1 is empty/has no tokens.
!!#1!sh!real!{#3}%<-case #1 = pseudonym.
!!pseudonym!#1!real!{#4}%<-case #1 = sh.
!!pseudonym!sh!#1!{#5}%<-case #1 = real.
!!pseudonym!sh!real!{%
\PseudonymForkError
{Identifier #1' unknown}%
{#2}%
\PseudonymFork{#2}{#2}{#3}{#4}{#5}%
}%<-case #1 = something else without exclamation-mark.
!!!!%
}{\PseudonymForkError{Identifier #1' unknown}{#2}\PseudonymFork{#2}{#2}{#3}{#4}{#5}}%<-case #1 = something else with exclamation-mark.
}%
\newcommand\PseudonymForkError[2]{%
\begingroup
\def\UD@tempa{#1}%
\@onelevel@sanitize\UD@tempa
\@latex@error{%
\string\PseudonymFork:\MessageBreak
\UD@tempa\on@line,\MessageBreak
thus default identifier #2' used instead%
}{%
Either omit the optional argument or specify "sh" or "real"
or "pseudonym".\MessageBreak
Specifying "sh" yields the short form.\MessageBreak
Specifying "real" yields the real name.\MessageBreak
Specifying "pseudonym" yields the pseudonym.\MessageBreak
Omitting the optional argument yields the \PseudonymFork{#2}{#2}{pseudonym}{short form}{real name}.%
}%
\endgroup
}%
%%----------------------------------------------------------------------
%% \DefinePseudonym{<macro name>}%
%%                 {<default>}%
%%                 {<pseudonym>}%
%%                 {<short form>}%
%%                 {<real name>}%
%%----------------------------------------------------------------------
\DeclareRobustCommand\DefinePseudonym[5]{%
\@bsphack
\UD@CheckWhetherNoExclam{#2}{%
\@PseudonymFork
!#2!pseudonym!sh!real!{\UD@firstoftwo}%
!!#2!sh!real!{\UD@secondoftwo}%
!!pseudonym!#2!real!{\UD@secondoftwo}%
!!pseudonym!sh!#2!{\UD@secondoftwo}%
!!pseudonym!sh!real!{\UD@firstoftwo}%
!!!!%
}{\UD@firstoftwo}%
{\DefinePseudonymError{#2}}%
{\@ifdefinable{#1}{\DeclareRobustCommand#1[1][#2]{\PseudonymFork{##1}{#2}{#3}{#4}{#5}}}}%
\@esphack
}%
\newcommand\DefinePseudonymError[1]{%
\begingroup
\def\UD@tempa{#1}%
\@onelevel@sanitize\UD@tempa
\@latex@error{%
\string\DefinePseudonym:\MessageBreak
Default-identifier\UD@CheckWhetherNull{#1}{}{ \UD@tempa'} incorrect\on@line!\MessageBreak
Use one of the identifiers "pseudonym", "sh" or "real" instead%
}{%
Specify either "sh" or "real" or "pseudonym".\MessageBreak
Specifying "sh" yields that the short form will be the default.\MessageBreak
Specifying "real" yields that the real name will be the default.\MessageBreak
Specifying "pseudonym" yields that the pseudonym will be the default.%
}%
\endgroup
}%
%%----------------------------------------------------------------------
\makeatother

\begin{document}

\noindent
\verb|\DefinePseudonym{|%
\textit{$\langle$macro name$\rangle$}%
\verb|}{|%
\textit{$\langle$default$\rangle$}%
\verb|}{|%
\textit{$\langle$pseudonym$\rangle$}%
\verb|}{|%
\textit{$\langle$short~form$\rangle$}%
\verb|}{|%
\textit{$\langle$real~name$\rangle$}%
\verb|}|
\bigskip

\noindent
\verb|\DefinePseudonym{\AnGo}{pseudonym}{Edwin Smith}{Ted}{Antonio Gonzales}|
\DefinePseudonym{\AnGo}{pseudonym}{Edwin Smith}{Ted}{Antonio Gonzales}%

\noindent\hrulefill\null

\noindent
% Error and default; default is pseudonym:
%\verb|\AnGo[unknown specifier]|: \AnGo[unknown specifier]\\
% Error and default; default is pseudonym:
%\verb|\AnGo[]|: \AnGo[]\\
% default; default is pseudonym:
\verb|\AnGo|: \AnGo\\
% pseudonym:
\verb|\AnGo[pseudonym]|: \AnGo[pseudonym]\\
% short form:
\verb|\AnGo[sh]|: \AnGo[sh]\\
% real name:
\verb|\AnGo[real]|: \AnGo[real]

\end{document}


A slight variation of egreg's answer lets you specify at the time of calling \definepseudonym the default in case of not providing an optional argument:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\definepseudonym}{mO{pseudonym}mm}
{% #1 = command name
% #2 = default used in case of not providing the optional argument
% #3 = pseudonym
% #4 = other names
\exp_args:Nc{\NewDocumentCommand}{#1}{O{#2}}
{
\prop_item:cn { g_pseudonym_#1_prop } { ##1 }
}
\prop_gclear_new:c { g_pseudonym_#1_prop }
\prop_gset_from_keyval:cn { g_pseudonym_#1_prop } { #4 }
\prop_gput:cnn { g_pseudonym_#1_prop } { pseudonym } { #3 }
}
\ExplSyntaxOff

\definepseudonym{AnGo}[pseudonym]{Edwin Smith}{
sh=Ted,
real=Antonio Gonzalez,
birthplace=Somewhere,
}

\begin{document}

\AnGo[real] was known as \AnGo[pseudonym] abbreviated in \AnGo[sh].
He was born in \AnGo[birthplace].

Applying \verb|\AnGo| without optional argument yields the pseudonym: \AnGo

This is because within \verb|\definepseudonym|'s second argument, which is
optional, "pseudonym" was specified as the default which is to be used when
not providing an optional argument.

If instead of "pseudonym", e.g., "real" was specified here, then
\verb|\AnGo| without optional argument would yield the real
name/the value of the "real"-property.

\end{document}


Another variation where the "pseudonym"-property is not treated separately from other properties/other names:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\definepseudonym}{mO{pseudonym}m}
{% #1 = command name
% #2 = default used in case of not providing the optional argument
% #3 = property-value-list
\exp_args:Nc{\NewDocumentCommand}{#1}{O{#2}}
{
\prop_item:cn { g_pseudonym_#1_prop } { ##1 }
}
\prop_gclear_new:c { g_pseudonym_#1_prop }
\prop_gset_from_keyval:cn { g_pseudonym_#1_prop } { #3 }
}
\ExplSyntaxOff

\definepseudonym{AnGo}[pseudonym]{
pseudonym=Edwin Smith,
sh=Ted,
real=Antonio Gonzalez,
birthplace=Somewhere,
}

\begin{document}

\AnGo[real] was known as \AnGo[pseudonym] abbreviated in \AnGo[sh].
He was born in \AnGo[birthplace].

Applying \verb|\AnGo| without optional argument yields the pseudonym: \AnGo

This is because within \verb|\definepseudonym|'s second argument, which is
optional, "pseudonym" was specified as the default which is to be used when
not providing an optional argument.

If instead of "pseudonym", e.g., "real" was specified here, then
\verb|\AnGo| without optional argument would yield the real
name/the value of the "real"-property.

\end{document}


Yet another variation could be letting you specify a global default-value for the optional argument of a pseudonym-macro which at the time of calling \definepseudonym can be overridden via also specifying the default-property within \definepseudonym's second argument:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\cs_generate_variant:Nn \prop_item:Nn {cx}
\tl_new:N {\jan_GlobalPseudonymDefault}
\tl_gset:Nn {\jan_GlobalPseudonymDefault} {pseudonym}
\NewDocumentCommand{\SetGlobalPseudonymDefault}{m}{\tl_gset:Nn {\jan_GlobalPseudonymDefault} {#1}}
\NewDocumentCommand{\definepseudonym}{mm}
{% #1 = command name
% #2 = property-value-list
\exp_args:Nc{\NewDocumentCommand}{#1}{O{default}}
{
\prop_item:cn { g_pseudonym_#1_prop } { ##1 }
}
\prop_gclear_new:c { g_pseudonym_#1_prop }
\prop_gset_from_keyval:cn { g_pseudonym_#1_prop } { #2 }
\prop_if_in:cnTF{ g_pseudonym_#1_prop }{ default }{}{%
\prop_gput:cnV { g_pseudonym_#1_prop } { default } { \jan_GlobalPseudonymDefault }
}
\prop_gput:cnx { g_pseudonym_#1_prop } { default }
{ \prop_item:cx { g_pseudonym_#1_prop } { \prop_item:cn { g_pseudonym_#1_prop } { default } } }
}
\ExplSyntaxOff

% The global default is initialized to "peseudonym" but we change it
% to the real name:
\SetGlobalPseudonymDefault{real}

\definepseudonym{AnGo}{
pseudonym=Edwin Smith,
sh=Ted,
real=Antonio Gonzalez,
birthplace=Somewhere,
% Override the global default:
%default=sh,
default=pseudonym,
}

\begin{document}

\AnGo[real] was known as \AnGo[pseudonym] abbreviated in \AnGo[sh].
He was born in \AnGo[birthplace].

Applying \verb|\AnGo| without optional argument yields the pseudonym: \AnGo

This is because within \verb|\definepseudonym|'s second argument, pseudonym
was specified as the value of the default-property.

If the default-property would not have been specified here, it would have
got the value stored in \verb|\jan_GlobalPseudonymDefault|, which in turn
can be changed globally via \verb|\SetGlobalPseudonymDefault|.

\end{document}

• But wasn't this already how it was working in egreg's answer? – jan Apr 29 at 16:58
• @jan Maybe I am overlooking something but if I got it right, with egreg's answer the default delivered in case of not providing \AnGo's optional argument is hardcoded as "pseudonym" in the parameter text of the definition of the \genericpseudonym-macro and thus cannot be specified differently at the time of calling \definepseudonym. – Ulrich Diez Apr 29 at 17:03
• I tried with \NewDocumentCommand{\genericpseudonym}{mO{real}} and it did what it was supposed to. – jan Apr 29 at 17:06
• @jan Sure. But this implies modification/redefinition of \genericpseudonym. You may wish at the same time to do something like \definepseudonym{AnGo}[pseudonym]{Edwin Smith}{sh=Ted, real=Antonio Gonzalez, birthplace=Somewhere,} ... \definepseudonym{Gambol}[sh]{John Doe}{sh=Johann Gambolputty, real=Johann Gambolputty de von Ausfern-schplenden-schlitter-crasscrenbon-..., birthplace=Monty-Python-Land,} ...  The default-properties in the optional arguments differ... \AnGo (without optional argument) yields the pseudonym. \Gambol (without optional argument) yields the short form. – Ulrich Diez Apr 29 at 17:13
• I see your point. But in that case wouldn't it be better to have something like \definepseudonym{AnGo}{pseudonym=Edwin Smith, sh=Ted, real=Antonio Gonzalez, birthplace=Somewhere, } and define globally which to make the default? – jan Apr 29 at 17:20