4

Question

In languages such as Python, you can define a list like so:

example_list = ['apples']

I can append this list like so:

example_list.append('oranges')

I can print this list using

print example_list

which results in:

['apples', 'oranges']

How can I do something similar in LaTeX?


This question is part of a trail of questions. The goal mine was to use this list inside of a tikz node, but I removed that from this question in the interest of keeping it simple. So, for those interested, here is a quick list for reference:

For making a macro that can handle post-parsing-inputted list items, see:

For that same solution with tikz node support, see:


Situation

I have a list of inputted languages (see my other question). I would like to capture each language code into a list that I can print to paper as an inline list (i.e. da, de, en, etc.)

I would like to title page to look like this:

TITLE

da, de, en ... (or instead of ISO 639-1 codes, a list of full language names)


Appendage

There are a few good answers already. Although the original question was answered, my problem was not solved due to some other things I did not originally think about. :( Maybe somebody can help me.

I have a list of documents to input

Sudo-Code

List based on Werner's answer

\maketitle[\printlist{languagelist}]{User Manual}
\inputlanguagefile{En}{English}{./Languages/en/UserManual_en.tex}
\inputlanguagefile{Da}{Dansk}{./Languages/da/UserManual_da.tex}
\inputlanguagefile{De}{Deutsch}{./Languages/de/UserManual_de.tex}

I have a custom \maketitle command where the mandatory input {} is the title of the document and the optional [] is the subtitle (list of ISO 639-1 language codes) My problem is that the \maketitle command is called before the file inputs are called, which means that at the time the language list is called, it is still empty. I need to find a way to loop the input commands one by one to grab the two-letter language codes (#1) and append them to my list.

Then I want to actually add the inputs after the \maketitle as shown in the sudo-code. Obviously, the inputted documents should appear after the cover page, but I need to parse the language codes before the maketitle page is called.

  • Either you use the etoolbox \dolistloop etc. macros or the list features of expl3 – user31729 Mar 3 '15 at 6:19
  • Both pythontex and sagetex let you work with Python code in your LaTeX document. – DJP Mar 3 '15 at 6:40
4

etoolbox provides a host of list managing tools. Here is one way using \listadd{<stuff>} that seems to match your requirements:

enter image description here

\documentclass{article}
\usepackage{etoolbox}

% \printlist[<sep>]{<list macro>}
\newcommand{\printlist}[2][,]{{% Print list
  % http://tex.stackexchange.com/a/89187/5764
  \def\listsep{\def\listsep{#1}}% Delayed execution of list separator
  \renewcommand{\do}[1]{\listsep`##1'}%
  [\dolistloop\languagelist]
}}
\begin{document}

\listadd{\languagelist}{de}
\listadd{\languagelist}{da}
\listadd{\languagelist}{en}

\printlist{\languagelist}

\end{document}

There are other ways to add list elements (pre-expanded, globally, etc.). The only requirement is that you define the elements contained in \languagelist before printing it via \printlist. That is, it doesn't work like the \label-\ref system where you can refer to future \labels.

  • How can I get rid of the brackets? I see that I can remove the quotations here {\listsep '##1'} > {\listsep ##1} – Jonathan Komar Mar 3 '15 at 6:55
  • @macmadness86: I used [\dolistloop\languagelist], but you're probably interested in \dolistloop\languagelist (without the brackets [...]). – Werner Mar 3 '15 at 7:10
4

A rather flexible list management can be obtained with expl3 and xparse.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\listset}{O{default}m}
 {
  \seq_clear_new:c { l_macmadness_list_#1_seq }
  \seq_set_from_clist:cn { l_macmadness_list_#1_seq } { #2 }
 }
\NewDocumentCommand{\listappend}{O{default}m}
 {
  \clist_map_inline:nn { #2 }
   {
    \seq_put_right:cn { l_macmadness_list_#1_seq } { ##1 }
   }
 }
\NewDocumentCommand{\listprint}{O{}}
 {
  \group_begin:
  \keys_set:nn { macmadness/lists } { #1 }
  \macmadness_print_list:V \l__macmadness_list_name_tl
  \group_end:
 }

\seq_new:N \l_macmadness_list_default_seq
\tl_new:N \l__macmadness_list_lastitem_tl

\keys_define:nn { macmadness/lists }
 {
  name .tl_set:N       = \l__macmadness_list_name_tl,
  name .initial:n      = default,
  action .code:n       = \cs_set_eq:NN \__macmadness_action:n #1,
  action .initial:n    = \use:n,
  separator .tl_set:N  = \l__macmadness_list_separator_tl,
  separator .initial:n = { ,~ },
 }

\cs_new_protected:Npn \macmadness_print_list:n #1
 {
  \seq_if_empty:cTF { l_macmadness_list_#1_seq }
   {
    $\langle$ \textit{empty~list} $\rangle$
   }
   {
    % split off the last item
    \seq_pop_right:cN { l_macmadness_list_#1_seq } \l__macmadness_list_lastitem_tl
    % print the items followed by the separator
    \seq_map_inline:cn
     { l_macmadness_list_#1_seq }
     {
      \__macmadness_action:n { ##1 } % the item
      \l__macmadness_list_separator_tl % the separator
     }
    % print the last item
    \__macmadness_action:n { \l__macmadness_list_lastitem_tl }
   }
 }
\cs_generate_variant:Nn \macmadness_print_list:n { V }

\ExplSyntaxOff

\newcommand{\addquotes}[1]{`#1'}

\begin{document}

\listset{apples}
\listappend{oranges,strawberries}

\listprint

\listprint[
  separator={ $|$ },
  action=\addquotes
]

\listset[languages]{de,da,en}

\listprint[
  name=languages,
  action=\addquotes,
]

\listset[empty]{}

\listprint[name=empty]

\end{document}

Lists are identified by a name given as optional argument to \listset or \listappend. Without the optional argument the name is default.

The command \listprint receives an optional list of key-value pairs. Keys are

  • name for telling what list to print (name=default is implicit);
  • separator for telling how to separate items, default is “comma and space”;
  • action should receive as value a one parameter macro; in the example it's \addquotes, but it can be \textit or any predefined or personal macro; default is just printing the item.

enter image description here

You can use action for any action you like, for example for inputting files. I created UserManual_de.tex, UserManual_en.tex and UserManual_de.tex with some mock text in them (just “This is the German|English|Danish manual”) and defined a suitable \inputlanguagefile action.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\listset}{O{default}m}
 {
  \seq_clear_new:c { l_macmadness_list_#1_seq }
  \seq_set_from_clist:cn { l_macmadness_list_#1_seq } { #2 }
 }
\NewDocumentCommand{\listappend}{O{default}m}
 {
  \clist_map_inline:nn { #2 }
   {
    \seq_put_right:cn { l_macmadness_list_#1_seq } { ##1 }
   }
 }
\NewDocumentCommand{\listprint}{+O{}}
 {
  \group_begin:
  \keys_set:nn { macmadness/lists } { #1 }
  \macmadness_print_list:V \l__macmadness_list_name_tl
  \group_end:
 }

\seq_new:N \l_macmadness_list_default_seq
\tl_new:N \l__macmadness_list_lastitem_tl

\keys_define:nn { macmadness/lists }
 {
  name .tl_set:N       = \l__macmadness_list_name_tl,
  name .initial:n      = default,
  action .code:n       = \cs_set_eq:NN \__macmadness_action:n #1,
  action .initial:n    = \use:n,
  separator .tl_set:N  = \l__macmadness_list_separator_tl,
  separator .initial:n = { ,~ },
 }

\cs_new_protected:Npn \macmadness_print_list:n #1
 {
  \seq_if_empty:cTF { l_macmadness_list_#1_seq }
   {
    $\langle$ \textit{empty~list} $\rangle$
   }
   {
    % split off the last item
    \seq_pop_right:cN { l_macmadness_list_#1_seq } \l__macmadness_list_lastitem_tl
    % print the items followed by the separator
    \seq_map_inline:cn
     { l_macmadness_list_#1_seq }
     {
      \__macmadness_action:n { ##1 } % the item
      \l__macmadness_list_separator_tl % the separator
     }
    % print the last item
    \__macmadness_action:n { \l__macmadness_list_lastitem_tl }
   }
 }
\cs_generate_variant:Nn \macmadness_print_list:n { V }

\ExplSyntaxOff

\newcommand{\addquotes}[1]{`#1'}
\newcommand{\inputlanguagefile}[1]{%
  \input{UserManual_#1}%
}

\listset[languages]{de,da,en}


\begin{document}

\title{\listprint[name=languages]}
\author{macmadness86}

\maketitle

\section{Examples of list management}

\listset{apples}
\listappend{oranges,strawberries}

\listprint

\listprint[
  separator={ $|$ },
  action=\addquotes
]

\listprint[
  name=languages,
  action=\addquotes,
]

\listset[empty]{}

\listprint[name=empty]

\section{The manuals}

\listprint[
  name=languages,
  separator=\par\bigskip,
  action=\inputlanguagefile,
]

\end{document}

enter image description here

  • Good to have another solution. Maybe you can have a look at my appendage above. – Jonathan Komar Mar 3 '15 at 10:11
  • @macmadness86 Easy enough. ;-) – egreg Mar 3 '15 at 10:23
  • Well, not really. As it stands, you manually created the list named languages, right? I want it to be generated (the principle of only typing code once) from the \inputlanguagefile commands. This makes the code scalable with minimal chances for errors. I am pretty sure I need a loop for this. – Jonathan Komar Mar 3 '15 at 10:30
  • @macmadness86 I can't understand what you're saying: the list of languages is created in the preamble and you don't issue \inputlanguagefile explicitly. Please, don't ask XY questions. – egreg Mar 3 '15 at 10:34
  • @macmadness86 Your problem is completely different from what you stated in the question, that's what I'm trying to say. Please, ask a new question stating the real problem. It should be easy to solve by using the .aux file. – egreg Mar 3 '15 at 10:36
2

This uses the etoolbox package and adds some list elements in a row using \forcsvlist{\listadd{\myfruitlist}}{element1,element2,element3} etc.

Single elements can be added with \listadd{\myfruitlist}{element} or \listgadd, \listeadd, \listxadd, depending on the needs of expansion/global availability.

The output/processing of lists can be done with (for example) \forlistloop and an element processing macro, \printfruitlist. There are other routines, see the documentation of etoolbox on this.

\documentclass{article}


\usepackage{etoolbox}

\def\myfruitlist{}


\newcommand{\printfruitlist}[1]{%
\textbf{#1} 

}%

\begin{document}
\forcsvlist{\listadd{\myfruitlist}}{apples,oranges,strawberries}

\listadd{\myfruitlist}{salad}
\listadd{\myfruitlist}{bananas}

Find the error in this list:

\forlistloop{\printfruitlist}{\myfruitlist}


\end{document}

enter image description here

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.