使用收据“LaTeX3:无法将空格分隔列表转换为 clist“我根据自己的需要详细阐述了以下代码:
\documentclass{book}
...
\usepackage{expl3}
\begin{document}
\newcommand{\PrintAnswer}[1]{%
\InputIfFileExists{#1}{\refstepcounter{subsection}}{\typeout{*** #1 not found ***}}}
\ExplSyntaxOn
\cs_new:Nn\PrintAnswerList:n{
\clist_set:Nx\l_csv_clist{#1}
\clist_map_inline:Nn\l_csv_clist{
\typeout{**** Printing ##1.ans}
\ExplSyntaxOff
\PrintAnswer{##1.ans}
\ExplSyntaxOn
}
}
\PrintAnswerList:n{\inputfiles}
\ExplSyntaxOff
\end{document}
它用于对教科书进行条件编译,其中每一章(例如 01.tex、02.tex)将问题的答案写入以章节源文件的名称命名的文件中(例如 01.ans、02.ans 等)。在书的末尾,这些文件由宏读入\PrintAnswer
。通常,我仅编译几个章节,使用以下技巧将所需的章节保留在\inputfiles
宏中:
\typein[\inputfiles]{^^JEnter filename(s) for \protect\includeonly:}
所有这些都运行良好,但我之前被迫关闭了实验性语法,\PrintAnswer{##1.ans}
因为否则答案文件无法正确处理(特别是,LaTeX 抱怨希腊字母的命令未定义,连字被破坏)。因此我的问题是如何使用用户级 LaTeX3 命令重写上述代码? 我\SplitList
在包中找到了命令xparse
。它能帮忙吗?
答案1
在 LaTeX3 中,获取用户级函数的首选方法是xparse
及其\NewDocumentCommand
函数。
如果列表不是逗号分隔的列表,那么你必须执行以下操作
\ExplSyntaxOn
\NewDocumentCommand{\PrintAnswerList}{>{\SplitList;}m}
{ \tl_map_inline:nn {#1} { \PrintAnswer {##1.ans} } }
\ExplSyntaxOff
\PrintAnswerList { file01 ; file 02 ; file03 }
然后\PrintAnswer
将在 expl 语法范围之外执行。
在这里,你的生活既稍微轻松一些,因为你有一个逗号分隔的列表,又稍微困难一些,因为它不是直接给出的,而是隐藏在宏中给出的。\inputfiles
在下面的代码中,我使用了\clist_map_inline:on
,它在执行每个项目的第二个参数之前将其 clist 参数展开一次。由于这个特定的变体在内核中不可用,我们需要提供它,
\clist_generate_variant:Nn \clist_map_inline:nn { o }
总而言之,你可以这样做(我\PrintAnswer
也改变了)
\documentclass{book}
...
\usepackage{expl3,xparse}
\ExplSyntaxOn
\NewDocumentCommand { \PrintAnswer } { m }
{
\file_if_exist:nTF {#1}
{
\iow_term:n {****~Printing~#1}
\file_input:n {#1}
\refstepcounter {subsection}
}
{ \iow_term:n {****~#1~not~found~****} }
}
\cs_generate_variant:Nn \clist_map_inline:nn {o}
\NewDocumentCommand { \PrintAnswerList } { m }
{ \clist_map_inline:on {#1} { \PrintAnswer {##1.ans} } }
\ExplSyntaxOff
\begin{document}
\PrintAnswerList{\inputfiles}
\end{document}