6

I have been studying the code from this TUGboat article by Joseph Wright and Christian Feurersänger (Volume 30, 2009, No. 1) explaining key-value techniques. I understand the use of \expandafter\@firstofone in the first two user macros but I can't understand where the second argument referenced by \@secondoftwo comes from in the third user macro. Is it the name of the desired color passed to the colour option?

I understand how the expansion works here. I don’t understand exactly why \@secondoftwo is used rather than \@firstofone. The question https://tex.stackexchange.com/a/21263/218142 makes the distinction very clear, but I can’t see the distinction in this case.

Here is the (slightly edited by me) MWE package file:

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{xmph}[2008/03/17 v1.0 Extended emph] 
\RequirePackage{color,kvoptions} 
\SetupKeyvalOptions{%
  family=xmph,
  prefix=xmph@
}%
\DeclareBoolOption{useitalic}
\DeclareBoolOption{usebold}
\DeclareBoolOption{usecolour}
\DeclareBoolOption{usecolor}
\let\KV@xmph@usecolor
  \KV@xmph@usecolour
\DeclareStringOption{colour}
\define@key{xmph}{color}{\setkeys{xmph}{colour=#1}}
\DeclareVoidOption{inactive}{%
  \PackageInfo{xmph}{Package inactive}%
  \AtEndOfPackage{\let\xmph\emph}%
}%
\setkeys{xmph}{useitalic,colour=red}
\ProcessKeyvalOptions{xmph}
\define@key{xmph}{inactive}{%
  \PackageInfo{xmph}{Package inactive}
  \let\xmph\emph
}%
\AtBeginDocument{%
  \DisableKeyvalOption[action=warning,package=xmph]{xmph}{inactive}
}%
\newcommand*{\xmphsetup}{%
  \setkeys{xmph}%
}%

\newcommand{\xmph}[1]{% \xmph@emph{% \xmph@bold{% {% \xmph@colourtext{#1} }% }% }% }% \newcommand{\xmph@emph}{% \ifxmph@useitalic \expandafter\emph \else \expandafter@firstofone \fi }% \newcommand{\xmph@bold}{% \ifxmph@usebold \expandafter\textbf \else \expandafter@firstofone \fi }% \newcommand{\xmph@colourtext}{% \ifxmph@usecolour \expandafter\textcolor \else \expandafter@secondoftwo \fi {\xmph@colour} }%

And here is the (again, slightly edited) MWE document using the package file:

% !TEX TS-program = lualatexmkjoe
% !TEX encoding = UTF-8 Unicode

\documentclass{article} \usepackage[usecolour,color=blue,usebold]{xmph} %\xmphsetup{inactive}

\begin{document} Some text \xmph{text}

\xmphsetup{usecolor=false,usebold=false,useitalic=false}% \xmph{more text}

\xmphsetup{usecolor=true,color=cyan,usebold=false,useitalic=true}% \xmph{more text}

\xmphsetup{usecolor=false,usebold=false,useitalic=false}% \xmph{even more text} \end{document}

  • 1
    You want to get effectively \textcolor{\xmph@colour}<stuff> or just <stuff>, and do not want to drown in \expandafters, so you decide to skip over {\xmph@colour} if you just want to have <stuff>. –  Dec 24 '20 at 02:09
  • That makes sense. Is the second argument the desired color? – LaTeXereXeTaL Dec 24 '20 at 02:22
  • How would I know which color you desire? ;-) –  Dec 24 '20 at 02:28
  • What's confusing me is that \xmph is defined with one parameter but the use of \@secondoftwo implies a second parameter and I can't see where it comes from. – LaTeXereXeTaL Dec 24 '20 at 02:30

3 Answers3

8

Consider the call \xmph{foo} abc. This translates into

\xmph@emph{\xmph@bold{{\xmph@colourtext{foo} }}} abc

according to your code. Now \xmph@emph is expanded. This turns into

\ifxmph@useitalic\expandafter\emph\else\expandafter\@firstofone\fi⮐
{\xmph@bold{{\xmph@colourtext{foo} }}} abc

(the symbol denotes continuation). According to the truth value of \ifxmph@useitalic, this becomes either

\emph{\xmph@bold{{\xmph@colourtext{foo} }}} abc

or

\@firstofone{\xmph@bold{{\xmph@colourtext{foo} }}} abc

The latter just strips the braces off the argument and I'll follow this case for simplicity. We get

\xmph@bold{{\xmph@colourtext{foo} }} abc

and this turns into

\ifxmph@usebold\expandafter\textbf\else\expandafter\@firstofone\fi⮐
\xmph@bold{{\xmph@colourtext{foo} }} abc

Again, depending on the truth value of \ifxmph@usebold we get either

\textbf{{\xmph@colourtext{foo} }} abc

or

\@firstofone{{\xmph@colourtext{foo} }} abc

Let's follow the latter case, getting

{\xmph@colourtext{foo} } abc

The opening brace is digested, opening a group; then we obtain

\ifxmph@usecolour\expandafter\textcolor\else\expandafter\@secondoftwo\fi⮐
{\xmph@colour} {foo} } abc

Depending on the value of \ifxmph@usecolour we get either

\textcolor{\xmph@colour} {foo} } abc

or

\@secondoftwo{\xmph@colour} {foo} } abc

Now you should clearly see why \@secondoftwo is necessary, so the color part is removed from the input stream. The space in the middle is removed by rule, because \@secondoftwo takes two undelimited arguments (and \textcolor eventually calls a macro taking two arguments as well).

Now foo is printed (colored or not), the following space is printed, the group that had been opened is closed, another space is printed and processing continues from abc.

The cases when \emph and \textbf are used just add some complications which are irrelevant as far as understanding \@secondoftwo is concerned.

You see that you have two points that should be fixed: the spurious spaces and the useless group. Try the input

\documentclass{article}
\usepackage[usecolour,color=blue,usebold]{xmph}
%\xmphsetup{inactive}

\begin{document}

Some text \emph{\textbf{\textcolor{blue}{text}}} some text

Some text \xmph{text} some text

\xmphsetup{usecolor=false,usebold=false,useitalic=false}

\xmph{more text} some text

\xmphsetup{usecolor=true,color=cyan,usebold=false,useitalic=true}

\xmph{more text} some text

\xmphsetup{usecolor=false,usebold=false,useitalic=false}

\xmph{even more text} some text

\end{document}

enter image description here

and you'll see the spurious space. Fix the missing % tokens (and getting rid of the unneeded ones) and remove the useless group:

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{xmph}[2008/03/17 v1.0 Extended emph] 
\RequirePackage{color,kvoptions} 
\SetupKeyvalOptions{%
  family=xmph,
  prefix=xmph@
}
\DeclareBoolOption{useitalic}
\DeclareBoolOption{usebold}
\DeclareBoolOption{usecolour}
\DeclareBoolOption{usecolor}
\let\KV@xmph@usecolor\KV@xmph@usecolour
\DeclareStringOption{colour}
\define@key{xmph}{color}{\setkeys{xmph}{colour=#1}}
\DeclareVoidOption{inactive}{%
  \PackageInfo{xmph}{Package inactive}%
  \AtEndOfPackage{\let\xmph\emph}%
}
\setkeys{xmph}{useitalic,colour=red}
\ProcessKeyvalOptions{xmph}
\define@key{xmph}{inactive}{%
  \PackageInfo{xmph}{Package inactive}%
  \let\xmph\emph
}
\AtBeginDocument{%
  \DisableKeyvalOption[action=warning,package=xmph]{xmph}{inactive}%
}
\newcommand*{\xmphsetup}{%
  \setkeys{xmph}%
}

\newcommand{\xmph}[1]{% \xmph@emph{% \xmph@bold{% \xmph@colourtext{#1}% }% }% } \newcommand{\xmph@emph}{% \ifxmph@useitalic \expandafter\emph \else \expandafter@firstofone \fi } \newcommand{\xmph@bold}{% \ifxmph@usebold \expandafter\textbf \else \expandafter@firstofone \fi } \newcommand{\xmph@colourtext}{% \ifxmph@usecolour \expandafter\textcolor \else \expandafter@secondoftwo \fi {\xmph@colour}% }

Now the same input file as before yields

enter image description here


Here is an implementation with expl3. There is no \expandafter and the coding is much more straightforward.

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{xmph}[2008/03/17 v1.0 Extended emph]
\RequirePackage{expl3,xparse,l3keys2e}
\RequirePackage{color}

\ExplSyntaxOn

%%% define the keys \keys_define:nn { xmph } { useitalic .bool_set:N = \l_xmph_italic_bool, useitalic .default:n = true, usebold .bool_set:N = \l_xmph_bold_bool, usebold .default:n = true, usecolour .bool_set:N = \l_xmph_colour_bool, usecolour .default:n = true, usecolor .bool_set:N = \l_xmph_colour_bool, usecolor .default:n = true, colour .tl_set:N = \l_xmph_colour_tl, color .tl_set:N = \l_xmph_colour_tl, inactive .code:n = __xmph_inactivate:, inactive .value_forbidden:n = true, }

% we don't want to set inactive in the document \AtBeginDocument { \keys_define:nn { xmph } { inactive .code:n = \PackageWarning{xmph}{Disabled~option}, } }

% process the package keys \ProcessKeysPackageOptions { xmph }

%%% user level commands

\NewDocumentCommand{\xmphsetup}{m} { \keys_set:nn { xmph } { #1 } }

\NewDocumentCommand{\xmph}{m} { \xmph_emph:n { \xmph_bold:n { \xmph_colour:n { #1 } } } }

%%% internal functions

\cs_new_protected:Nn __xmph_inactivate: { \PackageInfo{xmph}{Package~inactive} \AtBeginDocument{\cs_set_eq:NN \xmph \emph} }

\cs_new_protected:Nn \xmph_emph:n { \bool_if:NTF \l_xmph_italic_bool { \emph { #1 } } { #1 } } \cs_new_protected:Nn \xmph_bold:n { \bool_if:NTF \l_xmph_bold_bool { \textbf { #1 } } { #1 } } \cs_new_protected:Nn \xmph_colour:n { \bool_if:NTF \l_xmph_colour_bool { \textcolor { \l_xmph_colour_tl } { #1 } } { #1 } }

\ExplSyntaxOff

egreg
  • 1,121,712
  • AHA! My conceptual block was in thinking that \@firstofone and \@secondoftwo and such could only be used on parameters #1 or #2 etc. and not on general tokens. That was my problem and you cleared it up. – LaTeXereXeTaL Dec 24 '20 at 18:06
4

You should follow the expansion in order to understand the use of \@secondoftwo. Consider a call to

\xmph{<stuff>}

\xmph takes a single argument, based on its definition, and passes that on directly to \xmph@colourtext{#1}.

Now, \xmph@colourtext is defined to take no argument. So, with the usecolor option set to true,

\ifxmph@usecolour 
  \expandafter\textcolor
\else 
  \expandafter\@secondoftwo
\fi

expands to \textcolor. With \usecolor=false, it expands to \@secondoftwo. Before closing, \xmph@colourtext inserts {\xmph@colour} into the input stread, effectively turning \xmph@colourtext{<stuff>} into \textcolor{\xmph@colour}{<stuff>} or \@secondoftwo{\xmph@colour}{<stuff>}.

So, the \@secondoftwo skips the reference to colour (\xmph@colour) and just prints <stuff>.

Werner
  • 603,163
2

As written in my comment, and copied by Werner, this is to skip over {\xmph@colour}. That is, you want to get effectively \textcolor{\xmph@colour} or just , and do not want to drown in \expandafters, so you decide to skip over {\xmph@colour} if you just want to have .

In other words, when you call

\xmph{<stuff>}

there are two cases. In case \ifxmph@usecolour is true, you get

\textcolor{\xmph@colour}<stuff>

On the other hand, if \ifxmph@usecolour, you get \@secondoftwo{\xmph@colour}{<stuff>}, which is just {<stuff>}.

  • Let me approach this differently. What if \@firstofone had been used instead of \@secondoftwo. Would the code work the same way? I understand the expansion. – LaTeXereXeTaL Dec 24 '20 at 04:06
  • 1
    @LaTeXereXeTaL You could have moved {\xmph@colour} right after \textcolor but then you would have to start an orgy of \expandafters to get after {, \xmph@colour and }. This is what I meant by drowning in \expandafter. –  Dec 24 '20 at 05:41
  • Okay now your explanation makes sense. I thought \@firstofone and \@secondoftwo were tied to arguments like #1 and #2. That was my problem. – LaTeXereXeTaL Dec 24 '20 at 18:09