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}
  • Does \t necessarily appear only as the first token in \p? – egreg Oct 25 '15 at 9:39
  • Yes, in my scenario if \t appears in the argument to \p it will be the first token. – David Z Oct 25 '15 at 12:03
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.

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.