Is there a possibility to generate a list dynamically in Latex?
You can use the .aux
file.
With \defineList
we initialize a sequence variable; each \addToList
command writes in the .aux
file the corresponding entry as argument to \chrillofaddtolist
.
When the .aux
file is read in at begin document, the sequence is populated with the items gathered in the previous run so it will be available as soon as the document starts.
The command \chrillofaddtolist
is made a no-op at end document, when the .aux
file is read back in, but we need no action.
Finally, \printList
just delivers the sequence.
As a technical workaround, I added a litemize
environment, so no error is raised when the sequence is still empty.
\documentclass[a4paper,12pt]{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\defineList}{m}
{
\seq_new:c { g_chrillof_list_#1_seq }
}
\NewDocumentCommand{\addToList}{mm}
{
\iow_shipout:cn { @auxout } { \chrillofaddtolist { #1 } { #2 } }
}
\NewDocumentCommand{\chrillofaddtolist}{mm}
{
\seq_gput_right:cn { g_chrillof_list_#1_seq } { #2 }
}
\NewDocumentCommand{\printList}{m}
{
\seq_use:cn { g_chrillof_list_#1_seq } { }
}
\AtEndDocument{\cs_set_eq:NN \chrillofaddtolist \use_none:nn }
\ExplSyntaxOff
\makeatletter
\newenvironment{litemize}
{\let\@noitemerr\relax\itemize}
{\enditemize}
\makeatother
\defineList{MyListName}
\begin{document}
\begin{litemize}
\printList{MyListName}
\end{litemize}
Lorem ipsum dolor sit amet...
\addToList{MyListName}{\item First}
\addToList{MyListName}{\item Second}
\end{document}
The sagetex
package, documentation here, gives you access to the Python programming language. This is one way to keep track of the list and print using a loop.
\documentclass{article}
\usepackage{sagetex}
\begin{document}
\begin{sagesilent}
MyList = ["spring","summer"]
output = r"\begin{itemize}"
for i in range(0,len(MyList)):
output += r"\item %s"%(MyList[i])
output += r"\end{itemize}"
\end{sagesilent}
\sagestr{output}
Lorem ipsum dolor sit amet...
\begin{sagesilent}
MyList.insert(0,"winter")
MyList.append("fall")
output = r"\begin{itemize}"
for i in range(0,len(MyList)):
output += r"\item %s"%(MyList[i])
output += r"\end{itemize}"
\end{sagesilent}
\sagestr{output}
\end{document}
The result is shown below:
The "behind the scenes" work is done in sagesilent
environment. The original list is created to contain "spring" and "summer". A for loop creates a string that will put the list into the itemize environment. To insert it into the document, use sagestr
, the SAGE string environment. If we want to add "winter" to be first in the list and "fall" to be last, the command MyList.insert(0,"winter") puts "winter" in the first position (which in Python is the zeroth position). The command MyList.append("fall") puts "fall" at the end of the list, however long it is. The for loop prints out over the longer list since len(MyList) is the length of the list.
The extra block of code each time is a bit clunky but it is easy to read and modify. You also get the benefit of being able to insert into any part of the list. The sagetex
package relies on the computer algebra system SAGE, which is not part of the LaTeX package. It either needs to be downloaded to your computer or you can open a free Cocalc account and work from the cloud.
Requires two passes. Based on my answer at Extracting the structure of a LaTex document, including comments, but adapting the syntax to meet the OP's needs.
Multiple lists can be simultaneously active. Here, in the MWE, I build "xyz" and "pdq" lists.
\documentclass{article}
\let\svaddtocontents\addtocontents
\makeatletter
\newcommand\defineList[1]{%
\expandafter\def\csname add#1line\endcsname##1##2##3{\addtocontents {##1}{%
\protect \csname #1line\endcsname {##2}{##3}}}
\expandafter\def\csname write#1\endcsname{%
\renewcommand\addtocontents[2]{\relax}%
\setcounter{section}{0}\noindent%
\expandafter\def\csname #1line\endcsname####1####2{\expandafter\csname####1\endcsname{####2}}%
\@starttoc{#1}%
\setcounter{section}{0}%
\let\addtocontents\svaddtocontents%
}%
\csname add#1line\endcsname{#1}{begin}{itemize}%
\AtEndDocument{\csname add#1line\endcsname{#1}{end}{itemize}}
}
\newcommand\addToList[2]{\csname add#1line\endcsname{#1}{item}{#2}}
\newcommand\printList[1]{\csname write#1\endcsname}
\makeatother
\begin{document}
%\tableofcontents% CAN UNCOMMMENT TO SEE THAT toc WORKS FINE
\defineList{xyz}
\defineList{pdq}
\section{Introduction}
\addToList{xyz}{First item on my list.}
Text related to why tracking balls is important, blah, blah, blah.
Blah, blah, blah.
\addToList{pdq}{First pdq item}
Here is my XYZ list:
\printList{xyz}
\section{Next Section}
\addToList{xyz}{Second item on list}
Text relating the challenges, blah, blah, blah.
More blah, blah, blah.
\addToList{pdq}{Next pdq item}
\addToList{xyz}{Third item on list.}
Here is my PDQ list:
\printList{pdq}
Text relating the existing work on tracking balls, blah, blah, blah.
Blah, blah, blah.
\end{document}