我想在文档的任意位置创建一个文件名“列表”,并使用附录中的列表来加载这些文件。据我所知,TeX 中有一个用于保存要布局的项目的列表的广义概念,但我正在寻找一种简单的方法,可以灵活地添加到项目列表中,然后在这些项目上进行迭代以将它们解释为“\input{item}”。
我用 Google 搜索了一下,但没有找到任何匹配的内容。所以,如果这个问题已经得到解答,我很乐意直接点击链接。
编辑:看了答案后我才意识到保持列表项的唯一性可能会很有用,即两次添加相同的文件名不会加载文件两次。这可能吗(在合理的简单程度下)?
答案1
LaTeX 内核中有一个标准列表管理,基于\@for
:
\makeatletter
\newcommand{\addtofilelist}[1]{%
\ifx\files@to@input@later\@empty
\g@addto@macro\files@to@input@later{#1}%
\else
\g@addto@macro\files@to@input@later{,#1}%
\fi
}
\let\files@to@input@later\@empty % initialize
\newcommand{\inputthefiles}{%
\@for\next:=\files@to@input@later\do{\input{\next}}%
}
\makeatother
所以你说
\addtofilelist{foo.tex}
\addtofilelist{bar.tex}
当你想要的时候,最后你可以发出
\inputthefiles
将按要求采取行动。
基于的技术expl3
:
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\addtofilelist}{m}
{
\seq_gput_right:Nn \g_regnirpsj_file_list_seq { #1 }
}
\NewDocumentCommand{\inputthefiles}{}
{
\seq_map_inline:Nn \g_regnirpsj_file_list_seq { \input{ ##1 } }
}
\seq_new:N \g_regnirpsj_file_list_seq
\ExplSyntaxOff
用法相同。如果您希望能够使用单个\addtofilelist
命令添加文件列表,请将第一个定义更改为
\NewDocumentCommand{\addtofilelist}{m}
{
\clist_map_inline:nn { #1 }
{
\seq_gput_right:Nn \g_regnirpsj_file_list_seq { ##1 }
}
}
你可以说,在任何时候
\addtofilelist{foo.tex, bar.tex}
文件名数量任意,以逗号分隔。对于基于内核的解决方案,这也是可能的,但请注意,在这种情况下不允许使用空格,而在xparse
基于内核的解决方案中,逗号周围的空格会被忽略。
答案2
etoolbox
例如,可以使用列表实用程序来完成此操作。
例如,用作\listgadd{\myfilelist}{}
列表的初始化器。
随后,在“任何”位置使用\listgadd{\myfilelist}{file1}
或处理一组文件\forcsvlist{\listgadd{\myfilelist}}{file2, file3,file4}
。
要输入附录中的所有文件,最好有一个包装命令,它在输入每个文件之前和之后做一些工作,但只要说
\forlistloop{\input}{\myfilelist}
,
迭代整个列表。
所有列表迭代器宏的第一个参数都来自etoolbox
一个元素例程,它将当前列表元素作为最后一个参数。
\documentclass[12pt]{article}
\usepackage{etoolbox}%
\usepackage{blindtext}%
\listgadd{\myfilelist}{}%
\newcommand{\inputallfiles}[1]{%
\input{#1}%
}%
\begin{document}
\blindtext
\listgadd{\myfilelist}{file1}%
\blindtext[10]
\forcsvlist{\listgadd{\myfilelist}}{file2,file3,file1}%
\appendix%
\section{First}
\forlistloop{\inputallfiles}{\myfilelist}%
\end{document}
文件1.tex
\textit{Hello World}
文件2.tex
\textbf{Hello World}
文件3.tex
\textsc{Hello World}
由于 OP 要求添加独特的列表元素——替代版本
使用包装器命令添加列表元素,可以使用ifinlist
etoolbox 中的命令检查列表中是否已存储“新”元素。如果此测试结果为真false
,则可以添加该元素,否则,将忽略该元素。
我添加了一个command
\addtofilelist
适用于单个元素或逗号分隔的元素列表的功能。
在\inputallfiles
宏中我添加了测试\InputIfFileExists...
以提高安全性。
\documentclass[12pt]{article}
\usepackage{etoolbox}%
\usepackage{blindtext}%
\listgadd{\myfilelist}{}%
\newcommand{\uniqueaddtolist}[2]{%
\ifdef{#1}{%
\ifinlist{#2}{#1}{%
% Do nothing
}{%
\listgadd{#1}{#2}%
}
}{% No list so far, so just add one!
\listgadd{#1}{#2}%
}%
}%
\newcommand{\uniqueaddtofilelist}[1]{%
\uniqueaddtolist{\myfilelist}{#1}%
}%
\newcommand{\addtofilelist}[1]{%
\forcsvlist{\uniqueaddtofilelist}{#1}%
}%
\newcommand{\inputallfiles}[1]{%
\InputIfFileExists{#1}{}{}%
}%
\begin{document}
\blindtext
\addtofilelist{file1}%
\blindtext[10]
\addtofilelist{file2,file3,file1}%
\appendix%
\section{First}
\forlistloop{\inputallfiles}{\myfilelist}%
\end{document}