我在编译 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
覆盖的内部内容,请参阅下面的进一步讨论。exam
framed
模拟包加载
班级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
的版本。framed
exam
第一种方法的优点:使用最新的版本,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()
@
我的文档的其余部分与之前一样。编译时没有任何错误!
如果我注释掉这一块,我会得到与@Andrej 完全相同的错误
Command \framed already defined.
Command \shaded already defined.
Command \leftbox already defined.