4

I need to produce a variable-sized string consisting of even number of Latin letters, each pair being of the format a\textrightarrow A;. Each pair separated from the other pairs by some empty space (here 1cm for example). For this I define a command \midarrow and use \regex_replace of expl3 to modify the argument of \midarrow.

I want \midarrow to convert

  1. "a,A;b,B;c,C" to "(a->A); (b->B); (c->C)"

  2. "a,A;b,B;c,C;d,D" to "(a->A); (b->B); (c->C); (d->D)"

  3. "->" above should be actual arrows produced by \textrightarrow

The MWE is as follows:

\documentclass[a4paper,11pt]{article}

\usepackage{expl3,xparse}
\usepackage{textcomp}

\ExplSyntaxOn
\NewDocumentCommand{\midarrow}{m}
{
    \tl_set:Nn \l_tmpa_tl { (#1) }
    \regex_replace_all:nnN { , } { \textrightarrow } \l_tmpa_tl
    \regex_replace_all:nnN { ; } { );\hspace{1cm}( } \l_tmpa_tl
    \tl_use:N \l_tmpa_tl
}
\ExplSyntaxOff

\begin{document}
    \midarrow{a,A;b,B;c,C}
\end{document}

However I get garbage as result. How do I make sure that the result of \regex_replace_all should be compiled by pdfLaTeX and produce the desired output?

PS: I am not proficient in latex3. I have just reused and modified code I found on this site to suit my purposes.

  • 1
    You could simply use \tl_replace_all:Nnn \l_tmpa_tl { , } { \textrightarrow } and \tl_replace_all:Nnn \l_tmpa_tl { ; } { );\hspace{1cm}( } instead of regular expressions. – Bruno Le Floch Mar 28 at 16:19
6

You should follow special rules in the replacement text:

  • Use \c{cmd} to represent control sequence \cmd.
  • Use \cB\{ and \cE\} to represent begin and end group brace, respectively.
  • To ensure the category codes, escape every printable character other than a-zA-Z0-9. For example, use \( to represent character (, and use (...) to represent a capturing group. (Thanks for @frougon's comment.)

Therefore your example can be modified to be

\documentclass[a4paper,11pt]{article}

\usepackage{expl3,xparse}
\usepackage{textcomp}

\ExplSyntaxOn
\NewDocumentCommand{\midarrow}{m}
{
    \tl_set:Nn \l_tmpa_tl { (#1) }
    \regex_replace_all:nnN { \, } { \c{textrightarrow} } \l_tmpa_tl
    \regex_replace_all:nnN { \; } { \)\; \c{hspace}\cB\{ 1cm \cE\} \( } \l_tmpa_tl
    \tl_use:N \l_tmpa_tl
}
\ExplSyntaxOff

\begin{document}
    \midarrow{a,A;b,B;c,C}
\end{document}

Use the document interface3.pdf, part XXVII as a thorough introduction to l3regex library.

| improve this answer | |
  • Thanks! That works very well. However I am curious as to what should I do if I wanted to use $\rightarrow$ instead of \textrightarrow? – magguu Mar 28 at 7:38
  • 2
    You can use \cM$ \c{rightarrow} \cM$. The parentheses and semicolon (;) should be preceded by a \ because the manual says (p. 223 here) “non-alphanumeric printable ascii characters can (and should) always be escaped: many of them have special meanings (e.g., use \(, \), \?, \.)”, where alphanumeric has been defined as A–Z, a–z, 0–9. You should read the l3regex chapter in the link muzimuzhi Z gave you. – frougon Mar 28 at 8:49
  • @frougon Thanks for pointing out that. Answer updated. – muzimuzhi Z Mar 28 at 20:05
8

I wouldn't use \regex_replace:nnN for this job.

My suggestion is to split the input at the semicolons; then apply to each item a command for the arrow and finally use the sequence with the desired space between items.

The arrow making function uses the fact that you have two items separated by a comma, so it's good input for a clist.

\documentclass[a4paper,11pt]{article}

\usepackage{expl3,xparse}
\usepackage{textcomp}

\ExplSyntaxOn
\NewDocumentCommand{\midarrow}{m}
 {
  \seq_set_split:Nnn \l_magguu_arrows_in_seq { ; } { #1 }
  \seq_set_map:NNn \l_magguu_arrows_out_seq \l_magguu_arrows_in_seq
   { \magguu_arrows_make:n { ##1 } }
  \seq_use:Nn \l_magguu_arrows_out_seq { \hspace{1cm} }
}
\cs_new_protected:Nn \magguu_arrows_make:n
 {
  \clist_item:nn { #1 } { 1 }
  \textrightarrow
  \clist_item:nn { #1 } { 2 }
 }
\ExplSyntaxOff

\begin{document}

\midarrow{a,A;b,B;c,C}

\end{document}

enter image description here

It is immaterial if you input \midarrow{a,A;b,B;c,C} or

\midarrow{
  a, A;
  b, B;
  c, C
}
| improve this answer | |

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.