4

Problem

I would like to use an expl3 function inside a \label{...}.

%!TEX program=xelatex
\documentclass{article}

\usepackage{l3regex}

\ExplSyntaxOn
    \tl_new:N \l_slugify_tl
    \cs_new:Npn \slugify #1 {
        \tl_set:Nf \l_slugify_tl { \tl_lower_case:n { #1 } } %lower case
        \regex_replace_all:nnN { [^a-z]+ }{ - }\l_slugify_tl % remove non-letters
        \regex_replace_all:nnN { (^-|-$$$$) }{ } \l_slugify_tl % clean up leading/trailing dashes
        \tl_use:N \l_slugify_tl
    }
\ExplSyntaxOff


\begin{document}

\subsection{The Explanation}
    \label{wiki:\slugify{The Explanation}}

\end{document}

When typesetting the document, I get a

) (./test-regex-slug.aux
! Undefined control sequence.
<argument> r@wiki:\tl 
                      _set:Nf {the explanation}\regex _replace_all:nnN {[^a-...
l.3 ...x_replace_all:nnN {(^-|-$$$$)}{}}{{0.1}{1}}

Apparently, the contents of \slugify are not expanded and the expl3-code is written directly to the aux file. How can I prevent that and make my code work?

Background

I'd like to simplify the usage of cross-references inside my (huge) document. I would type something like

... e.g. using a \linkR{Time of Flight} detector.
That \linkR{TOF} would ...

% ...

\section{\anchorR{Time of Flight} Detector (\aliasR{TOF})}
% ...

instead of

...e.g. using a \hyperref[time-of-flight]{Time of Flight} detector.
That \hyperref[time-of-flight]{TOF} would...

% ...

\section{Time of Flight Detector (TOF)} \label{time-of-flight} \label{tof}
% ...
  • I can't call your \slugify outside of \label, too. \tl_use:V seems to be the problem (undefined). If you remove the bottom most line from your macro it runs without an error (outside of \label). – Skillmon Jul 4 '17 at 23:23
  • 1
    What you want to do is simply not possible. Regex replace and assignments are just not expandable and can thus never be used in a full expansion context of, e.g., \label. – Henri Menke Jul 4 '17 at 23:33
  • 1
    In general it is a bad idea to use macros or active characters in \label and \ref. – Henri Menke Jul 4 '17 at 23:44
  • 3
    Your code would put \label{} in \section{} i.e. \section{ \label{} }. That will end in tears, even setting the expansion issues mentioned by @HenriMenke aside. – cfr Jul 5 '17 at 1:03
  • 2
    Note that you should not be creating user-level commands with \cs_new. If you want something like \slugify, use \NewDocumentCommand or whatever as a wrapper for the lower level function \ralfix_slugify:n. – cfr Jul 5 '17 at 1:05
6

What you want to do is simply not possible. Regex replace and assignments are just not expandable and can thus never be used in a full expansion context of, e.g., \label.

However, you can do things like save the processed label in a macro and pass that on or just make your \slugify macro immediately place the label, etc.

Whenever you are doing such things, keep this quote in mind:

»This is not as productive as you would think in the long run.« — percusse

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\tl_new:N \l_slugify_tl

\NewDocumentCommand \slugify { m m m }
{
  \tl_set:Nf \l_slugify_tl { \tl_lower_case:n { #3 } } %lower case
  \regex_replace_all:nnN { [^a-z]+ }{ - }\l_slugify_tl % remove non-letters
  \regex_replace_all:nnN { (^-|-$$$$) }{ } \l_slugify_tl % clean up leading/trailing dashes
  #1 { #2 \tl_use:N \l_slugify_tl }
}

\ExplSyntaxOff

\begin{document}

\subsection{The Explanation}
    \slugify{\label}{wiki:}{The Explanation}

\end{document}
  • My goal is to not have to memorize the exact labels, as there will be hundreds, created by a work group, think something wiki-like. An awesome quote, nevertheless :) – Peater de Xel Jul 5 '17 at 9:08
  • In my world, at a certain point, the regex replacements have to be fully expanded, as they are typeset in the document, aren't they? Do you have some additional material concerning your first point? Is this generally the case with the expl3 functions? – Peater de Xel Jul 5 '17 at 9:10
  • @ralfix No, typesetting isn't an expansion context: stuff can also be executed (for example assignments). The interface3 documentation marks every expandable command with a star: no star, not expandable. – Joseph Wright Jul 5 '17 at 10:34

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.