有没有办法给命令的参数赋予一个“名称”并在其定义中使用它们?我想要做的是能够使用“标签”而不是来获取参数的值#myargname
。#<number>
例如,我想定义\foocommand
一个
\newcommand{\foocommand}[#normal,#bold,#italics,#smallcaps,#emphasis]%
{#normal \textbf{#bold} \textit{#italics} \textsc{#smallcaps} \emph{#emphasis}}
代替
\newcommand{\foocommand}[5]%
{#1 \textbf{#2} \textit{#3} \textsc{#4} \emph{#5}}
答案1
你可以。这是一个概念证明。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\newparametercommand}{smO{}m}
{
\IfBooleanTF { #1 }
{
\ntakwetet_newparametercommand:Nnnn \cs_set_nopar:cV { #2 } { #3 } { #4 }
}
{
\ntakwetet_newparametercommand:Nnnn \cs_set:cV { #2 } { #3 } { #4 }
}
}
\tl_new:N \l__ntakwetet_replacement_tl
\int_new:N \l__ntakwetet_index_int
\cs_generate_variant:Nn \cs_set:Nn { cV }
\cs_generate_variant:Nn \cs_set_nopar:Nn { cV }
\cs_new_protected:Nn \ntakwetet_newparametercommand:Nnnn
{
\tl_set:Nn \l__ntakwetet_replacement_tl { #4 }
% double the #
\regex_replace_all:nnN { \cP. } { \cP\#\cP\# } \l__ntakwetet_replacement_tl
% index for the parameters
\int_zero:N \l__ntakwetet_index_int
% substitute any item in the list of parameters with #<n>
\clist_map_inline:nn { #3 }
{
\int_incr:N \l__ntakwetet_index_int
\exp_args:Nne \regex_replace_all:nnN
{ ##1 } % search
{ \exp_not:n { \cP\# } \int_eval:n { \l__ntakwetet_index_int } } % replace
\l__ntakwetet_replacement_tl
}
% define a temporary macro with #1=\cs_set:cV or \cs_set_nopar:cV
#1 {__ntakwetet_temp:\prg_replicate:nn { \l__ntakwetet_index_int } { n } } % name
\l__ntakwetet_replacement_tl % replacement
\cs_new_eq:Nc #2 {__ntakwetet_temp:\prg_replicate:nn { \l__ntakwetet_index_int } { n } }
}
\ExplSyntaxOff
\newparametercommand\foo[#abc,#def]{#abc,#def}
\newparametercommand*\baz[#abc,#def]{#abc--#def}
\newparametercommand{\foocommand}[#normal,#bold,#italics,#smallcaps,#emphasis]{%
#normal \textbf{#bold} \textit{#italics} \textsc{#smallcaps} \emph{#emphasis}%
}
\begin{document}
\foo{a}{b}
\baz{a}{b}
\foocommand{normal}{bold}{italics}{smallcaps}{emphasis}
\end{document}
在替换文本中搜索逗号分隔列表中的每个项目,并将其替换#<n>
为当前索引。
限制:关键字不能以另一个关键字作为起始段。因此#a
和#aa
不起作用。当然,也不能使用超过 9 个参数。
答案2
虽然不是自动的,但简单且容易。
\documentclass{article}
\newcommand{\foo}[2]% #1=\first, #2=\second
{\bgroup% make definitions local
\def\first{#1}%
\def\second{#2}%
Arguments are \first{} and \second.
\egroup}
\begin{document}
\foo{A}{B}
\end{document}
可替代,但容易出错。
\documentclass{article}
\newcommand{\foo}[1]% #1 = TeX definitions
{\bgroup% make definitions local
#1
Arguments are \first{} and \second.
\egroup}
\begin{document}
\foo{\def\first{A}\def\second{B}}
\end{document}
答案3
经过编辑以消除先前方法的缺陷。
如果您不介意按照下列方式更改语法:
将符号参数标识符从 更改
#
为非 cat 6 的内容,此处完成!
用 定义新命令
\symbolicnewcommand
,因为\newcommand
已经用不同的语法定义。
因此,语法如下:
\symbolicnewcommand{\foocommand}%
[!normal,!bold,!italics,!smallcaps,!emphasis,!boxed]%
{!normal{} \textbf{!bold} \textit{!italics}
\textsc{!smallcaps} \emph{!emphasis} \fbox{!boxed}}
与我之前的方法不同,这种方法不仅仅是模仿\newcommand
行为,而且通过将符号参数转换为显式的 、 等来重新创建它#1
(#2
即不是放置在 a 内\def
)。
这是 MWE。请注意,在\meaning
定义的宏的中,符号参数(例如)!normal
被转换为显式的#1
。
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{listofitems,tokcycle}
\newtoks\mytoks
\newtoks\tmptoks
\def\OPENSgroup{\OPENSgroup}% quark
\def\CLOSEgroup{\CLOSEgroup}% quark
\def\SPACEquark{\SPACEquark}% quark
\newcommand{\addtotoks}[2]{#1\expandafter{\the#1#2}}
\newcommand{\xaddtotoks}[2]{%
\expandafter\addtotoks\expandafter#1\expandafter{#2}}
\makeatletter
\long\def\symbolicnewcommand#1[#2]#3{%
\readlist*\arglist{#2}%
\stripgroupingtrue%
\tokcycle{\addcytoks{##1}}%
{\addcytoks{\OPENSgroup}\processtoks{##1}\addcytoks{\CLOSEgroup}}%
{\addcytoks{##1}}{\addcytoks{\SPACEquark}}{#3}%
\mytoks\expandafter{\the\cytoks}%
\foreachitem\z\in\arglist[]{%
\expandafter\setsepchar\expandafter{\z}%
\expandafter\def\expandafter\tmp\expandafter{\the\mytoks}%
\readlist*\cmdlist{\tmp}%
\mytoks{}%
\foreachitem\zz\in\cmdlist[]{%
\ifnum\zzcnt=1\relax\else%
\tmptoks{&}%
\xaddtotoks\tmptoks{\zcnt}%
\xaddtotoks\mytoks{\the\tmptoks}%
\fi%
\xaddtotoks\mytoks{\zz}%
}%
}%
%
\setsepchar{&}%
\expandafter\readlist\expandafter\cmdlist\expandafter{\the\mytoks}%
\mytoks{}%
\foreachitem\z\in\cmdlist[]{%
\ifnum\zcnt=1\relax\else\addtotoks\mytoks{####}\fi%
\xaddtotoks\mytoks{\z}%
}%
%
\expandafter\addBracesSpaces\expandafter{\the\mytoks}%
%
\def\tmp{\newcommand{#1}[\arglistlen]}%
\expandafter\tmp\expandafter{\the\mytoks}%
}
\newcommand\addBracesSpaces[1]{\mytoks{}\fooaux#1\endfoo}
\def\fooaux#1{%
\tctestifx{\endfoo#1}{}
{\tctestifx{\OPENSgroup#1}{\Z}
{\tctestifx{\SPACEquark#1}{\addtotoks\mytoks{ }}
{\addtotoks\mytoks{#1}}\fooaux}}%
}
\makeatother
\def\Z#1\CLOSEgroup{\addtotoks\mytoks{{#1}}\fooaux}
\symbolicnewcommand{\foocommand}%
[!normal,!bold,!italics,!smallcaps,!emphasis,!boxed]%
{!normal{} \textbf{!bold} \textit{!italics}
\textsc{!smallcaps} \emph{!emphasis} \fbox{!boxed}}
\begin{document}
\meaning\foocommand
\foocommand{To be,}{or not}{to be?}{That}{is the question.}{123}
\end{document}