
Quando o processador de entrada encontra dois caracteres com código de categoria 5 seguidos (em outras palavras, uma linha em branco), ele insere a \par
macro.
Quando \vbox{Abc.}
termina, o TeX termina o parágrafo atual, mas não inserindo a \par
macro. Parece que o TeX está inserindo o \par
primitivo. Estou entendendo corretamente o que o TeX está fazendo neste caso? E quanto a outros lugares onde o TeX se insere \par
? Quando é a macro \par
e quando é a primitiva?
\catcode`@=11
\let\@@par\par
\def\par{\typeout{Macro!}\@@par}
Abc.
\vbox{Abc.\tracingall}
Responder1
Existem exatamente 7 locais no programa TeX onde o TeX executa o construtor de parágrafos internamente, ou seja, transformando uma lista horizontal (se houver alguma em construção) em um parágrafo. Isto acontecenãoinserindo um \par
token no fluxo de entrada, mas executando o procedimentoend_grafimplementado no módulo §1096 do programa TeX.
Este procedimento não faz nada se o TeX não estiver no modo horizontal, mais ou menos nada se estiver no modo horizontal, mas com uma lista vazia (parágrafos nulos são ignorados pelo TeX), e executa o procedimentoquebra_linhacaso contrário (e esse faz toda a mágica ao adicionar penalidades de parfillskip, etc.).
Os sete lugares são
- no final das estruturas verticais internas, como a chave de fechamento de uma
\vbox
mas também\noalign
ou\vcenter
ou uma célula de alinhamento - quando o primitivopar_endé detectado (que está inicialmente disponível no nível macro como o significado do token
\par
) - imediatamente após o término de uma rotina de saída (OR) (portanto, qualquer lista horizontal iniciada no OR não continuará com o material da cozinha, mas formará um parágrafo por si só)
Em nenhum destes casos existe um \par
token inserido (que poderá ser sujeito a redefinições); em vez disso, oend_grafprocedimento é executado!
\par
tokens são inseridos apenas quando no modo horizontal e primitivos incompatíveis com o modo horizontal (como \vskip
, \hrule
, ... a lista completa é §1094 no código TeX) são encontrados. E, claro, no processo de tokenização, quando o TeX substitui dois caracteres finais por \par
(ou seja, tornando as linhas vazias equivalentes a \par
).
Responder2
De acordo comO TeXbook, a regra para finais de linha é a seguinte
Se o TeX vir um caractere de fim de linha (categoria 5), ele descarta qualquer outra informação que possa permanecer na linha atual. Então se o TeX estiver no estadoN(nova linha), o caractere de fim de linha é convertido no token de sequência de controle
\par
(fim de parágrafo); se o TeX estiver no estadoM(linha média), o caractere de fim de linha é convertido em token para o caracter 32 ( ) da categoria 10 (espaço); e se o TeX estiver no estadoS(ignorando espaços em branco), o caractere de fim de linha é simplesmente eliminado.
Aqui, é importante observar que o TeX insere o \par
token, e não o \par
primitivo. Isso significa que isso \par
deve ser definido em todas as circunstâncias. Knuth ilustra esse ponto ao discutir comandos que forçam o modo horizontal:
A aparência de um <comando vertical> no modo horizontal restrito é proibido, mas no modo horizontal regular faz com que o TeX insira o token
\par
na entrada; depois de ler e expandir este\par
token, o TeX verá o <comando vertical> token novamente. (O significado atual da sequência de controle\par
será usado;\par
pode não representar mais\par
o primitivo do TeX.)
Agora, o que parece não ser mencionado em lugar nenhum é o que acontece no final do modo vertical interno. Claramente, as regras acima não permitem a inserção de um \par
token, pois não há marcadores de fim de linha com os quais lidar. (Você será \par
inserido se houver uma linha em branco entre o último material \vbox
e o final da caixa.)
Lendo a saída do trace, não há menção ao \par
primitivo no final da caixa, mas o envio mostra
....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil
e é claro que há claramente um parágrafo construído. Portanto, minha conclusão é que o fim do modo vertical interno insere implicitamente um \par
primitivo e, portanto, insere o material usual de final de parágrafo e, em seguida, executa o construtor de parágrafo.
Responder3
Há uma razão pela qual o TeX coloca o "significado original" de \par
no final de a \vbox
: considere a seguinte entrada boba
\vbox{\let\par\empty a}
Quando o TeX encontra }
, ele faz o backup, encerra o modo horizontal inserindo o "original \par
" e então relê o }
que fecha o modo vertical interno.
Podemos emular o que aconteceria se o TeX inserisse o significado atual de \par
antes de reler o }
by
\vbox{\let\par\empty a\vskip0pt}
porque \vskip
insere um (atual) \par
e releia o TeX \vskip
. O resultado é um loop infinito!
(Encontrado em umDiscussão de 1993 sobrecomp.text.tex
.)