
\addtocontents
확장이 에서 , 더 정확하게는 에서 어떻게 작동하는지 혼란스럽습니다 \protected@write
. 내가 이해하는 바에 따르면 \addtocontents
기본적으로 두 번째 인수를 확장 \protected@edef
하고 결과를 aux 파일에 써야 합니다. 이러한 이해를 통해 나는 동작이 (최대 a까지 \protected@
) 동일 할 것으로 기대합니다.
\iow_shipout:Ne \@auxout
{
\exp_not:N \@writefile { #1 } { #2 }
}
그러나 다음 MWE에서 볼 수 있듯이 \exp_not:n
.
\documentclass{article}
\makeatletter
\ExplSyntaxOn
\NewDocumentCommand { \naiveaddtocontents } { m m }
{
\iow_shipout:Ne \@auxout
{
\exp_not:N \@writefile { #1 } { #2 }
}
}
\ExplSyntaxOff
\def\abc{some text}
\begin{document}
bla
\ExplSyntaxOn
% this does what I expect
\protected@edef \l_tmpa_tl { \exp_not:n { \abc } }
\tl_show:N \l_tmpa_tl
% so does this
\naiveaddtocontents{ lof }{ \exp_not:n { \abc } }
% this does not
\addtocontents{ lof }{ \exp_not:n { \abc } }
\ExplSyntaxOff
\end{document}
aux 파일은 다음과 같습니다
\relax
\@writefile {lof}{\abc }
\@writefile{lof}{some text}
\gdef \@abspage@last{1}
그래서 \naiveaddtocontents
확장을 방지하고 있지만 \exp_not:n
그렇지 \addtocontents
않습니다. 인수가 전혀 확장되는 것을 원하지 않는 사용 사례에서는 this 을 사용할 수 있습니다 \naiveaddtocontents
. 그런데 \exp_not:n
에서 내가 잘못 예상한 대로 작동 하지 않는 이유는 무엇입니까 \addtocontents
?
답변1
이 명령 \addtocontents
은 \protected@write
. 다음은 \protected@write
from 의 정의입니다 source2e
.
\long\def \protected@write#1#2#3{%
\begingroup
\let\thepage\relax
#2%
\let\protect\@unexpandable@protect
\edef\reserved@a{\write#1{#3}}%
\reserved@a
\endgroup
\if@nobreak\ifvmode\nobreak\fi\fi
}
관련 부분은 입니다 \edef\reserved@a{\write#1{#3}}%
. 위의 정의가 \protected@write
문서와 이전 줄에 추가되면 는 .aux 파일에 제공 \edef
됩니다 .\def
\addtocontents{ lof }{ \exp_not:n { \abc } }
\@writefile{lof}{\abc }
그러나 를 사용하면 .aux 파일에 제공되는 \edef
추가 확장이 발생합니다 .\addtocontents{ lof }{ \exp_not:n { \abc } }
\@writefile{lof}{some text}
따라서 를 사용하면 추가 항목이 추가 \edef
되면 예제가 작동합니다 . .aux 파일에 제공됩니다 .\exp_not:n
\addtocontents{ lof }{ \exp_not:n { \exp_not:n { \abc } } }
\@writefile{lof}{\abc }
답변2
다음의 정의를 살펴보겠습니다 \addtocontents
.
% latex.ltx, line 14289:
\long\def\addtocontents#1#2{%
\protected@write\@auxout
{\let\label\@gobble \let\index\@gobble \let\glossary\@gobble}%
{\string\@writefile{#1}{#2}}}
\label
순진한 정의를 사용하면 에 대한 두 번째 인수에 a가 있으면 큰 문제가 발생할 수 있습니다 \addtocontents
. 하지만 이는 기술적인 문제이므로 생략하겠습니다.
당신이 원한다고 가정하십시오 \addtocontents{toc}{Hey, this is \textbf{boldface}}
.
\documentclass{article}
\makeatletter
\ExplSyntaxOn
\NewDocumentCommand { \naiveaddtocontents } { m m }
{
\iow_shipout:Ne \@auxout
{
\exp_not:N \@writefile { #1 } { #2 }
}
}
\ExplSyntaxOff
\makeatother
\begin{document}
Some text
\addtocontents{toc}{Hey, this is \textbf{boldface}}
\naiveaddtocontents{toc}{Hey, this is \textbf{boldface}}
\end{document}
콘솔이 인쇄됩니다
(\end occurred when \ifx on line 21 was incomplete)
(\end occurred when \ifx on line 21 was incomplete)
(\end occurred when \ifx on line 21 was incomplete)
(\end occurred when \ifmmode on line 21 was incomplete)</usr/local/texlive/2023
/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb>
그리고 aux
파일은
\relax
\@writefile{toc}{Hey, this is \textbf {boldface}}
\@writefile {toc}{Hey, this is \protect \unhbox \voidb@x \bgroup \edef l3backend-pdftex.def{boldface}\let \futurelet \@let@token \let \protect \relax \edef cmr{cmr}\edef cmss{cmss}\edef cmtt{cmtt}\def ##1,b,{}\series@check@toks {,ulm,elm,lm,slm,mm,sbm,bm,ebm,ubm,muc,mec,mc,msc,msx,mx,mex,mux,{}{},b,}\edef {}\edef b{b}\def ##1,m,{}\series@check@toks {,ulm,elm,lm,slm,mm,sbm,bm,ebm,ubm,muc,mec,mc,msc,msx,mx,mex,mux,{}{},m,}\edef {}\edef m{m}\protect \let }
\gdef \@abspage@last{1}
실제로 당신이 보고 싶은 것은 아니지 않습니까? 문제를 해결해 봅시다.
\documentclass{article}
\makeatletter
\ExplSyntaxOn
\NewDocumentCommand { \naiveaddtocontents } { m m }
{
\iow_shipout:Ne \@auxout
{
\exp_not:N \@writefile { #1 } { \text_expand:n { #2 } }
}
}
\ExplSyntaxOff
\makeatother
\newcommand{\abc}{some text}
\begin{document}
Some text
\addtocontents{toc}{Hey, this is \textbf{boldface} and \abc}
\naiveaddtocontents{toc}{Hey, this is \textbf{boldface} and \abc}
\end{document}
이제 aux
파일에는
\relax
\@writefile{toc}{Hey, this is \textbf {boldface} and some text}
\@writefile {toc}{Hey, this is \textbf {boldface} and some text}
\gdef \@abspage@last{1}
기본적으로 은 (는 \text_expand:n
) 거의 동일한 작업을 수행 \protected@edef
하지만 결과 토큰 목록을 \unexpanded
.
그렇게 하면 \exp_not:n
(즉,\unexpanded
), TeX는 그렇게 할 것입니다아니요\abc
확장이므로 확장이 아닌 얻을 수 있습니다 .
\makeatletter
및 없음 \makeatother
:
\ExplSyntaxOn
\NewDocumentCommand { \naiveaddtocontents } { m m }
{
\iow_shipout:ce { @auxout }
{
\token_to_str:c { @writefile } { #1 } { \text_expand:n { #2 } }
}
}
\ExplSyntaxOff
대신에 \token_to_str:c
사용할 수 있습니다\exp_not:c