这是修改后的版本在类选项中使用参数时出现“未使用的全局选项”问题是如何创建一个寄生类(即加载另一个类的类),它接受特定于该类的键值选项,但不会生成有关未知选项的警告。
考虑,
\begin{filecontents}[overwrite]{\jobname.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{\jobname}
\DeclareOption{bertha}{}
\DeclareKeys[testwork]{%
test .code ={\newcommand{\foo}{#1}},
test .usage = load,
}
\ProcessKeyOptions[testwork]
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\ProcessOptions\relax
\LoadClass{article}
\endinput
\end{filecontents}
\documentclass[test=wtf,bertha]{\jobname}
\begin{document}
test \foo
\end{document}
编译此示例产生了预期的排版结果,但打印到终端和记录在日志中的消息并不像预期的那样。
LaTeX Warning: Unused global option(s):
[test].
在原始问题中,使用 创建键值选项xkeyval
。我无法弄清楚如何避免这种情况下的警告,但我希望使用内置框架声明键值选项可以更好地处理。
根据clsguide.pdf
只有寄生类未声明的选项才应传递给article
。 例如,这是正确的bertha
。 但显然, 并不正确test
。 此外,如果test=wtf
传递给article
,我希望它与其值一起传递,即我希望出现关于 的警告,test=wtf
而不是test
。
显然,我没有正确设置,但我不确定我做错了什么。到底该怎么做?
答案1
您混合了两个选项系统,这会混淆未使用列表处理的设置,因为对于每个系统,不同的选项是“未知的”并且因此未使用。
坚持使用一个系统(可以使用的系统\CurrentOption
没有\DeclareUnknownKeyHandler
记录,我们应该改变它;-))。
\begin{filecontents}[overwrite]{testoption.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{testoption}
\DeclareKeys[testwork]{%
bertha .code={},
test .code ={\newcommand{\foo}{#1}},
test .usage = load
}
\DeclareUnknownKeyHandler [testwork]
{\PassOptionsToClass{\CurrentOption}{article}}
\ProcessKeyOptions[testwork]
\LoadClass{article}
\endinput
\end{filecontents}
\documentclass[test=wtf,bertha,12pt]{testoption}
\begin{document}
test \foo
\end{document}
答案2
问题似乎在于使用\ProcessKeyOptions
和\ProcessOptions
。相反,我会使用:
\begin{filecontents}[overwrite]{\jobname.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{\jobname}
\DeclareKeys[testwork]{%
test .code ={\newcommand{\foo}{#1}},
test .usage = load,
bertha .code = {},
bertha .value_forbidden:n = true,
}
\DeclareUnknownKeyHandler[testwork]{%
\PassOptionsToClass{\CurrentOption}{article}%
}
\ProcessKeyOptions[testwork]\relax
\LoadClass{article}
\endinput
\end{filecontents}
\documentclass[test=wtf,bertha,alpha,gamma=true,12pt]{\jobname}
\begin{document}
test \foo
\end{document}
这
(/usr/local/texlive/2023/texmf-dist/tex/latex/base/size12.clo)
在log
-file 中显示,该选项12pt
已正确传递给 并被 识别article.cls
。
信息:
LaTeX Warning: Unused global option(s): [alpha,gamma].
表明两个未知选项正确地导致警告信息。
注意:对于键值选项,LaTeX 始终只将键报告为未知。这是一个功能。
附录:如果加载的类本身处理键值选项,则使用此建议也有效:
\begin{filecontents}[overwrite]{test.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{\jobname}
\DeclareKeys[testwork]{%
test .code ={\newcommand{\foo}{#1}},
test .usage = load,
bertha .code = {},
bertha .value_forbidden:n = true,
}
\DeclareUnknownKeyHandler[testwork]{%
\PassOptionsToClass{\CurrentOption}{test-base}%
}
\ProcessKeyOptions[testwork]\relax
\LoadClass{\jobname-base}
\endinput
\end{filecontents}
\begin{filecontents}[overwrite]{test-base.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{\jobname-base}
\DeclareKeys{%
gamma .code= \typeout{Gamma=`#1'},
gamma .value_required:n =true
}
\DeclareUnknownKeyHandler{%
\PassOptionsToClass{\CurrentOption}{article}
}
\ProcessKeyOptions
\LoadClass{article}
\end{filecontents}
\documentclass[test=wtf,bertha,alpha,gamma=test,gamma=,12pt]{test}
\begin{document}
test
\end{document}
这里你还可以看到, 被gamma=
传递为gamma=
从test
到test-base
。 (如果 被传递为gamma
,则会报告错误,因为gamma
需要一个值。)
答案3
编辑:第一个代码块 using\ProcessKeyOptions
并没有真正起作用,因为\ProcessKeyOptions
它会将所有未知选项添加到未使用的全局选项列表中,因此如果您使用一个已知article
但不属于您的类的选项,您将得到一个误报。下面的 using 代码块不是这种情况expkv-opt
,\ekvoProcessGlobalOptions
它只会删除,而不会添加到未使用的全局选项列表中。
编辑2:如果在第一个代码中使用unknown
处理程序,应该会得到所需的行为,但目前(2023-11-20)选项处理中存在一个错误(已报告#1183),这个问题至少会在 LaTeX 2024-06-01 之前得到修复。
我建议颠倒一下逻辑。您不必先解析类的选项,然后将未知的选项转发给article
,而是可以先加载article
整个列表,然后再解析选项。只要您的类没有定义对有效的选项,这基本上会具有相同的行为,并且您的代码不会遇到太多麻烦(请参阅中article
的文档)。未使用的选项列表仍然相同:\LoadClassWithOptions
clsguide.pdf
\begin{filecontents}[overwrite]{\jobname.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{\jobname}
\LoadClassWithOptions{article}
\DeclareKeys[testwork]{%
test .code = \newcommand{\foo}{#1},
test .usage = load,
% the following three lines give an equivalent definition of your bertha
% option as defined with `\DeclareOption{bertha}{}`
bertha .code = {},
bertha .value_forbidden:n = true,
bertha .usage = load,
# ignore unknown options to not add them to the unused options list
unknown .code = {}
}
\ProcessKeyOptions[testwork]
\endinput
\end{filecontents}
\documentclass[test=wtf,bertha]{\jobname}
\begin{document}
test \foo
\end{document}
由于我必须做广告,这是使用等效代码expkv
:
\begin{filecontents}[overwrite]{\jobname.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{\jobname}
\LoadClassWithOptions{article}
\RequirePackage{expkv-opt,expkv-def}
\ekvdefinekeys{testwork}
{%
% `store` isn't really equivalent to your newcommand-using code, that
% would've been:
% code test = \newcommand\foo{#1}
% Instead `store` is equivalent to ltkeys' `.store` handler.
store test = \foo
,noval bertha = {}
}
% if a standard class was already loaded by \LoadClassWithOptions in a parasitic
% class the unused options list is already filled, we don't need to parse local
% options any more, and only having the package's default handling of global
% options is fine.
\ekvoProcessGlobalOptions{testwork}
\endinput
\end{filecontents}
\documentclass[test=wtf,bertha]{\jobname}
\begin{document}
test \foo
\end{document}