7

Would I need to use a token list?

For the purpose of removing confusion, let there be two delimiters:

  1. input delimiter (what LaTeX reads as input)
  2. output delimiter (what is seen on paper)

I would like to loop over and grab items from a file containing a list of files:

apples.tex
bananas.tex
strawberries.tex

Example

I have tried using LaTeX3 code based on How can I create a list as a variable that can be appended and eventually typeset?, but it is nerve-wrecking.

\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 } % input delimiter? (due to clist? "comma list"?)
 }
\NewDocumentCommand{\listappend}{O{default}m}
 {
  \clist_map_inline:nn { #2 }% input delimiter? (due to clist? "comma list"?)
   {
    \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, % output delimiter
  separator .initial:n = { ,~ }, % output delimiter
 }

\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 delimiter
    \seq_map_inline:cn
    \seq_map_inline:cn
     { l_macmadness_list_#1_seq }
     {
      \__macmadness_action:n { ##1 } % the item
      \l__macmadness_list_separator_tl % output delimiter
     }
    % print the last item
    \__macmadness_action:n { \l__macmadness_list_lastitem_tl }
   }
 }
\cs_generate_variant:Nn \macmadness_print_list:n { V }

\ExplSyntaxOff

\begin{document}
\listprint[%
    separator={ , } % output delimiter
]%
\end{document}
2
  • 2
    But the lines of fruit in the first box are not delimited by \par. \par is a blank line. – daleif Jul 8 '15 at 7:59
  • I would use textmerg for merging in the list of files. But I have no idea how people answering know the content of those files to answer the output bit of the question. l3 is great but it just seems like overkill for the first merge, at least. (Though maybe textmerg does extravagant non-l3 things...) – cfr Jul 22 '15 at 22:09
7

If your input is in a file, you need to grab the file:

\begin{filecontents*}{\jobname-list.tex}
apples.tex
bananas.tex
strawberries.tex
\end{filecontents*}

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\listset}{O{default}m}
 {
  \macmadness_listset:nn { #1 } { #2 }
 }

\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_separator_tl

\cs_new_protected:Nn \macmadness_listset:nn
 {
  \seq_clear_new:c { l_macmadness_list_#1_seq }
  \tl_set_from_file:Nnn \l_macmadness_file_contents_tl {} {#2}
  \seq_set_split:cnV { l_macmadness_list_#1_seq } { ~ } \l_macmadness_file_contents_tl
  \seq_pop_right:cN { l_macmadness_list_#1_seq } \l_tmpa_tl
 }
\cs_generate_variant:Nn \seq_set_split:Nnn {cnV}

\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, % output delimiter
  separator .initial:n = { ,~ }, % output delimiter
 }

\cs_new_protected:Npn \macmadness_print_list:n #1
 {
  \seq_if_empty:cTF { l_macmadness_list_#1_seq }
   {
    $\langle$ \textit{empty~list} $\rangle$
   }
   {
    \seq_clear:N \l_macmadness_output_seq
    \seq_map_inline:cn { l_macmadness_list_#1_seq }
     {
      \seq_put_right:Nn \l_macmadness_output_seq { \__macmadness_action:n { ##1 } }
     }
    \seq_use:NV \l_macmadness_output_seq \l__macmadness_list_separator_tl
   }
 }
\cs_generate_variant:Nn \macmadness_print_list:n { V }
\cs_generate_variant:Nn \seq_use:Nn { NV }

\ExplSyntaxOff


\begin{document}

\listset{\jobname-list}

\listprint

\listprint[separator={; }]

\end{document}

enter image description here

9
  • I tried \listset{\input{Documents.txt}}, but it did not work. What am I doing wrong here? Documents.txt exists in the same folder as the tex file. – Jonathan Komar Jul 8 '15 at 8:40
  • @macmadness86 \listset{Documents.txt}. If you make your question more precise, I may add different ways for setting the list: from a file or from direct input. – egreg Jul 8 '15 at 9:08
  • 1
    I've seen you lately not declaring certain variables, in this case \l__macmadness_list_name_tl, you just use .tl_set:N and .initial:n it. Why not declaring it with \tl_new:N before? Isn't that the good way? – Manuel Jul 8 '15 at 9:41
  • 1
    @Manuel The variables used for .tl_set:N or any other .<type>_set:N declaration are automatically initialized. From interface3.pdf, about .tl_set:N: “If the variable does not exist, it will be created globally at the point that the key is set up.” – egreg Jul 8 '15 at 9:43
  • 1
    @Manuel For stuff working with l3keys we (I) made a decision that the keys themselves were declarative enough to allow 'short-cutting' the need to apply \<var>_new:N when coupled with .<var>_set:N. I hope this is a reasonable balance. – Joseph Wright Jul 8 '15 at 10:48

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.