\newrobustcmd 不能作为键值扩展吗?

\newrobustcmd 不能作为键值扩展吗?

我用“推迟”的内容做了一些 TeX 实验,将其写入某个文件以便稍后包含(不一定在最后,但大多数时候将其放在那里是合适的)

\WriteSomeContent再次使用接口定义了一些带有可选参数的写入命令xkeyval

到目前为止,一切都只是测试,因此我将一个\pdfbookmark和一个书签颜色写入延期文件。如果没有明确说明bookmarkcolor=colorname,则应默认为\BookmarkDefaultColor,这是由创建的命令\newcommand

一切正常,只要其中一个不改变

\newcommand{\BookmarkDefaultColor}{red}%

\newrobustcmd{\BookmarkDefaultColor}{red}%

这会导致语句\BookmarkDefaultColor的最后出现空格字符,造成混淆color=\BookmarkDefaultColor并停止编译。

这是与键值扩展相关的错误,还是某种奇怪的非吞噬空格字符的错误\newrobustcmd(在我看来,这根本不应该存在)???

**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}

暂时写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}

该程序的一些输出如下:

请不要对chapter 3在第 1 章之前发生的情况表示不满。所有这些都是故意为之,属于更广泛的框架,它将是治愈在正确的时间。

在此处输入图片描述

答案1

当 TeX 执行 时\write,它会以与 相同的方式完全扩展材料\edef。因此

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

导致\KVMacroColor“尽可能”扩展。如果你插入

\show\KVMacroColor

在上述几行之前,你会看到三组输出

> \KVMacroColor=macro:
->cyan.

> \KVMacroColor=macro:
->\BookmarkDefaultColor 

> \KVMacroColor=macro:
->blue.

其中关键的是中间的情况。当\BookmarkDefaultColor使用 定义时\newcommand,它是一个普通的宏,它本身是可扩展的。因此,TeX 很乐意将其转换为它的内容作为 的一部分\write。另一方面,当你使用 时,\newrobustcmd你正在创建一个 e-TeX受保护的宏:这些确实不是在类似上下文中展开\edef。因此,TeX 将命令的名称写入输出。空格出现是因为 TeX 添加了它:在每个控制字后添加一个空格,以便在读回时标记化是正确的。对此需求的通常演示如下

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

请注意,我写的是标记添加到文件中:\fooq,并且它们应该以相同的方式读回,这是增加的空间确保的。(您会在很多地方看到完全相同的内容:\def\foo{\bar\baz}然后\show\foo和看到空格!)

相关内容