![参数中的空行导致失败](https://linux22.com/image/385117/%E5%8F%82%E6%95%B0%E4%B8%AD%E7%9A%84%E7%A9%BA%E8%A1%8C%E5%AF%BC%E8%87%B4%E5%A4%B1%E8%B4%A5.png)
由于某些原因,\NewDocumentCommand
从xparse
其他包裹\newcommand
必须使用 Latex
空行中断 xparse 或 ifthen 宏
但是下面的示例代码仍然无法编译。为什么?
\documentclass{article}
\usepackage{xparse}
\usepackage[most]{tcolorbox}
\begin{document}
\NewDocumentCommand{\mycmd}{+O{}m}{% notice "+O{}"
\begin{tcbitemize}[#1]
#2
\end{tcbitemize}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\mycmd[
colback=yellow,
coltext=red
]
{\tcbitem some text}
\end{document}
答案1
正如 Andrew 在评论中所说,问题不在于您的\mycmd
,而在于 PGF 的密钥解析器中更深层的地方。该问题已在\pgfkeys@addpath
宏中报告。
第一个也是最简单的选择是删除空白行。在这种情况下,段落分隔符没有多大意义。如果您希望在按键之间有视觉分隔,您可以随时注释行尾:
\mycmd[
colback=yellow,
% <- here
coltext=red
]
第二种选择可以重新定义\pgfkeys@addpath
使其变长。剧透警告:另一个宏可能会在不久后发出抱怨,因为令牌\par
将通过键值解析器传递。但假设您设法使所有这些宏都成为\long
。那么解析器最终会看到这样的键值对:\par coltext=red
。解析器被编码为,它会修剪空格在键周围,但\par
不是空格,因此至少你必须重写一些解析器以使其\par
也删除标记。
如果我们要删除\par
标记,那么我们可以直接采用第三种选择,即尽早删除它们:
\documentclass{article}
\usepackage{xparse}
\usepackage[most]{tcolorbox}
\begin{document}
\ExplSyntaxOn
\tl_new:N \LylTmpaTl
\cs_new:Npn \StripPar #1 #2
{
\tl_set:Nn #1 { #2 }
\tl_remove_all:Nn #1 { \par }
}
\ExplSyntaxOff
\NewDocumentCommand{\mycmd}{+O{}m}{% notice "+O{}"
\StripPar\LylTmpaTl{#1}% Removing ALL \par tokens
% Trick to expand \LylTmpaTl once
\begingroup\edef\x{\endgroup\noexpand
\begin{tcbitemize}[\unexpanded\expandafter{\LylTmpaTl}]}\x
#2
\end{tcbitemize}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\mycmd[
colback=yellow,
coltext=red
]
{\tcbitem some text}
\end{document}
此方法将删除全部从选项列表中删除 par 令牌。即使您不想删除,但这是您必须付出的代价。如果您恰好想要\par
某个密钥值中的令牌,则必须使用它\endgraf
。
答案2
Ti 的内部宏钾控制键值分配的 Z/PGF 不允许\par
token,而且一件好事™ 他们没有。
您的输入
colback=yellow,
coltext=red
完全等同于
colback=yellow,\par coltext=red
显然没有\par coltext
密钥。为了避免这个问题,宏被明确定义为不久,所以不允许\par
他们的论点。
回想一下,TeX 会自动将空白行转换为\par
标记在读入输入时。
事实上,你将可选参数标记为 long (用+
)并不能“删除”错误\par
标记,它只是允许在参数吸收时接受它。但随后该参数被传递给应该能够接受它的其他宏:好吧,它们不能接受。