![`\renewcommand` 中的“嵌套太深”错误](https://linux22.com/image/464928/%60%5Crenewcommand%60%20%E4%B8%AD%E7%9A%84%E2%80%9C%E5%B5%8C%E5%A5%97%E5%A4%AA%E6%B7%B1%E2%80%9D%E9%94%99%E8%AF%AF.png)
我正在关注问答创建一个新的\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}