`\renewcommand` 中的“嵌套太深”错误

`\renewcommand` 中的“嵌套太深”错误

我正在关注问答创建一个新的\inputminted命令。

\documentclass{article}

\usepackage{minted}                 % code highlighting, uses python pygments
\usepackage{mdframed}
\usepackage{xcolor}
\definecolor{codebg}{rgb}{0.95,0.95,0.95}

\let\inputmintedorig\inputminted    % copy original command [pack:minted]\inputminted to \inputmintedorig
\renewcommand{\inputminted}[3][]{%  % change original \inputminted
    \begin{mdframed}%
        \inputmintedorig[#1]{#2}{#3}%
    \end{mdframed}%
}

\begin{document}
\inputminted[bgcolor=codebg,mathescape,linenos,numbersep=5pt,gobble=2,frame=none,framesep=2mm,label=Some Code]{py}{pycode.py}
\end{document}

其中 pycode.py 包含一些任意的 Python 代码:

  import numpy as np    # importing library
  ls = np.arange(0, 100, 1)

但是使用更新的命令时,我收到错误“嵌套太深。...framesep=2mm,label=Some Code]{py}{pycode.py}”。我做错了什么?

答案1

这是一个众所周知的问题\let

当你询问时,\show\inputminted你会被告知

> \inputminted=macro:
->\@protected@testopt \inputminted \\inputminted {}.

执行实际工作的宏是\\inputminted(第二个反斜杠是名称的一部分。一般来说,当你有类似

\newcommand{\foo}[2][default]{something with #1 and #2}

LaTeX 内部会执行如下操作

\def\foo{\protected@testopt\foo\\foo{default}}
\def\\foo[#1]#2{something with #1 and #2}

但作为用户你不应该知道这一点。(注:我知道上面的代码并不是 LaTeX 实际上所做的,但细节完全不重要。

但你试图访问内部以重新定义\inputminted。我认为这实际上不是一个好主意。无论如何,当你想这样做时,你必须意识到其中的微妙之处。

使用您的\let,您无法访问真实的宏来完成这项工作。更糟糕的是,后续\renewcommand破坏的意思\\inputminted,所以你一使用就会进入无限循环\inputmintedorig

直到 2021 年,正确的做法是加载\usepackage{letltxmacro}并说

\LetLtxMacro{\inputmintedorig}{\inputminted}

但是现在 LaTeX 内核本身有一种方法:

\NewCommandCopy{\inputmintedorig}{\inputminted}

答案2

自行操作(如果 LaTeX 内核改变,可能会失效)

\documentclass{article}

\usepackage{minted}
\usepackage{mdframed}

\makeatletter
\expandafter\let\expandafter\inputmintedorig@internal
             \csname\string\inputminted\endcsname
\renewcommand{\inputminted}[3][]{%
\begin{mdframed}%
\inputmintedorig@internal[#1]{#2}{#3}%
\end{mdframed}%
}
\makeatother
\begin{document}
\inputminted{py}{test.py}
\end{document}

但不建议这样做,因为如果 LaTeX 内核内部发生变化,这可能会被破坏。

顺便说一句,铸造的文档没有解释如何使用自己选择的“框架”包(未经测试)。

使用专用包装方式

\documentclass{article}

\usepackage{minted}
\usepackage{mdframed}

\usepackage{letltxmacro}

\LetLtxMacro{\inputmintedorig}{\inputminted}

\renewcommand{\inputminted}[3][]{%
\begin{mdframed}%
\inputmintedorig[#1]{#2}{#3}%
\end{mdframed}%
}

\begin{document}
\inputminted{py}{test.py}
\end{document}

包裹letltxmacro就是为了完成这样的任务而创建的。

使用现代 LaTeX 方式

复制自给出答案

\NewCommandCopy{\inputmintedorig}{\inputminted}

相关内容