我正在尝试在 中定义一组命令\tableofcontents
。这是一个不起作用的示例。
\documentclass{book}
\newcounter{foo}
\begin{document}
\tableofcontents
\providecommand{\foo1}{0}
\providecommand{\foo2}{0}
\foo1 \foo2
\stepcounter{foo}
\addtocontents{toc}{\protect\newcommand{\detokenize{\foo}\thefoo}{\thepage}}
text
\stepcounter{foo}
\addtocontents{toc}{\protect\newcommand{\detokenize{\foo}\thefoo}{\thepage}}
text
\end{document}
这几乎可行。命令 \detokenize 在末尾生成一个额外的空格。这会导致文件.toc
包含类似于的内容,\newcommand{\foo 1}{14}
而不是所需的内容\newcommand{\foo1}{14}
。
答案1
首先,你不能做\newcommand{\foo1}{whatever}
,也不希望\foo1
做一些明智的事情。
事实上,如果你这样做
\newcommand{\foo1}{whatever}
后 \begin{document}
已经被处理,不会有错误,但\foo
会被定义为等同于\relax
,而1
和whatever
会被打印。
如果您想根据前缀\foo
和序列号定义一组命令,您可以将其定义\foo
为带有参数的宏,以执行适当的操作。
\documentclass{article}
\makeatletter
\newcommand{\foo}[1]{%
\@ifundefined{foo#1}{INEXISTENT}{\@nameuse{foo#1}}%
}
\newcounter{foo}
\newcommand{\serialize}{%
\stepcounter{foo}%
\addtocontents{toc}{%
\global\protect\@namedef{foo\thefoo}{\thepage}%
}%
}
\makeatother
\begin{document}
\tableofcontents
Here is \verb|\foo{1}|: \foo{1}
Here is \verb|\foo{2}|: \foo{2}
Here is \verb|\foo{3}|: \foo{3}
Some contents
\serialize
\newpage
Some contents
\serialize
\end{document}
答案2
虽然可以定义类似这样的命令\foo1
,但没有真正方便的用户界面来访问它,因为控制序列/命令应该只包含字母字符(默认情况下)。您需要\csname foo1\endcsname
或定义类似
\newcommand{\nameuse}[1]{\csname #1\endcsname}
或者
\makeatletter
\let\nameuse\@nameuse% From the LaTeX2e kernel
\makeatother
来规避它的限制。
除此之外,如果您有\protect
不应扩展的命令,您可以在目录中定义内容:
\documentclass{article}
\newcounter{foo}
\renewcommand{\thefoo}{\Alph{foo}}
\begin{document}
\tableofcontents
\section{A section}
\providecommand{\fooA}{0}
\providecommand{\fooB}{0}
\fooA~\fooB
\makeatletter
\stepcounter{foo}%
\addtocontents{toc}{\global\protect\@namedef{foo\thefoo}{\thepage}}
\makeatother
text
\makeatletter
\stepcounter{foo}%
\addtocontents{toc}{\global\protect\@namedef{foo\thefoo}{\thepage}}
\makeatother
text
\end{document}
我曾经\Alph{foo}
在宏创建中使用字母字符。