6

I need chapter/section specific labels to be generated dynamically for each chapter and section. I have modified the chapter and section command to do that. I use a regex based string manipulation and the following scheme to achieve it (MWE uses an article class to illustrate) -

\documentclass{article}
\usepackage{expl3,l3regex}
\ExplSyntaxOn
\NewDocumentCommand{\compactlabel}{m}
{
    \tl_set:Nn \l_tmpa_tl { #1 }
    \regex_replace_all:nnN {[^a-zA-Z]} {\ } \l_tmpa_tl
    \regex_replace_all:nnN {\ ([a-zA-Z]{1,2}\ )*} {\ } \l_tmpa_tl
    \regex_replace_all:nnN {^[a-zA-Z]{1,2}\ } {\ } \l_tmpa_tl
    \regex_replace_all:nnN {\ [a-zA-Z]{1,2}$} {\ } \l_tmpa_tl
    \regex_replace_all:nnN {^\ +} {} \l_tmpa_tl
    \regex_replace_all:nnN {\ +$} {} \l_tmpa_tl
    \regex_replace_all:nnN {\ +} {\ } \l_tmpa_tl
    \regex_replace_all:nnN {\ } {_} \l_tmpa_tl
    \regex_replace_all:nnN {(^\w{1,20})\w*} {\1} \l_tmpa_tl
    \regex_replace_all:nnN {_$} {} \l_tmpa_tl
    \tl_use:N \l_tmpa_tl
}
\ExplSyntaxOff
\begin{document}
% \sidebyside is a temporary command just to display and illustrate the point
\newcommand*{\sidebyside}[1]{
        #1

        \compactlabel{#1}
}

    \sidebyside{A 1st Mathematical Primer for the universe of chimpmunks}
\end{document}

My objectives :

  1. The argument string must be cleared of all one and two letter words as well as all numbers and non-characters.
  2. All multiple or single spaces the in the string must be replaced by an underscore.
  3. The last or first character of the output must not be an underscore.
  4. The string size should be curtailed at 20**.

So in the MWE, I see this as output -

A 1st Mathematical Primer for the universe of chimpmunks
mathematical_primer

** Notice the magic number 20 in the line \regex_replace_all:nnN {(^\w{1,20})\w*} {\1} \l_tmpa_tl above.

** Ideally I want this number to be a variable, default set at 20. So if I call \compactlabel{#1} it should mean 20 as above. But I would like to also call something like \compactlabel[10]{#1} and get the string size to be curtailed by 10.

PS: To be honest I do not claim to completely understand the expl3 or l3regex syntax. I copied and adapated it from tex.stackexchage forum.

  • 1
    May I ask, why? – Henri Menke Jun 22 '17 at 6:03
  • My scheme of label generation is something like math:chap:chapter_name for chapters and math:sec:chapter_name:section_name for sections. The total number of documents I am writing is huge and they all are interlinked so cross referencing must be possible. math might change to phy or chem or comp or elec. chapter_name or section_name is where the output of regex manipulation enter. the chapter names or section names might have conflicts so such an elaborate labeling is desirable. But to have shorter/manageable labels, I want a degree of flexibility for regex output size. – magguu Jun 22 '17 at 6:10
  • It is possible to write one or two new commands which differs only in the number 20 and my purpose will be served.... after all I do need only a few options (say 5 or 10 or 20). But this is an inelegant solution. I am curious if total flexibility is possible. – magguu Jun 22 '17 at 6:12
  • If you need such a degree of automation, why not simply \detokenize the title and the number and use this as the label? – Henri Menke Jun 22 '17 at 6:15
  • A much more efficient way of extracting first 20 characters of a string is \str_range:Nnn. – Bruno Le Floch Jul 12 '17 at 21:40
4

Use an optional argument:

\documentclass{article}
\usepackage{xparse}
%\usepackage{l3regex} % only for releases earlier than June 2017

\ExplSyntaxOn
\NewDocumentCommand{\compactlabel}{O{20}m}
 {
  \tl_set:Nn \l_tmpa_tl { #2 }
  \regex_replace_all:nnN {[^a-zA-Z]} {\ } \l_tmpa_tl
  \regex_replace_all:nnN {\ ([a-zA-Z]{1,2}\ )*} {\ } \l_tmpa_tl
  \regex_replace_all:nnN {^[a-zA-Z]{1,2}\ } {\ } \l_tmpa_tl
  \regex_replace_all:nnN {\ [a-zA-Z]{1,2}$} {\ } \l_tmpa_tl
  \regex_replace_all:nnN {^\ +} {} \l_tmpa_tl
  \regex_replace_all:nnN {\ +$} {} \l_tmpa_tl
  \regex_replace_all:nnN {\ +} {\ } \l_tmpa_tl
  \regex_replace_all:nnN {\ } {_} \l_tmpa_tl
  \regex_replace_all:nnN {(^\w{1,#1})\w*} {\1} \l_tmpa_tl
  \regex_replace_once:nnN {_$} {} \l_tmpa_tl
  \tl_use:N \l_tmpa_tl
 }
\ExplSyntaxOff

\begin{document}

A 1st Mathematical Primer for the universe of chimpmunks

\texttt{\compactlabel{A 1st Mathematical Primer for the universe of chimpmunks}}

\texttt{\compactlabel[10]{A 1st Mathematical Primer for the universe of chimpmunks}}

\end{document}

Note that l3regex has been included in the kernel with the last release of expl3.

enter image description here

A revised version with comments; I added also lowercasing the final string. The last two examples end up with the same string, because of removal of a trailing underscore.

\documentclass{article}
\usepackage{xparse}
%\usepackage{l3regex} % only for releases earlier than June 2017

\ExplSyntaxOn
\NewDocumentCommand{\compactlabel}{O{20}m}
 {
  \tl_set:Nn \l_tmpa_tl { #2 }
  % remove non alphabetic/space characters
  \regex_replace_all:nnN {[^a-zA-Z\s]} {} \l_tmpa_tl
  % remove one or two character words
  \regex_replace_all:nnN {\b[a-zA-Z]{1,2}\b} {} \l_tmpa_tl
  % remove leading and trailing spaces
  \regex_replace_once:nnN {\A\s+} {} \l_tmpa_tl
  \regex_replace_once:nnN {\s+\Z} {\ } \l_tmpa_tl
  % change runs of spaces into one underscore
  \regex_replace_all:nnN {\s+} {_} \l_tmpa_tl
  % curtail at the stated limit (default 20)
  \regex_replace_all:nnN {(^\w{1,#1})\w*} {\1} \l_tmpa_tl
  % remove a possible trailing underscore
  \regex_replace_once:nnN {_\Z} {} \l_tmpa_tl
  % use the result
  \tl_set:Nx \l_tmpa_tl { \str_lower_case:f { \tl_use:N \l_tmpa_tl } }
  \tl_use:N \l_tmpa_tl
 }
\ExplSyntaxOff

\begin{document}

A 1st Mathematical Primer for the universe of chimpmunks

\texttt{\compactlabel{A 1st Mathematical Primer for the universe of chimpmunks}}

\texttt{\compactlabel[10]{A 1st Mathematical Primer for the universe of chimpmunks}}

\texttt{\compactlabel[11]{A 1st Mathematical Primer for the universe of chimpmunks}}

\texttt{\compactlabel[12]{A 1st Mathematical Primer for the universe of chimpmunks}}

\texttt{\compactlabel[13]{A 1st Mathematical Primer for the universe of chimpmunks}}

\end{document}

enter image description here

  • though the answer is acceptable, I am curious as to why \texttt is necessary? I see a overhead small dot in place of underscore if I try to print it directly. However in some cases where \compactlabel is buried even deeper into layers of commands, the underscore prints correctly. Why so? – magguu Jun 23 '17 at 7:20
  • @Magguu If you use T1 encoded fonts, the underscore will print as such. – egreg Jun 23 '17 at 7:30

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.