我看见这个答案,它使用该etoolbox
包创建一个带有可选参数的宏。不幸的是,我无法让它工作。这是一个最小的工作示例:
\documentclass[12pt]{article}
\usepackage{etoolbox}
\newcommand\mymacrotwo[2][]{
\ifstrempty{#2}{
#1: none
}{
#1: #2
}
}
\begin{document}
\mymacrotwo{hello}
\mymacrotwo{hello}{world}
\end{document}
输出:
: hello
: hello world
不仅冒号位置不对,而且none
如果第二个参数未定义,它也不会显示。问题出在哪里?
我也尝试过这个变体:
\documentclass[12pt]{article}
\usepackage{etoolbox}
\newcommand{\mymacro}[2]{#1 \ifboolexpr{ test {\ifdef{#2}} } {#2} {none}}
\begin{document}
\mymacro{hello}
\mymacro{hello}{world}
\end{document}
但输出如下:
hello
hello orldworld
这显然也是不对的。
答案1
如果 TeX 宏定义为具有两个参数,TeX 将总是为两个参数分配一些标记,或者引发错误。
定义
\newcommand\mymacrotwo[2]{
\ifstrempty{#2}{
#1: none
}{
#1: #2
}
}
已经有一些缺点了,因为你添加了几个空格,这些空格会在打印输出中显示出来。更好的做法是
\newcommand\mymacrotwo[2]{%
\ifstrempty{#2}%
{%
#1: none%
}%
{%
#1: #2%
}%
}
如何对齐替代括号是个人喜好问题,但行尾应该被遮盖,除非你做想要一个可以展现的空间。
让我们看看如果你输入
\mymacrotwo{hello} and some text
宏有二参数;第一个被确定为hello
,因为扫描了一个括号;第二个参数将是a
:在寻找参数时,TeX 会采用第一个非空间找到的标记,除非它是{
;在这种情况下,参数是匹配的任何内容}
。
如果你打电话
\mymacrotwo{hello}
and some text
它会完全相同,因为 TeX 将行尾转换为空格,并且在寻找参数时会忽略空格。
技术说明:这里我谈论的是未限定参数,即在涉及定义的宏时所寻找的类型\newcommand
。
留一个空行也无济于事:
\mymacrotwo{hello}
and some text
第二个参数是\par
,因为 TeX 将空行转换为\par
标记。
让我们验证一下。我将使用宏的简化版本,仅打印其参数:
\documentclass{article}
\newcommand{\mymacrotwo}[2]{%
``{\ttfamily \#1 is \detokenize{#1}, \#2 is \detokenize{#2}}''%
}
\begin{document}
\mymacrotwo{hello} and some text
\mymacrotwo{hello}
and some text
\mymacrotwo{hello}
and some text
\end{document}
因此,如果你想按预期使用宏,你必须也可以叫它
\mymacrotwo{hello}{}
或者
\mymacrotwo{hello}{world}
实际上,xparse
您可以定义具有所需特性的宏,但这是否符合 LaTeX 语法还有待商榷。
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\mymacrotwo}{ m g }
{%
\IfNoValueTF{#2}%
{%
#1: none%
}
{
#1: #2%
}%
}
\begin{document}
\mymacrotwo{hello} and some text
\mymacrotwo{hello}{world} and some text
\end{document}
我绝对不会建议使用此功能。