我用“推迟”的内容做了一些 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}
请注意,我写的是二标记添加到文件中:\foo
和q
,并且它们应该以相同的方式读回,这是增加的空间确保的。(您会在很多地方看到完全相同的内容:\def\foo{\bar\baz}
然后\show\foo
和看到空格!)