1

I am trying to apply a regular expression to a string item from a sequence in LaTeX3.

Example

Compiles with error, but only by pressing return many times.

! Missing control sequence inserted.
<inserted text>
                \inaccessible
l.64 \listprint[separator={ \par }]

Documents.txt

Input file Documents.txt in same folder as source tex file:

test1_de.tex
test1_en.tex
test2_de.tex
test2_en.tex

Source TeX File

\documentclass{article}
\usepackage{fontspec}
\usepackage{xparse}
\usepackage{expl3}
\usepackage{l3regex}

\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 % Command called by \listset (see above)
 {
  \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 }
     {
     \tl_set:Nn \l_filename_tl { ##1 }
     \regex_replace_all:nnN {(.*)[\c{_}|.] } { \1 } \l_filename_tl
     \seq_put_right:Nn \l_macmadness_output_seq { \__macmadness_action:n { ../\regex_replace_all:nnN {(.*)[\c{_}|.] } { \1 } ##1 /##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{./Documents.txt}
\listprint[separator={ \par }]
\end{document}

The special line with the regex command is:

\seq_put_right:Nn \l_macmadness_output_seq { \__macmadness_action:n { ../\regex_replace_all:nnN {(.*)[\c{_}|.] } { \1 } ##1 /##1 }

I think the problem is that the \regex_replace does not know to stop after the first ##1 and continues gobbling up tokens. If that is the problem, how could I make it stop reading at that point.

(just FYI, the regular expression is messed up and does not result in what I want anyway.)

I would like the output of that to be:

../test1/test1_de.tex
../test1/test1_en.tex
../test2/test2_de.tex
../test2/test2_en.tex
  • why separator={ \par } ? – David Carlisle Jul 9 '15 at 12:49
  • @DavidCarlisle It can be anything. It is just used between items in the output. \par would list each item vertically. – Jonathan Komar Jul 10 '15 at 7:19
2

It's unclear why you're looking for \_ when the input file is not expected to have such token.

\tl_new:N \l_macmadness_filename_tl 

\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 }
     {
      \tl_set:Nn \l_macmadness_filename_tl { ##1 }
      \regex_replace_all:nnN {([^_.]*).*} { \1 } \l_macmadness_filename_tl
      \seq_put_right:Nx \l_macmadness_output_seq
       {
        \exp_not:N \__macmadness_action:n { ../ \l_macmadness_filename_tl / \tl_to_str:n { ##1 } }
       }
      }
    \seq_use:NV \l_macmadness_output_seq \l__macmadness_list_separator_tl
   }
 }
\cs_generate_variant:Nn \macmadness_print_list:n { V }

The replacement has already been done by \regex_replace:nnN before; I changed the search regex to match all characters until the first underscore or period.

enter image description here

Full code:

\documentclass{article}
\usepackage{fontspec}
\usepackage{xparse}
\usepackage{expl3}
\usepackage{l3regex}

\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 % Command called by \listset (see above)
 {
  \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
 }

\tl_new:N \l_macmadness_filename_tl

\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 }
     {
      \tl_set:Nn \l_macmadness_filename_tl { ##1 }
      \regex_replace_all:nnN {([^_.]*).*} { \1 } \l_macmadness_filename_tl
      \seq_put_right:Nx \l_macmadness_output_seq
       {
        \exp_not:N \__macmadness_action:n { ../ \l_macmadness_filename_tl / \tl_to_str: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{./Documents.txt}
\listprint[separator={ \par }]
\end{document}
  • I've copied your code into mine and it does not work correctly. Are you sure that you did not change anything else? Would you be willing to explain the extra { } where \exp_not: is located, and \exp_not: itself? That seems to be an important step I was missing. Also, the reason why I was looking for \_ is because originally, the code was used outside of a LaTeX3 environment. I had to escape the underscore there. Thanks for that correction. – Jonathan Komar Jul 10 '15 at 7:26
  • I see no extra { } next to \exp_not:N – egreg Jul 10 '15 at 8:24
  • Wherein \exp_not:N is located I should have written. There are extra brackets around \exp_not:N that are not in my example. The pair just above { \seq_use:NV \l_macmadness_output_seq \l__macmadness_list_separator_tl } – Jonathan Komar Jul 10 '15 at 8:28
  • 1
    @daleif Fixed (I changed a name in almost all places) – egreg Jul 10 '15 at 11:16
  • 1
    @daleif It doesn't disappear, as it produces a small dot; with pdflatex you have to use T1 encoding. – egreg Jul 10 '15 at 11:43

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.