GeneralLists and loops

LaTeX specific issues not fitting into one of the other forums of this category.
Post Reply
oyvist
Posts: 4
Joined: Tue Apr 14, 2009 11:42 am

Lists and loops

Post by oyvist »

Hi. I have been struggling with macro programming in (La)TeX. I'm writing a class file and want to provide a command for the user that can be issued repeatedly, thereby building a list which can then be processed later.

More specifically:
I want to define a command \revision that builds a revision history of a document.
The original author just adds this to the preamble of his document

Code: Select all

\revision{2008--01--01}{Original AuthorName}{Created document!}
When someone later changes the document (s)he just adds another command below the first instance:

Code: Select all

\revision{2008--01--01}{Original AuthorName}{Created document!}
\revision{2008--02--02}{Second AuthorName}{Added some stuff. Much better now.}
I'd like to collect the dates, author names and comments in three lists, and then output it in a revision history table.

Surprise, surprise, I can't hack this. I tried some stuff like this for building my lists:

Code: Select all

\newcommand*{\auth}{}
\newcommand*{\comment}{}
\newcommand*{\revdate}{}
\newcommand*{\revision}[3]{%
	\edef\auth{\revdate{},#1}
	\edef\auth{\auth{},#2}
	\edef\comment{\comment{},#3}
}
Unfortunately, I now get a comma at the beginning of each list, and if there's a comma in the input arguments, that throws everything off. Enclosing the input
arguments in '{}' doesn't help. I have looked into Philipp Lehman's etoolbox, which
looked very promising, but the lack of examples in the documentation made it fly far above my head.

My actual question has two parts:
1) How do I build lists in (La)TeX, and can I use other delimiters than comma?
2) What sort of looping mechanism should I use to output my lists into a table?

I would also very much appreciate it if someone could point me towards some sort of
tutorial/documentation on macro programming. I am finding it extremely difficult to
get into this subject, and it seems like there is a body of 'secret' macros/commands floating around, but very little documentation of them. (For example, it seems that the Latex Companion contains virtually _nothing_ on macro programming.) Specifically, I'd like to know more about 'list macros' and 'list processing' which I see mentioned here and there, but always in a very cryptic fashion.

Recommended reading 2024:

LaTeXguide.org • LaTeX-Cookbook.net • TikZ.org
LaTeX Beginner's Guide LaTeX Cookbook LaTeX TikZ graphics TikZによるLaTeXグラフィックス
josephwright
Site Moderator
Posts: 814
Joined: Tue Jul 01, 2008 2:19 pm

Lists and loops

Post by josephwright »

This type of low-level programming is, as you say, rather poorly documented. A lot of things here are currently done using plain TeX, for which The TeXBook is the main reference. The LaTeX team know this is not good: one of the ideas for LaTeX3 is to include some proper looping structures including proper documentation. However, that does not help you in the here and now.

If you want to loop over comma-lists, LaTeX provides the \@for macro. This works by repeatedly assigning list items to a temporary variable:

Code: Select all

\@for\TempVar:=\CommaList\do{%
  %Do stuff with \TempVar
}
Notice the slightly odd syntax for this macro: you do need the ":=". The method for implementing these loops is rather complex, as you will see if you look at latex.ltx. Defining loops to use a different delimiter is probably easiest done by copy-pasting the latex.ltx code (using new names for the macros) and replacing the "," in the definitions with whatever you want as a delimiter. Unfortunately, this is not easy code to read.

You can avoid the extra comma by testing for an empty list before adding to it:

Code: Select all

\newcommand*{\CommaList}{}
\newcommand*{\AddToCommaList}[1]{%
  \ifx\CommaList\empty
    \def\CommaList{#1}%
  \else
    \expandafter\def\expandafter\CommaList\expandafter
      {\CommaList,#1}%
  \fi
}
I've avoid \edef here a some things do not like it, and the \expandafter run here will expand \CommaList exactly once, which is what we really need to do in this context.

Having said all of that, I would probably not code much myself here. The datatool package covers much of this type of thing in an easy-to-use way. A quick version using datatool:

Code: Select all

\documentclass{article}
\usepackage{datatool}
\DTLnewdb{revisions}
\newcommand*{\revision}[3]{%
  \DTLnewrow{revisions}%
  \DTLnewdbentry{revisions}{date}{#1}%
  \DTLnewdbentry{revisions}{author}{#2}%
  \DTLnewdbentry{revisions}{comment}{#3}%
}
\begin{document}
\revision{2008--01--01}{Original AuthorName}{Created document!}
\revision{2008--02--02}{Second AuthorName}{Added some stuff. Much better now.}
\DTLdisplaydb{revisions}
\end{document}
Joseph Wright
oyvist
Posts: 4
Joined: Tue Apr 14, 2009 11:42 am

Re: Lists and loops

Post by oyvist »

Thank you very much for a helpful and illuminating answer. I have not come across the datatool package before, and it, together with your example, seem to provide a very good solution to my question.

The TeXbook does not seem to be available at my local univ library. Do you know of any online resources that does a good job of explaining macros?

If only I had come to this forum sooner.. I have wasted a lot of time on this.
josephwright
Site Moderator
Posts: 814
Joined: Tue Jul 01, 2008 2:19 pm

Lists and loops

Post by josephwright »

You can find TeX by Topic on CTAN: it is a very good reference work on TeX. You can also look at the source for The TeXBook on CTAN: note that you are not allowed to typeset it!
Joseph Wright
ptoche
Posts: 49
Joined: Thu Apr 12, 2007 10:41 am

Re: Lists and loops

Post by ptoche »

Hi Joseph, I have posted a question that may require coding a loop, if you're reading this I wonder if you would care to comment, since you clearly know a fair bit about LaTeX loops. I figured you'd be more likely to read this post than my other post. That's all, I don't want to hijack this thread any more than this. I do hope my intrusion does not violate the community's code of conduct.

My question is posted there: http://www.latex-community.org/forum/vi ... 18&p=20055
Post Reply