前几天我在思考以下问题。假设我有两个命令,\mycommand
和\mycommandSpecial
:
\newcommand{\mycommand}
{A simple phrase.}
\newcommand{\mycommandSpecial}
{A special phrase!}
现在假设我还有另一个命令,如下所示(当然这不起作用,但它可以让您了解我在寻找什么):
\newcommand{\mynewcommand}[1]
{First this one: #1 -- and then the special one: #1Special}
我希望如果我现在输入的话\mynewcommand{\mycommand}
会得到以下输出:
首先是这个:一个简单的短语。——然后是特殊的一个:一个特殊的短语!
正如你所见,我只想一\mynewcommand
(因为)的论点[1]
,但援引两个都其他命令,利用它们的类似名称,因为特殊命令只是在其名称中添加了一些内容。
不管我想实现什么(以及这是否合理),我一般想知道 LaTeX 是否可以做到这一点,以某种方式修改命令中的命令前执行它们。
我正在研究\expandafter
并\csname … \endcsname
尝试以下方法:
\newcommand{\mynewcommand}[1]
{First this one: #1 -- and then the special one: \expandafter#1\csname#1Special\encsname}
但您立即就会发现它不起作用。
答案1
据我了解,这就是你想要的:
\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}
输出:
答案2
你可以通过\csname
...\endcsname
或 来做到这一点\@nameuse
。但是,由于你传递的是控制序列而不是字符串,所以你必须remove
反击b
s
第一的:
\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
类似于\csname
... \endcsname
,但如果在常规文档中使用,则需要\makeatletter
...对。此外,不会检查传递给的宏是否存在。如果结果宏不存在,则默认为...因此不会打印任何内容。如果需要,可以内置检查。\makeatother
\mynewcommand
\csname
\endcsname
\relax
一个更直观的替代方案可能\macroname
是\@gobble
:\
\makeatletter
\newcommand{\macroname}[1]{\expandafter\@gobble\string#1}
\makeatother
答案3
这迫切需要*
-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*%
}
第一个命令可以称为\mycommand
或\mycommand*
。