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
2
  • why separator={ \par } ? Jul 9, 2015 at 12:49
  • @DavidCarlisle It can be anything. It is just used between items in the output. \par would list each item vertically. Jul 10, 2015 at 7:19

1 Answer 1

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}
14
  • 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. Jul 10, 2015 at 7:26
  • I see no extra { } next to \exp_not:N
    – egreg
    Jul 10, 2015 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 } Jul 10, 2015 at 8:28
  • 1
    @daleif Fixed (I changed a name in almost all places)
    – egreg
    Jul 10, 2015 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, 2015 at 11:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .