我练习了xparse
。我重写了 的定义\part
。当我尝试以下代码时,一切正常:
\documentclass{book}
\usepackage{xparse}
\newcounter{spart}% makes hyperref work
\makeatletter
\DeclareDocumentCommand{\part}{s m o}%
{\cleardoublepage\thispagestyle{plain}%
\if@twocolumn%
\onecolumn%
\@tempswatrue%
\else%
\@tempswafalse%
\fi%
\null\vfil%
\IfNoValueTF{#3}%
{\IfBooleanTF{#1}{\m@part*{#2}{#2}}{\m@part{#2}{#2}}}%
{\IfBooleanTF{#1}{\m@part*{#2}{#3}}{\m@part{#2}{#3}}}}
\DeclareDocumentCommand{\m@part}{s m m}%
{\IfBooleanTF{#1}{\refstepcounter{spart}% makes hyperref work
\addcontentsline{toc}{part}{#3}}%
{\ifnum \c@secnumdepth >-2\relax%
\refstepcounter{part}%
\addcontentsline{toc}{part}{\thepart\hspace{1em}#3}%
\else%
\addcontentsline{toc}{part}{#3}%
\fi}%
\markboth{}{}%
{\centering%
\interlinepenalty \@M%
\normalfont%
\IfBooleanF{#1}{\ifnum \c@secnumdepth >-2\relax%
\huge\bfseries \partname~\thepart%
\par%
\vskip 20\p@%
\fi}%
\Huge \bfseries #2\par}%
\@endpart}
\makeatother
\usepackage{blindtext}
\usepackage{hyperref}
\begin{document}
\tableofcontents
\part{Teil 1}
\Blinddocument
\part*{Teil 2}
\Blinddocument
\end{document}
看看我的 \m@part 宏。首先我尝试将其命名为 \@part,就像在 book.cls 中调用的那样。但是当我编译它时出现了一些错误。例如:
Use of \@part doesn't match its Definition.
或者
Too many }'s.
我不明白这个问题。为什么它可以与 一起使用\m@part
,但不能与 一起使用\@part
?
谢谢。
答案1
问题在于hyperref
重新定义\@part
,本质上是为了用计数器做你自己所做的事情spart
。
无论如何,您不需要使用两个宏。我不会改变部分的语法:可选参数应该放在强制参数之前。
\documentclass{book}
\usepackage{xparse}
\usepackage{hyperref}
\makeatletter
\DeclareDocumentCommand{\part}{s O{#3} m}{%
\cleardoublepage\thispagestyle{plain}%
\if@twocolumn
\onecolumn
\@tempswatrue
\else
\@tempswafalse
\fi
\null\vfil
\IfBooleanTF{#1}
{% * version
\csname phantomsection\endcsname % for hyperref
\addcontentsline{toc}{part}{#2}%
}
{% standard version
\ifnum\c@secnumdepth >-2\relax
\refstepcounter{part}%
\addcontentsline{toc}{part}{\thepart\hspace{1em}#2}%
\else
\addcontentsline{toc}{part}{#2}%
\fi
}%
\markboth{}{}%
{% print the title
\centering \interlinepenalty\@M \normalfont
\IfBooleanF{#1}
{% standard version
\ifnum \c@secnumdepth >-2\relax
\huge\bfseries \partname~\thepart
\par
\vskip 20\p@
\fi
}%
\Huge \bfseries #2\par
}%
\@endpart
}
\makeatother
\begin{document}
\tableofcontents
\part{Teil 1}
\part[Ops 2]{Teil 2}
\part*{Teil 3}
\part*[Ops 4]{Teil 4}
\end{document}
请注意,您需要最新版本xparse
才能正常工作(2017/02/10 或更高版本)。
答案2
hyperref
重新定义了\addcontentsline
和\label
分段命令,添加了超链接功能等。
如果您的定义不应干扰,则它应该在完成其工作后抓住等hyperref
的定义或在之后重新定义它。\@part
hyperref
hyperref
将重新定义包装在\AtBeginDocument{...}
作品中。
我拿了 OP 的原始版本并把它包裹在\AtBeginDocument{...}
钩子中,在我看来,没有必要xparse
为此使用最新版本。
\documentclass{book}
\usepackage{xparse}
\newcounter{spart}% makes hyperref work
\usepackage{blindtext}
\usepackage{hyperref}
\makeatletter
\AtBeginDocument{%
\DeclareDocumentCommand{\part}{s m o}%
{\cleardoublepage\thispagestyle{plain}%
\if@twocolumn%
\onecolumn%
\@tempswatrue%
\else%
\@tempswafalse%
\fi%
\null\vfil%
\IfNoValueTF{#3}%
{\IfBooleanTF{#1}{\m@part*{#2}{#2}}{\m@part{#2}{#2}}}%
{\IfBooleanTF{#1}{\m@part*{#2}{#3}}{\m@part{#2}{#3}}}}
\DeclareDocumentCommand{\m@part}{s m m}%
{\IfBooleanTF{#1}{\refstepcounter{spart}% makes hyperref work
\addcontentsline{toc}{part}{#3}}%
{\ifnum \c@secnumdepth >-2\relax%
\refstepcounter{part}%
\addcontentsline{toc}{part}{\thepart\hspace{1em}#3}%
\else%
\addcontentsline{toc}{part}{#3}%
\fi}%
\markboth{}{}%
{\centering%
\interlinepenalty \@M%
\normalfont%
\IfBooleanF{#1}{\ifnum \c@secnumdepth >-2\relax%
\huge\bfseries \partname~\thepart%
\par%
\vskip 20\p@%
\fi}%
\Huge \bfseries #2\par}%
\@endpart}
}
\makeatother
\begin{document}
\tableofcontents
\part{Teil 1}
\Blinddocument
\part*{Teil 2}
\Blinddocument
\end{document}