3

I do some TeX experiments with 'postponed' content, writing it to some file to be included later on (not necessarily at end, but most time it would be appropriate to place it there)

I defined some writing command \WriteSomeContent with optional parameters, again using the xkeyval interface.

All is a test so far, as such I write a \pdfbookmark and a bookmark color to the postponed file. If there is no explicitly stated bookmarkcolor=colorname, it should default to \BookmarkDefaultColor, which is a command created by \newcommand.

Everything works as long one does not change from

\newcommand{\BookmarkDefaultColor}{red}%

to

\newrobustcmd{\BookmarkDefaultColor}{red}%

This leads to a statement \BookmarkDefaultColor with a final whitespace character, confusing color=\BookmarkDefaultColor and stopping the compilation.

Is this a bug of \newrobustcmd in conjunction with keyvalue expansion or some strange non-gobbling of a whitespace character (which should not be there at all, in my opinion)???

**postponed.tex**

\documentclass{book}
\usepackage{etoolbox}
\usepackage{xcolor}
\usepackage{xkeyval}
\usepackage{blindtext}%

\usepackage[bookmarksopen=true]{hyperref}
\usepackage{bookmark}


\newcommand{\BookmarkDefaultColor}{red}%
%\newrobustcmd{\BookmarkDefaultColor}{red}%


\makeatletter
\define@key{FamilyA}{bookmarkcolor}[\BookmarkDefaultColor]{%
\def\KVMacroColor{#1}%
}%


\makeatother

\presetkeys{FamilyA}{bookmarkcolor=\BookmarkDefaultColor}{}%



\newcommand{\WriteSomeContent}[4][]{%
\setkeys{FamilyA}{#1}%
\immediate\write\myhandle{%
\string#4% Content first
\string\phantomsection%
\string\pdfbookmark[1,color=\KVMacroColor]{#2}{#3}% Some bookmark
}% End of \immediate\write
}% End of command



\newwrite\myhandle%


\AtBeginDocument{%
\immediate\openout\myhandle=\jobname.post%
}%

\AtEndDocument{%
\immediate\closeout\myhandle%
\IfFileExists{\jobname.post}{\input{\jobname.post}}{Sorry, no file there}%
}%


\begin{document}

\chapter{First}

\WriteSomeContent[bookmarkcolor={cyan}]{Entry 3}{entry::number::3}{\expandafter\unexpanded{\chapter{This is the 3rd one!}}}%

\WriteSomeContent{Entry 1}{entry::number::1}{\expandafter{\unexpanded{\textbf{\textcolor{blue}{\blindtext}}}% 
}% End of unexpanded
}%

\WriteSomeContent[bookmarkcolor={blue}]{Entry 2}{entry::number::2}{\expandafter{\unexpanded{%
\vspace{\baselineskip}%

\noindent\large\textbf{And now for something completely different:}\normalsize\

\vspace{\baselineskip}
\noindent
\textbf{\textcolor{brown}{%
\blindtext}}}}}%

\chapter{Second}%



\end{document}

Temporarily written postponed.post

\expandafter\chapter {This is the 3rd one!}\phantomsection\pdfbookmark[1,color=cyan]{Entry 3}{entry::number::3}
\expandafter{\textbf {\textcolor {blue}{\blindtext }}}\phantomsection\pdfbookmark[1,color=\BookmarkDefaultColor ]{Entry 1}{entry::number::1}
\expandafter{\vspace {\baselineskip }\par \noindent \large \textbf {And now for something completely different:}\normalsize \^^M\par \vspace {\baselineskip } \noindent \textbf {\textcolor {brown}{\blindtext }}}\phantomsection\pdfbookmark[1,color=blue]{Entry 2}{entry::number::2}

And some output of the programme:

Please do not frown on chapter 3 occurring before chapter 1` etc. All is done on purpose and belongs to a more widespread framework, it will be cured at the right time.

enter image description here

  • One of the purposes of \newrobustcmd is not to expand the defined command in a \write. – egreg Jun 13 '14 at 16:28
  • @egreg: Really????I found no statement about the non-expansion in the manual or does robust imply this? – user31729 Jun 13 '14 at 16:29
  • \newrobustcmd is syntactic sugar for \protected\def. – egreg Jun 13 '14 at 16:30
  • 1
    @ChristianHupfer Did you read the etoolbox manual :-) Since it uses e-TeX’s low-level protection mechanism ... – Joseph Wright Jun 13 '14 at 16:32
  • 1
    @ChristianHupfer Read the bottom of page 14 in texdoc etex – egreg Jun 13 '14 at 16:33
4

When TeX does a \write, it fully expands material in the same way as \edef does. Thus

\immediate\write\myhandle{%
  \string#4% Content first
  \string\phantomsection%
  \string\pdfbookmark[1,color=\KVMacroColor]{#2}{#3}% Some bookmark
}%

causes \KVMacroColor to be expanded 'as far as possible'. If you insert

\show\KVMacroColor

just before the above lines you'll see three lots of output

> \KVMacroColor=macro:
->cyan.

> \KVMacroColor=macro:
->\BookmarkDefaultColor 

> \KVMacroColor=macro:
->blue.

where the key one is that middle case. When \BookmarkDefaultColor is defined using \newcommand, it's a normal macro is is itself expandable. Thus TeX happily converts it to it's content as part of the \write. On the other hand, when you use \newrobustcmd you are creating an e-TeX protected macro: these do not expand inside \edef-like contexts. TeX therefore writes the name of the command into the output. The space appears because TeX adds it in: after every control word a space is added so that the tokenization will be correct on reading back. The usual demo for the need for that is something like

\catcode`\q=12 %
\protected\def\foo{bar}
\immediate\write\mywrite{\fooq}

Note that I'm writing two tokens to the file: \foo and q, and they should be read back in the same way, which the added space ensures. (You see exactly the same in lots of places: \def\foo{\bar\baz} then \show\foo and see the spaces!)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy