Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I need a macro, which saves a string (like the content of a label) to the aux file. During the next run, there should be a macro checking, if that string has been set in the last run or not.

My solution so far presented as an example:

\documentclass{minimal}
\usepackage{etoolbox}

\makeatletter
\def\csxdefaux#1{%
    \protected@write\@mainaux{}{%
        \expandafter\string\expandafter\xdef\expandafter\string\csname #1\endcsname{}%
    }%
}
\makeatother

\begin{document}
    \ifcsdef{setValue}{value set}{value \emph{not} set}
    \csxdefaux{setValue}

    \ifcsdef{strange:value}{strange value set}{strange value \emph{not} set}
    \csxdefaux{strange:value}
\end{document}

This results (after multiple compilations) in: enter image description here

So although the pair of \csxdefaux and \ifcsdef macros obviously works for normal strings, it fails for strings with special characters.

What would be a good way to achieve the same as with my solution but supporting a wide range of special characters like colons, digits, umlauts?

share|improve this question

1 Answer 1

up vote 12 down vote accepted

The issue is nothing to do with \ifcsdef, as it is testing correctly and giving the correct answer. To see why, we need to look at the .aux file. With your definition, the .aux file reads

\relax 
\xdef\setValue{}
\xdef\strange:value{}

which is then read back by LaTeX to defined \setValue (as required), and \strange as a delimited macro (wrong). The latter happens as : is an 'other' character at this point, and the tokenization you had before is lost when you write something to a file.

What you therefore need is the \csname ...\endcsname construct inside the .aux file. One working definition is

\def\csxdefaux#1{%
    \protected@write\@mainaux{}{%
        \string\expandafter\string\gdef
          \string\csname\string\detokenize{#1}\string\endcsname{}%
    }%
}

or using the etoolbox wrapper

\def\csxdefaux#1{%
    \protected@write\@mainaux{}{%
        \csgdef{\detokenize{#1}}{}%
    }%
}

I've detokenized #1 when it's read back in case something like babel has made anything active. (I'm not sure why you have \xdef, so went with \gdef instead.)

share|improve this answer
    
Brilliant answer, thanks very much. The \xdef is not needed in this simple example, it was a relic of a more complex use case. –  Patrick Häcker Jul 22 '12 at 19:10

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.