我查看了一些相关问题但无法解决这个问题。
我有一个通用的 LaTeX 文件,我将这个geometry
包加载到其中。
此文件(pre.tex
此处称为)是加载许多包的通用站点范围文件。这些选项适用于站点上的几乎所有文件,但有时一个文件需要不同的几何选项。
因此我想在输入这个常见的 LaTeX 文件后更改几何设置。
我正在回答卸载 LaTeX 包但它给了我一个错误。这是一个 MWE:
\documentclass[11pt,titlepage]{article}%
\makeatletter
\@namedef{geometry.sty}{}% a fake for a "loaded" package
\makeatother
\input{pre} %this has in it \usepackage{geometry} with some options
% I want to override common file and load geometry
% with different options here
\usepackage[letterpaper,bindingoffset=0.2in,
left=1.2in,right=1.2in,top=.8in,bottom=.8in,
footskip=.25in]{geometry}
\begin{document}
test
\end{document}
pre.tex
刚刚那条线在哪里
\usepackage[letterpaper,bindingoffset=0.2in,left=2in,right=2in]{geometry}
错误lualatex file.tex
来自
(/usr/local/texlive/2018/texmf-dist/tex/generic/ifxetex/ifxetex.sty))
! LaTeX Error: Option clash for package geometry.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.12
?
奇怪的是,这个可以工作并且可以编译
\documentclass[11pt,titlepage]{article}%
\makeatletter
\@namedef{geometry.sty}{}% a fake for a "loaded" package
\makeatother
\input{pre} %this has in it \usepackage{geometry}
\usepackage{geometry}
\begin{document}
test
\end{document}
所以只有当我想使用geometry
与原始加载不同的选项再次加载时才会失败?
geometry
一旦加载,包括加载时使用的任何选项,正确的删除方法是什么,以便如果特定文件想要使用不同的选项,他们可以使用不同的选项重新加载几何图形?
使用 TL 2018
答案1
很可能总是欺骗 LaTeX 允许你加载包两次不是一个好主意。即使你设法通过取消定义来实现这一点(我不会展示如何实现——虽然这很容易——这样人们就不会责怪我教这个 :),你也会得到一长串其他错误,例如\[email protected]
! LaTeX Error: Command \Gm@vrules@mpi already defined.
Or name \end... illegal, see p.192 of the manual.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.927 \llap{\Gm@vrule}\hfil\Gm@vrule}}
%
?
因为包不应该被加载两次,所以他们使用\newcommand
,我们都知道这不会起作用两次。
也就是说,对于这种几何情况,您可以将选项传递给命令\geometry
:
\geometry{letterpaper,bindingoffset=0.2in,
left=1.2in,right=1.2in,top=.8in,bottom=.8in,
footskip=.25in}
来自手册:
\geometry{<options>}
根据参数中指定的选项更改页面布局。此命令(如果有)应仅放置在前言中(之前\begin{document}
)。几何包可以用作类的一部分或您在文档中使用的另一个包。该命令
\geometry
可以覆盖序言中的某些设置。允许多次使用\geometry
,然后使用连接的选项进行处理。如果几何尚未加载,则只能使用而\usepackage[<options>]{geometry}
不是\geometry
。
对于更一般的情况,我建议将您的代码变成pre.tex
一个包pre.sty
并向其中添加一些选项。例如,这是我在编写的一个类中所做的,该类具有预定义值但允许用户覆盖它们:
\RequirePackage{filecontents}
\begin{filecontents}{pre.sty}
\ProvidesPackage{pre}[2018-09-17 Nasser's geometry package]
% I'm using kvoptions, but you can adapt to your favorite keyval package
\RequirePackage{kvoptions}
% First pass options -- Here only the "interface" option will be declared
\SetupKeyvalOptions{%
family=nasser@first,%
prefix=nasser@@%
}
% Create the interface option
\DeclareStringOption{interface}
% Temporarily redefine \KV@errx to allow "undefined" options
\let\nasser@KVerr\KV@errx
\let\KV@errx\@gobble
% Process the interface option. Every other option is left untouched
\ProcessLocalKeyvalOptions{nasser@first}
\let\KV@errx\nasser@KVerr% Restore \KV@errx
% Now we can set the main option list of the package
\SetupKeyvalOptions{%
family=nasser@main,%
prefix=nasser@% Different prefix than before!
}
% Create a dummy interface option just to satisfy the option parser -- won't be used anywhere
\DeclareStringOption{interface}
% By now we have \nasser@@interface, a comma-separated list of package names
% Then, for each <package>, we create an option <package> and another force<package>
\@for\pkg:=\nasser@@interface\do{% (notice that for interface, the prefix is nasser@@ -- two @s)
\DeclareStringOption{\pkg}% Soft option
\DeclareStringOption{force\pkg}% Hard option
}%
% Now the user has passed the options and we can
\ProcessKeyvalOptions{nasser@main}
% Now the fun part begins :)
% We have three option lists to pass for a package:
% - The "soft" option from the interface;
% - The package default and;
% - The "hard" option from the interface
% and we are going to pass them in that order to respect their hierarchy
% First, the soft options which, if in conflict with the package defaults, are overridden
\@for\pkg:=\nasser@@interface\do{% Loop through every interface'd package
\expandafter\ifx\csname nasser@\pkg\endcsname\relax% If the option wasn't used do nothing
\else% else
\expandafter\PassOptionsToPackage\expandafter{% \PassOptionsToPackage
\csname nasser@\pkg\endcsname}% {soft,option,list}
{\pkg}% {package}
\fi
}
% Now we insert the package defaults
\PassOptionsToPackage{letterpaper,bindingoffset=0.2in,left=2in,right=2in}{geometry}
% And finally, the hard options which can override package defaults
\@for\pkg:=\nasser@@interface\do{% Loop through every interface'd package
\expandafter\ifx\csname nasser@force\pkg\endcsname\relax% If the option wasn't used do nothing
\else% else
\expandafter\PassOptionsToPackage\expandafter{% \PassOptionsToPackage
\csname nasser@force\pkg\endcsname}% {hard,option,list}
{\pkg}% {package}
\fi
}
% And finally load the package
\RequirePackage{geometry}
\endinput
\end{filecontents}
\documentclass[11pt,titlepage]{article}
\usepackage[%
interface=geometry,%
forcegeometry={%
letterpaper,bindingoffset=0.2in,%
left=1.2in,right=1.2in,top=.8in,bottom=.8in,%
footskip=.25in%
}%
]{pre}
% With \usepackage{pre}
% * h-part:(L,W,R)=(144.54pt, 310.76125pt, 144.54pt)
% * v-part:(T,H,B)=(95.39737pt, 556.47656pt, 143.09605pt)
% With \geometry
% * h-part:(L,W,R)=(86.72377pt, 426.39369pt, 86.72377pt)
% * v-part:(T,H,B)=(57.81621pt, 679.33757pt, 57.81621pt)
% With geometry option
% * h-part:(L,W,R)=(144.54pt, 310.76125pt, 144.54pt)
% * v-part:(T,H,B)=(57.81621pt, 679.33757pt, 57.81621pt)
% With forcegeometry option
% * h-part:(L,W,R)=(86.72377pt, 426.39369pt, 86.72377pt)
% * v-part:(T,H,B)=(57.81621pt, 679.33757pt, 57.81621pt)
\geometry{verbose}% Just to show settings in the log
\begin{document}
test
\end{document}
基本上,这会设置包加载,以便包中每个包都有一个默认选项列表,用户可以将尊重包默认值的附加选项传递给该包,并且还可以覆盖这些默认值(如果他们明确要求的话)。
代码很长,因为它允许与任意数量的包交互,并允许这种三级层次结构。但对于你的情况,只有一个包,没有层次结构(即任何选项都会覆盖包的默认值),它可以简化为:
\RequirePackage{filecontents}
\begin{filecontents}{pre.sty}
\ProvidesPackage{pre}[2018-09-17 Nasser's geometry package]
% I'm using kvoptions, but you can adapt to your favorite keyval package
\RequirePackage{kvoptions}
% Define the family and prefix for the options
\SetupKeyvalOptions{%
family=nasser,%
prefix=nasser@%
}%
% Decalre a "geometry" option
\DeclareStringOption{geometry}
% Process input option list
\ProcessKeyvalOptions*
% Now we insert the package defaults
\PassOptionsToPackage{letterpaper,bindingoffset=0.2in,left=2in,right=2in}{geometry}
% Then pass the package options to geometry
\PassOptionsToPackage{\nasser@geometry}{geometry}
% And finally load the package
\RequirePackage{geometry}
\endinput
\end{filecontents}
\documentclass[11pt,titlepage]{article}
\usepackage[%
geometry={%
letterpaper,bindingoffset=0.2in,%
left=1.2in,right=1.2in,top=.8in,bottom=.8in,%
footskip=.25in%
}%
]{pre}
% With \usepackage{pre}
% * h-part:(L,W,R)=(144.54pt, 310.76125pt, 144.54pt)
% * v-part:(T,H,B)=(95.39737pt, 556.47656pt, 143.09605pt)
% With \geometry
% * h-part:(L,W,R)=(86.72377pt, 426.39369pt, 86.72377pt)
% * v-part:(T,H,B)=(57.81621pt, 679.33757pt, 57.81621pt)
% With geometry option
% * h-part:(L,W,R)=(86.72377pt, 426.39369pt, 86.72377pt)
% * v-part:(T,H,B)=(57.81621pt, 679.33757pt, 57.81621pt)
% \geometry{letterpaper,bindingoffset=0.2in,
% left=1.2in,right=1.2in,top=.8in,bottom=.8in,
% footskip=.25in}
\geometry{verbose}% Just to show settings in the log
\begin{document}
test
\end{document}