更新

更新

如果我不使用,一切都会正常进行\PassOptionsToPackage{french}{babel}

我的文档类已经加载了 babel,然后,在我的文档类之前abntex2加载french我需要使用的语言。\PassOptionsToPackage{french}{babel}

% \PassOptionsToPackage{french}{babel}

\documentclass[english,12pt,a4paper,twoside]{abntex2}
\usepackage{caption,xpatch,listings}

\makeatletter
\tracingpatches
\newcommand{\specialcodelistingcontentsline}[1]{\contentsline{lstlisting}}

\newenvironment{code}{
  \captionsetup{type=listing}
  \xshowcmd\addcontentsline

  \xpatchcmd{\addcontentsline}
  {\contentsline}
  {\specialcodelistingcontentsline}
  {}
  {\FAILEDPATCHSPECIALCONTENTSLINE}
}{}
\makeatother
\begin{document}

\begin{code}
Hi.
\end{code}

\end{document}

在此日志上,我们可以看到修补成功:

> \addcontentsline=macro:
#1#2#3->\begingroup \let \label \@gobble \ifx \@currentHref \@empty \Hy@Warning
 {No destination for bookmark of \string \addcontentsline ,\MessageBreak destin
ation is added}\phantomsection \fi \expandafter \ifx \csname toclevel@#2\endcsn
ame \relax \begingroup \def \Hy@tempa {#1}\ifx \Hy@tempa \Hy@bookmarkstype \Hy@
WarningNoLine {bookmark level for unknown #2 defaults to 0}\else \Hy@Info {book
mark level for unknown #2 defaults to 0}\fi \endgroup \expandafter \gdef \csnam
e toclevel@#2\endcsname {0}\fi \edef \Hy@toclevel {\csname toclevel@#2\endcsnam
e }\Hy@writebookmark {\csname the#2\endcsname }{#3}{\@currentHref }{\Hy@tocleve
l }{#1}\ifHy@verbose \begingroup \def \Hy@tempa {#3}\@onelevel@sanitize \Hy@tem
pa \let \temp@online \on@line \let \on@line \@empty \Hy@Info {bookmark\temp@onl
ine :\MessageBreak thecounter {\csname the#2\endcsname }\MessageBreak text {\Hy
@tempa }\MessageBreak reference {\@currentHref }\MessageBreak toclevel {\Hy@toc
level }\MessageBreak type {#1}}\endgroup \fi \addtocontents {#1}{\protect \cont
entsline {#2}{#3}{\thepage }{\@currentHref }}\endgroup .
<recently read> \addcontentsline

l.23 \begin{code}

?
[debug] tracing \patchcmd on input line 23
[debug] analyzing '\addcontentsline'
[debug] ++ control sequence is defined
[debug] ++ control sequence is a macro
[debug] ++ macro can be retokenized cleanly
[debug] ++ search pattern found in replacement text
[debug] ++ patching possible
[debug] == retokenizing macro now

但是,在取消注释\PassOptionsToPackage{french}{babel}最小示例后,补丁将失败:

> \addcontentsline=macro:
#1#2#3->\begingroup \let \label \@gobble \ifx \@currentHref \@empty \Hy@Warning
 {No destination for bookmark of \string \addcontentsline ,\MessageBreak destin
ation is added}\phantomsection \fi \expandafter \ifx \csname toclevel@#2\endcsn
ame \relax \begingroup \def \Hy@tempa {#1}\ifx \Hy@tempa \Hy@bookmarkstype \Hy@
WarningNoLine {bookmark level for unknown #2 defaults to 0}\else \Hy@Info {book
mark level for unknown #2 defaults to 0}\fi \endgroup \expandafter \gdef \csnam
e toclevel@#2\endcsname {0}\fi \edef \Hy@toclevel {\csname toclevel@#2\endcsnam
e }\Hy@writebookmark {\csname the#2\endcsname }{#3}{\@currentHref }{\Hy@tocleve
l }{#1}\ifHy@verbose \begingroup \def \Hy@tempa {#3}\@onelevel@sanitize \Hy@tem
pa \let \temp@online \on@line \let \on@line \@empty \Hy@Info {bookmark\temp@onl
ine :\MessageBreak thecounter {\csname the#2\endcsname }\MessageBreak text {\Hy
@tempa }\MessageBreak reference {\@currentHref }\MessageBreak toclevel {\Hy@toc
level }\MessageBreak type {#1}}\endgroup \fi \addtocontents {#1}{\protect \cont
entsline {#2}{#3}{\thepage }{\@currentHref }}\endgroup .
<recently read> \addcontentsline

l.23 \begin{code}

?
[debug] tracing \patchcmd on input line 23
[debug] analyzing '\addcontentsline'
[debug] ++ control sequence is defined
[debug] ++ control sequence is a macro
[debug] -- macro cannot be retokenized cleanly
[debug] -> the macro may have been defined under a category
[debug]    code regime different from the current one
[debug] -> the replacement text may contain special control
[debug]    sequence tokens formed with \csname...\endcsname;
[debug] -> the replacement text may contain carriage return,
[debug]    newline, or similar characters
! Undefined control sequence.
<argument> \FAILEDPATCHSPECIALCONTENTSLINE

更新

正如@Phelype Oleinikcatcode,将临时更改:为 12 解决了该问题。但是,我无法正确恢复catcode

以下操作不起作用,因为我曾经\begingroup恢复过catcode,但它也会恢复/取消我刚刚对\addcontentlines

\PassOptionsToPackage{french}{babel}
\documentclass[english,12pt,a4paper,twoside]{abntex2}
\usepackage{caption,xpatch,listings}

\makeatletter
\tracingpatches
\newcommand{\specialcodelistingcontentsline}[1]{\contentsline{lstlisting}}

\newenvironment{code}{
  \captionsetup{type=listing}
  \xshowcmd\addcontentsline

  \begingroup
    \catcode`\:=12
    \xpatchcmd{\addcontentsline}
    {\contentsline}
    {\specialcodelistingcontentsline}
    {}
    {\FAILEDPATCHSPECIALCONTENTSLINE}
  \endgroup
  % Here the catcode is restored, however, my patch is also undone
}{}
\makeatother
\begin{document}
\begin{code}
Hi.
\end{code}
\end{document}

有关的:

  1. 暂时更改 % 的 catcode
  2. 活动字符和分隔参数

答案1

在找到另一个答案之后保存并恢复 makeatletter/makeatother 状态,我设法catcode用这个设置和恢复冒号:

\PassOptionsToPackage{french}{babel}
\documentclass[english,12pt,a4paper,twoside]{abntex2}
\usepackage{caption,xpatch,listings}
\makeatletter
\tracingpatches
\newcommand{\specialcodelistingcontentsline}[1]{\contentsline{lstlisting}}

\newenvironment{code}{
  \captionsetup{type=listing}
  \def\makesafecoloncatcoderestore##1{%
      \edef##1{\catcode`:=\the\catcode`:\relax}%
  }
  \makesafecoloncatcoderestore\restorecodecoloncatcode
  \catcode`\:=12
  \xpatchcmd{\addcontentsline}
  {\contentsline}
  {\specialcodelistingcontentsline}
  {\message{^^J^^JCould YES patch the contentsline environment!^^J^^J^^J^^J^^J^^J}}
  {\FAILEDPATCHSPECIALCONTENTSLINE}
  % \xshowcmd\addcontentsline
  \restorecodecoloncatcode
}{}

\makeatother
\begin{document}
\begin{code}
Hi.
\end{code}
\end{document}

有关的:

  1. 暂时更改 % 的 catcode
  2. 活动字符和分隔参数
  3. 如果使用 \PassOptionsToPackage{french}{babel},则 \xpatch 会失败

相关内容