1

My document uses a command which is renewed by every chapter. For some of chapters, I need to store its expansion as another variable (command). I need the actual expanded value, not the command.

To illustrate this is an MWE.

\documentclass{book}
\usepackage{etoolbox,ifthen,xspace}

\newcommand{\subjectshort}{Compsci} % this command is used several times in the document
\newcommand{\subjectshortl}{\MakeLowercase{\subjectshort}} % this command is an workaround just for the next command
\newcommand{\abracadabra}[1]{abracadabra:#1}
\newcommand{\chaplabel}[1]{
    \ifthenelse{\isundefined{\thischaplabeltmp}}{
        \newcommand{\thischaplabeltmp}{\abracadabra{#1}}
    } {
    \renewcommand{\thischaplabeltmp}{\abracadabra{#1}}
}
\ifthenelse{\isundefined{\thischaplabel}}{
    \newcommand{\thischaplabel}{\subjectshortl:mod:\thischaplabeltmp\xspace}
} {
\renewcommand{\thischaplabel}{\subjectshortl:mod:\thischaplabeltmp\xspace}
}
\thischaplabel
}

\begin{document}
\chapter{First chapter}
some content of first chapter\\
\chaplabel{Text specific to first chapter}\\
some more contents of first chapter\\
current thischaplabel = \thischaplabel\\
\expandafter\def\csname tmpstore\endcsname{\thischaplabel\xspace}
current tmpstore = \tmpstore\\ % this is the value I want to be avaibale till I redefine \tmpstore 

\chapter{Second chapter}
some content of second chapter\\
\chaplabel{Text specific to second chapter}\\
some more contents of second chapter\\
current thischaplabel = \thischaplabel\\
current tmpstore = \tmpstore\\ % i wanted the earlier expanded value avaibale here too
% writing to an auxiliary file does not produce the expected outcome as shown by the next line
%\expandafter\label{\tmpstore} % this breaks compliing

\chapter{Third chapter}
some content of third chapter\\
\chaplabel{Text specific to third chapter}\\
some more contents of third chapter\\

\chapter{Fourth chapter}
some content of fourth chapter\\
\chaplabel{Text specific to fourth chapter}\\
some more contents of fourth chapter\\
\end{document}

When I first call \chaplabel{Text specific to the chapter} inside a chapter, it creates or renews a command \thischaplabel and then outputs the expansion too. So far so good. However in some of the chapters I need to store the expanded value of the current \thischaplabel to be available a little longer, maybe for the next 4 chapters. I tried invoking the following in a relevant chapter

\expandafter\def\csname tmpstore\endcsname{\thischaplabel\xspace}

However it never seems to store the expanded value. Rather \tmpstore gets the value of the latest \thischaplabel .. in effect it becomes just an alias of \thischaplabel.

How do I use \tmpstore like a temporary variable holding a constant string (which itself is the expanded form of another command)?

Reason : I also need to write /tmpstore value to an auxiliary file (which is processed later). And the output I see in this aux file is the immediate expanded command instead of the final expanded (string) value. This can be seen by issuing \expandafter\label{\tmpstore} directive anywhere. Apart from all else, then it also does not compile correctly.

  • Please try to give a MWE So that we can run it and test it... I can not compile a code with your macro... I can suggest you to use the commands \xdef\temp{\csname\thischaplabel\xspace\endcsname} and \global\expandafter\let\mytmp\temp then I suppose you can use \mytmp where needed... – koleygr Jun 22 '17 at 18:11
  • MWE added. it compiles correctly. your suggestion however does not compile. – magguu Jun 22 '17 at 18:53
  • Since you're going to redefine \thischaplabel anyway, why bother with \newcommand and \renewcommand? Here \def is the best choice. – egreg Jun 23 '17 at 10:41
3

Use \protected@edef instead of \def.

The protected from of \edef is needed because the saved quantity of \tmpstore, namely \thischapterlabel, contains unexpandable macros in the form of \MakeLowercase and \xspace.

\documentclass{book}
\usepackage{etoolbox,ifthen,xspace}

\newcommand{\subjectshort}{Compsci} % this command is used several times in the document
\newcommand{\subjectshortl}{\MakeLowercase{\subjectshort}} % this command is an workaround just for the next command
\newcommand{\abracadabra}[1]{abracadabra:#1}
\newcommand{\chaplabel}[1]{
    \ifthenelse{\isundefined{\thischaplabeltmp}}{
        \newcommand{\thischaplabeltmp}{\abracadabra{#1}}
    } {
    \renewcommand{\thischaplabeltmp}{\abracadabra{#1}}
}
\ifthenelse{\isundefined{\thischaplabel}}{
    \newcommand{\thischaplabel}{\subjectshortl:mod:\thischaplabeltmp\xspace}
} {
\renewcommand{\thischaplabel}{\subjectshortl:mod:\thischaplabeltmp\xspace}
}
\thischaplabel
}

\begin{document}
\chapter{First chapter}
some content of first chapter\\
\chaplabel{Text specific to first chapter}\\
some more contents of first chapter\\
current thischaplabel = \thischaplabel\\
\makeatletter%
\expandafter\protected@edef\csname tmpstore\endcsname{\thischaplabel\xspace}
\makeatother%
current tmpstore = \tmpstore\\ % this is the value I want to be avaibale till I redefine \tmpstore 

\chapter{Second chapter}
some content of second chapter\\
\chaplabel{Text specific to second chapter}\\
some more contents of second chapter\\
current thischaplabel = \thischaplabel\\
current tmpstore = \tmpstore\\ % i wanted the earlier expanded value available here too

\chapter{Third chapter}
some content of third chapter\\
\chaplabel{Text specific to third chapter}\\
some more contents of third chapter\\

\chapter{Fourth chapter}
some content of fourth chapter\\
\chaplabel{Text specific to fourth chapter}\\
some more contents of fourth chapter\\
\end{document}

enter image description here


The OP EDITS the question and notes that he/she would like to use \tmpstore as a label. As I explained, one cannot use unexpandable material in a label. However, here I do two things. I disable \xspace with

\def\xspace{}% GETS RID OF ONE UNEXPANDABILITY (DISABLES \xspace}

(obviously, the proper approach is not to use it, rather than disabling it; I'm doing it here to demonstrate only) and then I come up with a more expandable form of \MakeLowercase in the form of

\usepackage{expl3}
\ExplSyntaxOn
\cs_set_eq:NN \explower \tl_lower_case:n% GETS RID OF SECOND UNEXPANDABILITY
\ExplSyntaxOff

which I use in

\newcommand{\subjectshortl}{\explower{\subjectshort}} % this command is an workaround just for the next command

With these changes, I can get it to work with a simple \edef, which I can then show has no unexpanded material in it (with \detokenize) and use it as a \label argument.

The bottom line is that \xspace and \MakeLowercase are not expandable and are thus not acceptable components in a \label argument.

\documentclass{book}
\usepackage{etoolbox,ifthen,xspace}

\newcommand{\subjectshort}{Compsci} % this command is used several times in the document
\newcommand{\subjectshortl}{\explower{\subjectshort}} % this command is an workaround just for the next command
\newcommand{\abracadabra}[1]{abracadabra:#1}
\newcommand{\chaplabel}[1]{
    \ifthenelse{\isundefined{\thischaplabeltmp}}{
        \newcommand{\thischaplabeltmp}{\abracadabra{#1}}
    } {
    \renewcommand{\thischaplabeltmp}{\abracadabra{#1}}
}
\ifthenelse{\isundefined{\thischaplabel}}{
    \newcommand{\thischaplabel}{\subjectshortl:mod:\thischaplabeltmp\xspace}
} {
\renewcommand{\thischaplabel}{\subjectshortl:mod:\thischaplabeltmp\xspace}
}
\thischaplabel
}

\def\xspace{}% GETS RID OF ONE UNEXPANDABILITY (DISABLES \xspace}

\usepackage{expl3}
\ExplSyntaxOn
\cs_set_eq:NN \explower \tl_lower_case:n% GETS RID OF SECOND UNEXPANDABILITY
\ExplSyntaxOff

\begin{document}
\chapter{First chapter}
some content of first chapter\\
\chaplabel{Text specific to first chapter}\\
some more contents of first chapter\\
current thischaplabel = \thischaplabel\\
\makeatletter%
\expandafter\edef\csname tmpstore\endcsname{\thischaplabel\xspace}
\makeatother%
current tmpstore = \tmpstore\\ % this is the value I want to be avaibale till I redefine \tmpstore 

\chapter{Second chapter}
some content of second chapter\\
\chaplabel{Text specific to second chapter}\\
some more contents of second chapter\\
current thischaplabel = \thischaplabel\\
current tmpstore = \tmpstore\\ % i wanted the earlier expanded value avaibale here too

Tokens of \textbackslash tmpstore:\\
\detokenize\expandafter{\tmpstore} % this breaks compliing

Using it as a label:
\expandafter\label\expandafter{\tmpstore} % this breaks compliing

\chapter{Third chapter}
some content of third chapter\\
\chaplabel{Text specific to third chapter}\\
some more contents of third chapter\\

\chapter{Fourth chapter}
some content of fourth chapter\\
\chaplabel{Text specific to fourth chapter}\\
some more contents of fourth chapter\\
\end{document}

enter image description here

  • In the MWE, it works. However it still seems not to store a constant string value. I also need to write this value to an auxiliary file (which is processed later). And the output I see in this aux file is the immediate expanded command instead of the final expanded (string) value. This can be seen by writing \expandafter\label{\tmpstore} directive anywhere. Then it also does not compile correctly. – magguu Jun 22 '17 at 19:17
  • In my edited explanation, I note that \MakeLowercase and \xspace are not expandable. I am guessing that is the root of the issue?? If not, perhaps you can add an updated MWE to your question showing the real issue. Indeed, one can not use non-expandable material in a \label. Also, \expandafter\label{\tmpstore} is improper...perhaps you mean \expandafter\label\expandafter{\tmpstore} – Steven B. Segletes Jun 22 '17 at 19:19
  • hmmm ... i cant do away with \MakeLowercase. I have edited my original question and included commented lines in MWE to highlight the issue. – magguu Jun 22 '17 at 19:26
  • @Magguu See my follow up. – Steven B. Segletes Jun 22 '17 at 19:48
  • hmmm ... I get some hang of it ... but I do not understand the sorcery of \expandafter\label\expandafter{\tmpstore} ... Why two \expandafters? In my real document, the command \abracadabra is more complicated (it is an expl3 command which uses regex). Due to that the labels still do not work fine. I have tried all sorts of tricks overnight ... but to no avail. One more thing - what does \detokenize do? – magguu Jun 23 '17 at 7:06

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.