Я хотел бы создать «список» имен файлов в произвольных точках документа и использовать этот список в приложении для загрузки этих файлов. Я понимаю, что в TeX есть обобщенная концепция списка для хранения элементов, подлежащих компоновке, но я ищу простой способ гибкого добавления элементов в список и последующего итерирования этих элементов для их интерпретации как «\input{item}».
Я немного погуглил, но ничего подходящего не нашлось. Так что, если на этот вопрос уже был дан ответ, я с радостью просто перейду по ссылке.
EDIT: просматривая ответы, я только что понял, что было бы полезно сохранять элементы списка уникальными, т. е. добавление одного и того же имени файла дважды не приведет к загрузке файла дважды. Возможно ли это (при разумном уровне простоты)?
решение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
list-utils.
Используйте, например, \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}
Поскольку ОП запросил уникальное добавление элементов списка — альтернативная версия
Используя команду-обертку для добавления элементов списка, можно проверить, сохранен ли уже «новый» элемент в списке, используя команду 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}