下面的代码定义了一个宏\addtothelist
,将水果的名称及其颜色(这只是一个例子)添加到\g_mylist_seq
。它还定义了一个宏\printmylist
,打印所有项目,例如:
- 苹果:红色
- 香蕉:黄色……
梅威瑟:
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\seq_new:N \g_mylist_seq
\newcommand{\addtothelist}[2]{
\cs_gset:cpn {mylist#1} {#2}
\seq_gput_right:Nn \g_mylist_seq {#1}
}
\NewDocumentCommand{\printmylist}{}
{
\seq_if_empty:NF \g_mylist_seq {
\begin{itemize}
\seq_map_inline:Nn \g_mylist_seq {
\item \use:c{mylist##1}:~##1
}
\end{itemize}
}
}
\ExplSyntaxOff
\begin{document}
\addtothelist{red}{apple}
\addtothelist{yellow}{banana}
\printmylist
\addtothelist{orange}{orange}
\end{document}
但是,orange
由于它是在被调用之后\printmylist
被调用的,因此它会忽略。我们可以使用aux
文件来解决这个问题吗?
答案1
.aux
在读取文件时构建序列,而不是在添加到列表时构建序列。
\documentclass{article}
\ExplSyntaxOn
\seq_new:N \g_mylist_seq
\NewDocumentCommand{\addtothelist}{mm}
{
\iow_shipout:cn { @auxout } { \ADDTOTHELIST { #1 } { #2 } }
}
\NewDocumentCommand{\ADDTOTHELIST}{mm}
{
\seq_gput_right:Nn \g_mylist_seq { {#1}{#2} }
}
\NewDocumentCommand{\printmylist}{}
{
\seq_if_empty:NF \g_mylist_seq
{
\begin{itemize}
\seq_map_inline:Nn \g_mylist_seq { \mylist_print_item:nn ##1 }
\end{itemize}
}
}
\cs_new_protected:Nn \mylist_print_item:nn
{
\item #1:~#2
}
\ExplSyntaxOff
\begin{document}
Some text
\addtothelist{red}{apple}
\addtothelist{yellow}{banana}
\printmylist
\addtothelist{orange}{orange}
\end{document}
第一次运行不会产生任何结果,但第二次运行将产生预期的结果。
答案2
在您的示例中,您甚至不需要将 seq 写入 -file aux
。您只需要将\addtothelist
命令写入aux
-file,即使不使用语法也可以完成此操作expl3
:
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\seq_new:N \g_mylist_seq
\newcommand{\addtothelist}[2]{
\cs_gset:cpn {mylist#1} {#2}
\seq_gput_right:Nn \g_mylist_seq {#1}
}
\NewDocumentCommand{\printmylist}{}
{
\seq_if_empty:NF \g_mylist_seq {
\begin{itemize}
\seq_map_inline:Nn \g_mylist_seq {
\item \use:c{mylist##1}:~##1
}
\end{itemize}
}
}
\ExplSyntaxOff
\makeatletter
\newcommand{\addtothelistindirect}[2]{%
\protected@write{\@auxout}{}{\protect\addtothelist{\detokenize{#1}}{\detokenize{#2}}}% write without expanding the arguments
}
% Alternative definitions:
% \newcommand{\addtothelistindirect}[2]{%
% \write\@auxout{\detokenize{\addtothelist{\detokenize{#1}}{\detokenize{#2}}}}% write without expanding the arguments
% }
% \newcommand{\addtothelistindirect}[2]{%
% \protected@write{\@auxout}{}{\protect\addtothelist{#1}{#2}}% write with expansion of the argument unless \protect is used
% }
\makeatother
\begin{document}
You need at least one page of output, otherwise the write to the aux will
never happen.
\addtothelistindirect{red}{apple}
\addtothelistindirect{yellow}{banana}
\printmylist
\addtothelistindirect{orange}{orange}
\end{document}
经过两次 LaTeX 运行后,结果显示:
如果您希望将序列写入aux
-file,可以使用 来完成\AtEndOfDocument
。但在这种情况下,您需要两个序列:一个序列将填充到文档中并写入 -file ,另一个序列将从文件aux
中读取并由 打印。否则,您将无法在不删除-file 的情况下删除条目。aux
\begin{document}
\printmylist
aux