6

I'm trying to write a macro to change the definitions of \thesection, \thechapter, and other commands for the sectioning prefixes. I want to redefine only one of the commands depending on the user's input to a command. I've tried something like this:

\documentclass{report}

\usepackage{etoolbox}
\usepackage{titlesec}

\newcommand{\changeprefix}[2]{
  %\renewcommand\csname the#1\endcsname{#2} % ! Extra \endcsname.

  %\renewcommand \the#1{#2} %! Argument of \rem@pt has an extra }.

  %\def\headername{\csuse{the#1}}
  %\renewcommand \headername {#2} % compiles but has no effect

  %\renewcommand \csuse{the#1} {#2} % compiles but prints the value of #2

  \makeatletter
  \expandafter\renewcommand \@nameuse{the#1} {#2} % compiles but prints everything after \@
  \makeatother
}

\begin{document}
\changeprefix{section}{test prefix - }
\section{Test section}
Some text...
\end{document}

My attempts don't quite work. For the two bottom ones (that actually compile) I get the following output:

No visual change

Prints value of #2 and some scrap text

Prints everything from the \@

I've taken my inspiration from this answer as well as this one, but I'm not quite there yet. Is it possible to make this work and get the following output for the \section{Test section} call?

test prefix - Test section

7

First attempt

\renewcommand\csname the#1\endcsname{#2}

You're trying to redefine \csname to be t

Second attempt

\renewcommand \the#1{#2}

You're trying to redefine \the to expand to the first token in #1

Third attempt

\def\headername{\csuse{the#1}}
\renewcommand \headername {#2} % compiles but has no effect

You're redefining \headername

Fourth attempt

\renewcommand \csuse{the#1} {#2}

You're redefining \csuse

Fifth attempt

\makeatletter
\expandafter\renewcommand \@nameuse{the#1} {#2}
\makeatother

You're trying to define \spacefactor, because you're expanding \@. Note that \makeatletter and \makeatother should surround the outer \newcommand, not be inside the replacement text. But this wouldn't fix the code, because

\makeatletter
\newcommand\changeprefix[2]{
  \expandafter\renewcommand \@nameuse{the#1} {#2}
}
\makeatother

would try and redefine \csname, which is the first token in the expansion of \@nameuse.

Correct version

\makeatletter
\newcommand{\changeprefix}[2]{%
  \@namedef{the#1}{#2}%
}
\makeatother

or

\newcommand{\changeprefix}[2]{%
  \expandafter\renewcommand\csname the#1\endcsname{#2}%
}
  • Thanks a bunch! This makes me realize there is a lot for me to learn regarding how LaTeX evaluates code. – Christian Eriksson Jan 7 '18 at 19:31
4

Since etoolbox is loaded already, there is a quicker way with \csdef or \csgdef, depending on the desired 'sustainability' in a group:

No 'weird' \makeatletter...\expandafter...\makeatother constructs to be used here:

\documentclass{report}

\usepackage{etoolbox}

\newcommand{\changeprefix}[2]{%
  \csdef{the#1}{#2}%
}

\begin{document}
\changeprefix{section}{test prefix - }
\section{Test section}
Some text...
\end{document}
0

After some additional experimenting I managed to get it working with a modification to the first attempt in the question so:

\renewcommand\csname the#1\endcsname{#2}

became:

\expandafter\renewcommand\csname the#1\endcsname{#2}

If I've understood this correctly, the \renewcommand macro was expanded before its input was finished. With this change the evaluation of \renewcommand is halted until \csname ... \endcsname has been evaluated.

I still don't quite know what was wrong with the other attempts, any input on these is welcome. But my problem is solved for now.

  • 3
    \renewcommand\csname t is \renewcommand\csname{t} and redefines \csname to be t after that latex is pretty broken and you will get assorted errors. – David Carlisle Jan 7 '18 at 18:16
  • Not quite, what happens is that the \csname macro is expanded by \expandafter, and \renewcommand is applied to the resulting string. – sgf Jan 8 '18 at 9:38

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.