
Considere este exemplo:
\documentclass{report}
\def\startnewpart{FALSE}
\makeatletter
\renewcommand\chapter{\if@openright\cleardoublepage\else\clearpage\fi
% \def\startnewpart{FALSE}
\thispagestyle{plain}%
\global\@topnum\z@
\@afterindentfalse
\secdef\@chapter\@schapter
% \def\startnewpart{FALSE}
}
\makeatother
\begin{document}
\tableofcontents
\chapter{Methods}
Some text
\end{document}
Se \renewcommand\chapter
eu descomentar o primeiro, \def\startnewpart{FALSE}
o documento será compilado corretamente.
Se, em vez disso, eu descomentar no segundo, \def\startnewpart{FALSE}
recebo um erro:
Chapter 1.
! Missing { inserted.
\@makechapterhead ...1\par \nobreak \vskip 40\p@ }
l.21 \tableofcontents
Onde está a diferença?
Neste exemplo estou explorando como usar uma variável de controle \startnewpart
para controlar a execução de \chapter
. \def\startnewpart{FALSE}
destina-se a redefinir o valor de \startnewpart
.
Responder1
\secdef
é definido como
% latex.ltx, line 6086:
\def\secdef#1#2{\@ifstar{#2}{\@dblarg{#1}}}
No seu caso você consegue
\@ifstar{\@schapter}{\@dblarg{\@chapter}}
Agora \@ifstar
analisa o seguinte token. Se você descomentar a segunda \def
linha, o próximo token não será *
, mas \def
. Assim, o LaTeX encontra
\@dblarg{\@chapter}\def\startnewpart{FALSE}
Aqui está a definição de \@dblarg
:
% latex.ltx, line 1105:
\long\def\@dblarg#1{\kernel@ifnextchar[{#1}{\@xdblarg{#1}}}
Assim você consegue
\kernel@ifnextchar[{\@chapter}{\@xdblarg{\@chapter}}\def\startnewpart{FALSE}
A macro \kernel@ifnextchar
absorve três argumentos, aqui [
, {\@chapter}
e {\@xdblarg{\@chapter}}
verifica se o próximo token é [
. Não é, porque é \def
, então o efeito é obter
\@xdblarg{\@chapter}\def\startnewpart{FALSE}
OK, vamos dar uma olhada em \@xdblarg
:
% latex.ltx, line 1106:
\long\def\@xdblarg#1#2{#1[{#2}]{#2}}
Aqui #1
está {\@chapter}
(mas os colchetes serão removidos por regra), então você acaba com
\@chapter[{\def}]{\def}\startnewpart{FALSE}
o que certamente não é algo que você gostaria de ter em seu código.
Não está realmente vinculado a \def
. Comandos como
\secdef\A\B
\@ifstar{A}{B}
\@ifnextchar<char>{A}{B}
devesemprevêm por último em um código de definição, porque eles querem ver o que vem a seguir.