4

I'm trying to increase my LaTeX3-fu, but I'm getting an error about encountering printed output before the document begins.

I'm trying to generalize How to get the section title by section number?.

I also understand that LaTeX3's big punch is to (mostly) do away with \expandafter, but I don't know the equivalent syntax if there is a one-to-one relationship. (I'm really just trying to learn, here :-).)

Here is my code:

\documentclass{article}

\usepackage{xparse}

% Macro to insert labels at the end of other macros
\ExplSyntaxOn
\NewDocumentCommand{\labelize}{mm}{
  % Automatically inserts a label of the form \label{#2:\the#1}for
  % referencing after every #1

  % For example:
  % \labelize{section}{auto-section}
  % ...
  % \begin{document}
  % \section{something}
  % -->\label{auto-section:1}
  % \section{something else}
  % -->\label{auto-section:2}
  % \end{document}


  % #1 : Macro to labelize
  % #2 : Prefix for label

  % Store the old macro
  \let\expandafter\csname old#1\endcsname\expandafter\csname #1\endcsname

  % Adapted from https://tex.stackexchange.com/questions/76078/
               % how-to-get-the-section-title-by-section-number
  \expandafter\renewcommand\csname #1\endcsname[2]{
    \ifx##1\relax
      \csname old#1\endcsname{##2}
    \else
      \csname old#1\endcsname[##1]{##2}
    \fi
    \label{#2:\csname the#1\endcsname}%
  }
}
\ExplSyntaxOff

\labelize{section}{auto@section}

\begin{document}
Hi
\end{document}
7
  • You should know that \section takes no argument. It's not clear what the \labelize command should do. And, most importantly, you're trying to redefine \expandafter; at least switch the positions of \renewcommand and \expandafter; \expandafter\csname is a (minor) mistake, too. – egreg Jul 6 '13 at 20:28
  • @egreg ? but section{argument here?}? How then does the more explicit case (linked) work? I tried to model it exactly. – Sean Allred Jul 6 '13 at 20:31
  • Well, I'd say that Werner's answer is not the best LaTeX programming I've ever seen. Can you please state clearly what \labelize is supposed to do? – egreg Jul 6 '13 at 20:33
  • @egreg See my edit, I incorporated your notes from your first comment, although I'm still unsure of what you mean by "\section takes no arguments"... it at least seems to as an end-user. – Sean Allred Jul 6 '13 at 20:38
  • @egreg Do you think I need to \expandafter to hop over \let until the control sequences \csname ... \endcsname resolve? – Sean Allred Jul 6 '13 at 23:42
7

I don't know what xparse and LaTeX3 has to do with this. You have almost all your \expandafter commands in the wrong place.

This works, but you lose the ability of using \section*.

\documentclass{article}

% Macro to insert labels at the end of other macros
\newcommand{\labelize}[2]{%
  % Automatically inserts a label of the form \label{#2:\the#1}for
  % referencing after every #1
  % For example:
  % \labelize{section}{auto-section}
  % ...
  % \begin{document}
  % \section{something}
  % -->\label{auto-section:1}
  % \section{something else}
  % -->\label{auto-section:2}
  % \end{document}
  % #1 : Macro to labelize
  % #2 : Prefix for label
  % Store the old macro
  \expandafter\let\csname old#1\expandafter\endcsname\csname #1\endcsname
  % Adapted from http://tex.stackexchange.com/questions/76078/
               % how-to-get-the-section-title-by-section-number
  \expandafter\renewcommand\csname #1\endcsname[2][]{
    \if\relax\detokenize{##1}\relax
      \csname old#1\endcsname{##2}%
    \else
      \csname old#1\endcsname[##1]{##2}%
    \fi
    \label{#2: \csname the#1\endcsname}%
  }
}

\labelize{section}{auto@section}

\begin{document}
\section{Test}
Hi

\ref{auto@section:1}
\end{document}

Of course using \ref{auto@section:1} is pointless, but if the automatically generated label is to be used via some macro, then it can be useful.

Here's a LaTeX3 version that allows for \section* as well as the optional argument. Note, however, that the first argument to \labelize should be the command (with the backslash). It would be possible to use the same syntax as before, but I believe this is clearer.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
% Macro to insert labels at the end of other macros
\NewDocumentCommand{\labelize}{mm}
 {
  \sean_labelize:Nn #1 { #2 }
 }

\cs_new_protected:Npn \sean_labelize:Nn #1 #2
 {
  \cs_set_eq:cN { original_ \cs_to_str:N #1 } #1
  \RenewDocumentCommand #1 { som }
   {
    \IfBooleanTF{##1}
     {
      \use:c { original_ \cs_to_str:N #1 }*{##3}
     }
     {
      \IfNoValueTF{##2}
       {
        \use:c { original_ \cs_to_str:N #1 } {##3}
       }
       {
        \use:c { original_ \cs_to_str:N #1 } [##2]{##3}
       }
      \label{#2: \use:c{the\cs_to_str:N #1} }%
     }
   }
 }
\ExplSyntaxOff

\labelize{\section}{auto@section}

\begin{document}
\section{Test}
Hi

\ref{auto@section:1}

\section*{Star}

Hi
\end{document}
1
  • This works like a charm, but it isn't magic. I've got a date with the library's copy of the TeXbook this Tuesday; I've yet to read it so I'm not surprised about my own misuse and abuse of \expandafter. I'll have to study the syntax you've used, but I was looking for a LaTeX3 version, hence the tag. The reference will be automatically used in the breadcrumbs question. – Sean Allred Jul 7 '13 at 0:05

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.