5

As stated, I wonder if there is any possibility to dynamically add items to a list and print it anywhere in the document, regardless of where the definitions are made.

I'm thinking something like this:

\documentclass[a4paper,12pt]{article}
\defineList{MyListName}
\begin{document}
\begin{itemize}
\printlist{MyListName}
\end{itemize}
Lorem ipsum dolor sit amet...
\addToList{MyListName}{\item First}
\addToList{MyListName}{\item Second}
\end{document}

and this would then result in something like this (in essence, the \printlist{MyListName} merely acts as a macro and is replaced by the content of the list:

Bullet list preceding the "Lorem ipsum" paragraph.

Of course, being able to iterate over the list items would be even more elegant, however it might introduce too much complexity.

  • Is it your intent that later defined \items are printed earlier in the document, at the instance of \printlist? Ala \tableofcontents? – Steven B. Segletes Apr 23 at 15:07
  • One can put pretty much anything into \@currentlabel and use \label and \ref to access it. ( Pgfplots puts the entire legend into a \ref.) All you need is a label naming convention. – John Kormylo Apr 23 at 15:21
  • An answer like this, tex.stackexchange.com/questions/202574/…, may be exactly what you are looking for. – Steven B. Segletes Apr 23 at 15:24
3

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}

enter image description here

  • This does pretty much everything that I was aiming for and the example works just fine. I'm having some troble to get it to work in my applied scenario but I figure that has nothing to do with your implementation. Thanks! – chrillof May 13 at 14:31
5

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}

enter image description here

3

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: enter image description here

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.

  • Being a programmer, I really like the thought of embedding Python into my document and I will keep it in mind for future uses. However, for the current problem, I find the embedded code a bit clunky for something that could be so much more simplistic and readable. – chrillof May 13 at 14:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.