4

I was wondering the other day about the following. Suppose I have two commands, \mycommand and \mycommandSpecial:

\newcommand{\mycommand}
    {A simple phrase.}
\newcommand{\mycommandSpecial}
    {A special phrase!}

Suppose now that I also have another command, along the lines of the following (which of course does not work, but it gives you a sense of what I am looking for):

\newcommand{\mynewcommand}[1]
    {First this one: #1 -- and then the special one: #1Special}

My hope is that if I now type \mynewcommand{\mycommand} I would get the following output:

First this one: A simple phrase. -- and then the special one: A special phrase!

I want, as you can see, to have only one argument for \mynewcommand (because of [1]), but invoking both of the other commands, making use of their similar names, as the special command has only something added to its name.

Regardless of what I want to achieve (and whether this is reasonable), I was wondering generally whether LaTeX can do this, somehow modifying the commands within a command before executing them.

I was looking into \expandafter and \csname … \endcsname and tried something along the lines of:

 \newcommand{\mynewcommand}[1]
    {First this one: #1 -- and then the special one: \expandafter#1\csname#1Special\encsname}

But it does not work as you will see immediately.

  • Why don't you post a minimal working example? – Johannes_B Oct 22 '17 at 6:03
2

Here is what you want as I can understand it:

\documentclass{article}
\newcommand{\mycommand}
    {A simple phrase.}
\newcommand{\mycommandSpecial}
    {A special phrase!}

\newcommand{\executeBoth}[1]{Here is firs: ``\csname#1\endcsname''\par Here is second: ``\csname#1Special\endcsname''}

\newcommand{\executeSelected}[1][0]{\ifnum#1=0 Fisrt command selected:``\mycommand''\else Second selected: ``\mycommandSpecial''\fi}

\newcommand{\myscommand}[1]
    {A simple phrase. And a \emph{#1}}
\newcommand{\myscommandSpecial}[1]
    {A special phrase! And no \emph{#1}}

\newcommand{\executesBoth}[2][pig]{Here is firs: ``\csname#2\endcsname{#1}''\par Here is second: ``\csname#2Special\endcsname{#1}''}

\newcommand{\executesSelected}[2][0]{\ifnum#1=0 Fisrt command selected:``\myscommand{#2}''\else Second selected: ``\myscommandSpecial{#2}''\fi}


\begin{document}

One command will execute both:

\executeBoth{mycommand}\vspace{20pt}

Next command without argument will execute first:

\executeSelected\vspace{20pt}

Next command with optional non zero will execute second:

\executeSelected[8]\vspace{40pt}




{\bfseries with arguments}\vspace{10pt}

One command will execute both:

\executesBoth{myscommand}\vspace{20pt}

Next command without argument will execute first:

\executesSelected{ball}\vspace{20pt}

Next command with optional non zero will execute second:

\executesSelected[8]{ball}

\end{document}

Output:

enter image description here

  • 1
    please note that this will not give an error or warning if you misspell the name of a command – jakun Oct 22 '17 at 7:21
  • @jakun it is just the basic idea... We can expand it with \ifcsname but I thing the OP needs just a way to start and to see of such way is useful for him. Usefull comment although. – koleygr Oct 22 '17 at 7:27
4

You can do this via \csname...\endcsname or \@nameuse. However, since you're passing a control sequence rather than a string, you'll have to remove the backslash first:

enter image description here

\documentclass{article}

% https://tex.stackexchange.com/a/42337/5764
\begingroup\lccode`\|=`\\
\lowercase{\endgroup\def\removebs#1{\if#1|\else#1\fi}}
\newcommand{\macroname}[1]{\expandafter\removebs\string#1}

\newcommand{\mycommand}
  {A simple phrase.}
\newcommand{\mycommandSpecial}
  {A special phrase!}
\newcommand{\mynewcommandA}[1]
  {First this one: #1{} -- and then the special one: \csname\macroname{#1}Special\endcsname}
\makeatletter
\newcommand{\mynewcommandB}[1]
  {First this one: #1{} -- and then the special one: \@nameuse{\macroname{#1}Special}}
\makeatother

\begin{document}

\verb|\mycommand|: \mycommand

\verb|\mycommandSpecial|: \mycommandSpecial

\verb|\mynewcommandA{\mycommand}|: \mynewcommandA{\mycommand}

\verb|\mynewcommandB{\mycommand}|: \mynewcommandB{\mycommand}

\end{document}

\@nameuse is similar to \csname...\endcsname, but requires a \makeatletter...\makeatother pair if used in a regular document. Also, no checking is performed whether the macro passed to \mynewcommand exists. \csname...\endcsname defaults to \relax if the resulting macro doesn't exist and therefore will print nothing. One can build in a check, if needed.


A somewhat more intuitive alternative to \macroname could be to \@gobble the \:

\makeatletter
\newcommand{\macroname}[1]{\expandafter\@gobble\string#1}
\makeatother
  • Oh! How very interesting! I am slightly puzzled though that the solution apparently is quite complicated (see the first lines about \begingroup … and the definition of \macroname). Does this mean that modifying command names prior to their execution is not part of the standard toolbox of latex? I.e. there are no readymade commands that do this? – ClintEastwood Oct 22 '17 at 6:12
  • 1
    @ClintEastwood: Construction of control sequences is done using \csname...\endcsname. However, your input requires the deconstruction of a control sequence before constructing it the "special" version. – Werner Oct 22 '17 at 6:22
  • @ClintEastwood: Using \csname\macroname{#1}\endcsname was superfluous. It just defaults to #1; I've updated my code for that. – Werner Oct 22 '17 at 6:23
  • ahh, I see now. thanks for clarifying this. So if the input were without a backslash, then one would not have to reconstruct first, right? (So much I gathered now from your response and the alternative solution by koleygr.) – ClintEastwood Oct 22 '17 at 6:26
  • @ClintEastwood: Indeed. It's easier to work with \mynewcommand{mycommand}. – Werner Oct 22 '17 at 6:39
2

This screams for *-variant.

\usepackage{xparse}

\NewDocumentCommand{\mycommand}{s}{%
  \IfBooleanTF{#1}{A simple phrase.}{A special phrase!}%
}

\newcommand{\mynewcommand}[1]{%
  First this one: #1 -- and then the special one: #1*%
}

The first command can be called \mycommand or \mycommand*.

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.