命令已定义

命令已定义

我在编译 LaTeX 时遇到了一个奇怪的问题exam.cls文件制作knitr。下面粘贴的是最少的可重现代码。

knitr编译正常,但pdflatex终止于:

  • 命令\framed已定义。
  • 命令\shaded已定义。
  • 命令\leftbox已定义。

似乎的作者exam.cls将大部分 framed.sty 粘贴到了类文件中,这会与任何实际想要加载原始framed.sty包的人(包括)产生冲突knitr

我对这个丑陋问题的丑陋解决方案是修改exam.cls文件:

% Original
\newenvironment{framed}% using default \FrameCommand
  {\MakeFramed {\advance\hsize-\width \FrameRestore}}%
  {\endMakeFramed}

% Modified
\newenvironment{exam-framed}% using default \FrameCommand
  {\MakeFramed {\advance\hsize-\width \FrameRestore}}%
  {\endMakeFramed}

% Same for "\newenvironment{shaded}" and "\newenvironment{leftbar}"

我想找到更优雅的解决方案,而不是重写原始exam.cls文件。

提前感谢任何指点。

答案1

重命名使用\let

名称冲突可以通过重命名来解决。在这种情况下,这些是简单环境。一个环境name定义了两个宏\name\endname(后者也可以不定义,因为它是通过调用的\csname)。

\documentclass{exam}
\newcommand*{\renameenviron}[1]{%
  \expandafter\let\csname exam-#1\expandafter\endcsname
      \csname #1\endcsname
  \expandafter\let\csname endexam-#1\expandafter\endcsname
      \csname end#1\endcsname
  \expandafter\let\csname #1\endcsname\relax
  \expandafter\let\csname end#1\endcsname\relax
}
\renameenviron{framed}
\renameenviron{shaded}
\renameenviron{leftbar}
\usepackage{framed}
\begin{document}
\end{document}

但是这种方法会用包的原始代码framed覆盖的内部内容,请参阅下面的进一步讨论。examframed

模拟包加载

班级exam说:

% Donald Arseneau <...>, who created the excellent
% ``framed.sty'' and generously allowed me to include basically the
% whole thing in exam.cls, making the few changes needed for it to
% work well with question environments:
% framed.sty   v 0.8a   21-Jul-2003
% Copyright (C) 1992-2003 by Donald Arseneau
% These macros may be freely transmitted, reproduced, or modified
% provided that this notice is left intact.

这可能意味着,framed已经加载了。加载两次可能没有意义。然后 LaTeX 可能会被欺骗,认为包已经加载:

\documentclass{exam}
\makeatletter
\expandafter\providecommand\expandafter*\csname [email protected]\endcsname
{2003/07/21 v0.8a Simulated by exam}
\makeatother
\usepackage{framed}
\begin{document}
\end{document}

长话短说

framed上述两种方法都没有解决类中的实现exam与原始的相比发生了哪些变化的问题framed。环境是一方面,内部内容是另一方面。例如,使用 定义内部宏\def不会产生错误,如果宏已经定义。在第一种方法中,后加载的包framed将覆盖类的内部内容。在第二种方法中,使用类中exam的版本。framedexam

第一种方法的优点:使用最新的版本,framed包括错误修复和新功能(如果有的话)。缺点是,更改exam会丢失(快速查看会发现一些边距和定位内容)。因此,第二种方法可能更好。

如果您很幸运,第二种方法已经适用于您的文档。

否则,可能knitr需要 的更高版本framed或需要未修改的framed。这些情况会造成大量工作,因为需要分析不同版本的宏之间的差异并进行合并或提供不同的环境。

答案2

3 分钟前我也遇到了这个问题!用 Google 搜索答案后我立即找到了这个页面 - 谢谢大家花时间 - 非常有帮助,非常感谢!

我使用该类的 LaTeX 代码exam使用 MiKTeX/texstudio 编译得非常好,但正如问题所示,将此代码复制到文档中.Rnw并编织它,即编译 PDF 导致了问题中详述的完全相同的问题 - 同样的 3 个错误。

我查看了这里提供的答案,但如果我的理解准确的话,似乎我需要编辑exam.cls- 不确定是否要这样做 - 如果更新了怎么办?那么每次我都需要再次编辑它吗?

相反,我使用了该软件包的作者 YiHui Xie 建议的解决方案,knitr并且效果很好:

复制自https://groups.google.com/forum/#!topic/knitr/sNZyM4Y3ETk

“... 另一个解决方案是使用 listing 包,将如下块放入您的文档中:

<<setup, include=FALSE>>=
render_listings()
@

在大多数情况下,该listings软件包更加强大。framed包装相当脆弱。...”

我确实这么做了:

\begin{document}
<<setup, include=FALSE>>=
render_listings()
@ 

我的文档的其余部分与之前一样。编译时没有任何错误!

如果我注释掉这一块,我会得到与@An​​drej 完全相同的错误

Command \framed already defined.
Command \shaded already defined.
Command \leftbox already defined.

相关内容