![\xpatchcmd 在更复杂的命令中失败](https://linux22.com/image/316567/%5Cxpatchcmd%20%E5%9C%A8%E6%9B%B4%E5%A4%8D%E6%9D%82%E7%9A%84%E5%91%BD%E4%BB%A4%E4%B8%AD%E5%A4%B1%E8%B4%A5.png)
我尝试修补该命令以在使用\minitoc@
后添加一些额外的垂直间距。(这是由\mtctitle
调整 minitoc 标题和内容之间的垂直间距)
然而,无论是完整包含部分\if...
还是内部分支都无法修补。
为了回答上面链接的问题,我使用了原始命令\minitoc@
,从包中复制它minitoc
并在相关位置更改了代码,但这并不令人满意。
目前,我无法弄清楚修补为何会失败。据我所知,其中\minitoc@
包含有效代码,没有定义任何未来命令,因此修补将不起作用。
以下是补丁和完整的“MWE”
\documentclass{book}
\usepackage{minitoc}
\usepackage{xpatch}
\newlength{\mymtcaftertitleskip}
\setlength{\mymtcaftertitleskip}{2ex} % For example
\nomtcrule
\makeatletter
\xpatchcmd{\minitoc@}{%
\begin{tabular}{@{}p{\columnwidth}@{}}
\reset@font\mtifont\do@mtitc{\mtc@v\mtctitle}\\
\end{tabular}%
}{%
\begin{tabular}{@{}p{\columnwidth}@{}}
\reset@font\mtifont\do@mtitc{\mtc@v\mtctitle}\\[\mymtcaftertitleskip]%
\end{tabular}%
}{\typeout{Patch success}}{\typeout{Patch failed}}
% Here is the original definition, renamed from \minitoc to \origminitoc etc, just for comparison -- it's not used in here.
\def\origminitoc{\@ifnextchar[{\origminitoc@}{\origminitoc@[d]}}
\def\origminitoc@[#1]{%
\global\@minitoc@used@true
\if@mtc@longext@
\def\@tocfile{mtc\The@mtc}%
\else
\def\@tocfile{M\The@mtc}%
\fi
\mtc@CkFile{\jobname.\@tocfile}
\if@mtc@FE
\mtcPackageInfo[I0006]{minitoc}%
{\jobname.\@tocfile\space is empty}
\@mtc@empty@minitoc@true
\else
\thispageminitocstyle
%% \mtc@markboth{\MakeUppercase{\mtctitle}}{\MakeUppercase{\mtctitle}}%
\beforeminitoc
\relax\begin{samepage}%
\if #1e\let\do@mtitc\e@mti
\else\if #1n\let\do@mtitc\n@mti
\else\if #1c\let\do@mtitc\c@mti
\else\if #1l\let\do@mtitc\l@mti
\else\if #1r\let\do@mtitc\r@mti
\else\if #1d\let\do@mtitc\df@mtitc
\fi\fi\fi\fi\fi\fi
\mtc@CkStr{\mtctitle}\if@mtc@FE \let\do@mtitc\e@mti\relax\fi
\raggedright
\parskip=\z@%
\reset@font\mtcfont%
\parindent=\z@%
\nopagebreak[4]%
\kern-0.8\baselineskip\nopagebreak[4]%
\par\noindent %%
\ifx\mtc@rule\relax
\begin{tabular}{@{}p{\columnwidth}@{}}
\reset@font\mtifont\do@mtitc{\mtc@v\mtctitle}\\
\end{tabular}%
\else
\begin{tabular}{@{}p{\columnwidth}@{}}
\reset@font\mtifont\do@mtitc{\mtc@v\mtctitle}\\\hline
\end{tabular}%
\fi
\nopagebreak[4]\null\leavevmode\mtc@zrule\\\mtc@BBR
\leftmargin\mtcindent \rightmargin\mtcindent
\itemindent=\z@\labelwidth=\z@%
\labelsep=\z@\listparindent=\z@%
\begin{mtc@verse}{\mtcoffset}%
\c@tocdepth=\c@minitocdepth
\leavevmode\\\mtc@BBR\vskip -.5\baselineskip
\begingroup
\makeatletter
\@ifundefined{mtc@pgno}%
{\let\@dottedtocline\@undottedtocline}{}
\@fileswfalse\mtc@hook@beforeinputfile
\mtc@setform%
\openminitoc \global\inminitoctrue
\@input{\jobname.\@tocfile}%
\global\inminitocfalse\closeminitoc
\vspace{-1ex} \vspace{-\baselineskip}
\leavevmode\mtc@strut
\global\@nobreakfalse\endgroup
\end{mtc@verse}%
\kernafterminitoc
\nopagebreak[4]\mtc@bottom@rule\null\leavevmode\\%
\vskip-1.0\baselineskip\mtc@zrule\end{samepage}%
\par\pagebreak[1]\vspace*{-1ex}\afterminitoc\fi}
\makeatother
\begin{document}
\dominitoc
\faketableofcontents
\chapter{Minimum}
\minitoc
\section{Working}
\section{Example}
\end{document}
答案1
您正在修补错误的命令。在 的定义之后\minitoc@
,包minitoc
会将其保存在 中,并在不可用时\sv@minitoc@
更改 的定义以\minitoc@
添加内容:\chapter
\@ifundefined{chapter}{}{%
\let\sv@minitoc@\minitoc@
\def\minitoc@[#1]{{\ifundottedmtc\let\@dottedtocline\@Undottedtoclinep\fi
\sv@minitoc@[#1]}}%
与 一起使用时\sv@minitoc@
,\xpatchcmd
成功。
答案2
如果我这样做\show\minitoc@
,我就会明白
> \minitoc@=macro:
[#1]->{\ifundottedmtc \let \@dottedtocline \@Undottedtoclinep \fi \sv@minitoc@ [#1]}.
这意味着提议的补丁无法成功。你被这个包对 有不同的定义误导了\minitoc@
,但后来它说
\@ifundefined{chapter}{}{%
\let\sv@minitoc@\minitoc@
\def\minitoc@[#1]{{\ifundottedmtc\let\@dottedtocline\@Undottedtoclinep\fi
\sv@minitoc@[#1]}}%
\let\sv@minilof@\minilof@
\def\minilof@[#1]{{\ifundottedmtc\let\@dottedtocline\@Undottedtoclinep\fi
\sv@minilof@[#1]}}%
\let\sv@minilot@\minilot@
\def\minilot@[#1]{{\ifundottedmtc\let\@dottedtocline\@Undottedtoclinep\fi
\sv@minilot@[#1]}}}
因此,\minitoc@
如果定义了,则保留该定义\chapter
,否则,它会将其更改并保存在中\sv@minitoc@
。