2

In LaTeX, I have a macro \p (okay, it's \paragraph, but perhaps the specific macro is not relevant?) with one argument. Sometimes I use it as

\p{plain text}

and sometimes as

\p{\t{alternate 1}{alternate 2}}

(where \t is hyperref's \texorpdfstring, but again, perhaps it doesn't matter). I'd like to redefine or modify \p and/or \t so that \p{plain text} continues to display as normal, but \p{\t{alt 1}{alt 2}} changes to

\p{\t{\extraformatting{alternate 1}}{alternate 2}}

where \extraformatting is some formatting command to be determined.

It has to be done in a way such that what I will physically write in the file is still \p{}. Well, it doesn't have to; this whole exercise is not strictly a requirement, but something that I feel like I should know how to do, but I can't remember.

I got a bit of a start using the \iffirsttoken conditional in this answer, whose "API" is

\iffirsttoken{<tokenlist>}{<token>}{<true>}{<false>}

I figure I can reimplement \p to test #1 against \t and if it matches, somehow insert \extraformatting into the first argument, and otherwise do nothing:

\def\p#1{%
  \iffirsttoken{#1}{\t}{%
    ...something goes here...
  }{%
    #1
  }%
}

but I can't quite figure out what would go in that true condition. Any help?


Here is a MWE that can be copied and pasted:

\documentclass{article}

% stands in for \paragraph - this is preexisting
\def\p#1{p( #1 )p}
% stands in for \texorpdfstring - this is preexisting
\def\t#1#2{t( #1 )t( #2 )t}

\makeatletter
\def\iffirsttoken#1#2{%
  \expandafter\def\expandafter\@first@token\expandafter{\@car#1\@nil}%
  \expandafter\ifx\@first@token#2\relax\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
}
\makeatother

% the extra formatting to apply to the first argument of \t
% this I define myself
\def\e#1{e( #1 )e}

\def\p#1{%
  \iffirsttoken{#1}{\t}{%
    % ...something goes here...
  }{%
    #1
  }%
}

\begin{document}
  The following should be ``p( t( e( arg1 )e )t( arg2 )t )p''

  \p{\t{arg1}{arg2}}

  The following should be ``p( text )p''

  \p{text}
\end{document}
David Z
  • 12,084
  • 7
  • 48
  • 65

2 Answers2

2

I'd say

\usepackage{letltxmacro}
\LetLtxMacro\originalp\p
\LetLtxMacro\originalt\t
\newif\ifp

\renewcommand\p[1]{\ptrue\originalp{#1}\pfalse}

\makeatletter
\renewcommand\t[2]{%
  \originalt{\apply@extraformatting{#1}}{#2}%
}
\newcommand\apply@extraformatting{%
  \ifp
    \expandafter\extraformatting
  \else
    \expandafter\@firstofone
  \fi
}
\makeatother

In this case \t need not be the first token in the argument to \p.

egreg
  • 1,121,712
0

As luck would have it I figured this out when I was just about to submit the question. I can use the fact that \def allows one to specify complex patterns from which arguments will be recognized, not just \def#1#2 etc. So I can write \def\e\t#1#2 to recognize and scoop up \e (the extra formatting), \t (the \texorpdfstring), and its two arguments.

\documentclass{article}

% ... lines omitted ...
\makeatother

\def\e\t#1#2{\t{e( #1 )e}{#2}}
\let\oldp=\p
\def\p#1{\iffirsttoken{#1}{\t}{\oldp{\e#1}}{\oldp{#1}}}

\begin{document}
 % ... lines omitted ...
\end{document}

I make no claims of this being robust, so perhaps someone else can do better.

David Z
  • 12,084
  • 7
  • 48
  • 65