我正在尝试制作一个自定义包来包含我所有的个人宏和一个适合我个人风格的自定义类。我想传递一个关键字参数,该参数可以取或notation
的值,以便更改我所学不同课程的符号(例如,在数学中,复共轭通常用横线表示,而在物理学中则用星号表示)。经过反复尝试并遵循答案后,我得到了math
physics
这里。我得到了以下 3 个文件:
% demo-pkg.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{demo-pkg}[Demo]
\RequirePackage{xstring}
\DeclareKeys[demo]
{
notation.choices:nn =
{ physics, math }
{\ExpandArgs{Nc}\let\@demo@notation{l_keys_choice_tl}},
notation.usage = load,
notation.initial:n = physics
}
\ProcessKeyOptions[demo]
\IfStrEqCase{\@demo@notation}{
{physics}{}%
{math}{}%
}[
\PackageError{demo-pkg}{Invalid notation value: \@demo@notation}
{Choose value of: physics, math}
]
\RequirePackage{xparse}
\IfStrEqCase{\@demo@notation}{%
{physics}{%
\NewDocumentCommand{\Conjugate}{ m }{{##1}^{\ast}}%
}%
{math}{%
\NewDocumentCommand{\Conjugate}{ m }{\overline{##1}}%
}%
}%
% demo-cls.cls
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{demo-cls}[Demo class]
\DeclareKeys[demo-cls]
{
notation.choices:nn =
{ physics, math }
{\PassOptionsToPackage{notation=l_keys_choice_tl}{demo-pkg}}, % <- This seems to cause issues
notation.usage = load,
notation.initial:n = physics
}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\ProcessKeyOptions[demo-cls]
\ProcessOptions\relax
\LoadClass[a4paper, 12pt]{article}
\RequirePackage{demo-pkg}
% main.tex
\documentclass[notation=math]{demo-cls}
\begin{document}
\[ z = x + iy \Longleftrightarrow \Conjugate{z} = x - iy \]
\end{document}
尝试编译此代码时出现错误Key 'demo/notation' accepts only a fixed set of choices.
。当我demo-pkg
直接使用时:
\documentclass{article}
\usepackage[notation=math]{demo-pkg}
\begin{document}
\[ z = x + iy \Longleftrightarrow \Conjugate{z} = x - iy \]
\end{document}
它可以正常编译,我可以使用包参数切换符号。将参数从类传递到包似乎会导致问题。我尝试使用\l_keys_choice_tl
,并用/\tl_use:N \l_keys_choice_tl
包围此代码块。没有任何效果。我得到了同样的错误。我如何将参数从类传递到包?\ExplSyntaxOn
\ExplSyntaxOff
notation
demo-cls
demo-pkg
答案1
您不必将notation=math
from转发\documentclass
到您的包。包使用\ProcessKeyOptions
,因此会解析包含该选项的全局选项列表。
并且您可以\ProcessKeyOptions
在类中使用机制将未知选项转发给article
。因此唯一需要更改的文件是您的类:
demo-cls.cls
:
% demo-cls.cls
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{demo-cls}[Demo class]
\DeclareKeys[demo-cls]
{
unknown .code = \PassOptionsToClass{\CurrentOption}{article}
}
\ProcessKeyOptions[demo-cls]
\LoadClass[a4paper, 12pt]{article}
\RequirePackage{demo-pkg}
demo-pkg.sty
:
% demo-pkg.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{demo-pkg}[Demo]
\RequirePackage{xstring}
\DeclareKeys[demo]
{
notation.choices:nn =
{ physics, math }
{\ExpandArgs{Nc}\let\@demo@notation{l_keys_choice_tl}},
notation.usage = load,
notation.initial:n = physics
}
\ProcessKeyOptions[demo]
\IfStrEqCase{\@demo@notation}{
{physics}{}%
{math}{}%
}[
\PackageError{demo-pkg}{Invalid notation value: \@demo@notation}
{Choose value of: physics, math}
]
\RequirePackage{xparse}
\IfStrEqCase{\@demo@notation}{%
{physics}{%
\NewDocumentCommand{\Conjugate}{ m }{{##1}^{\ast}}%
}%
{math}{%
\NewDocumentCommand{\Conjugate}{ m }{\overline{##1}}%
}%
}%
main.tex
:
% main.tex
\documentclass[notation=math]{demo-cls}
\begin{document}
\[ z = x + iy \Longleftrightarrow \Conjugate{z} = x - iy \]
\end{document}
我想需要做一点解释(也回顾一下我之前的回答):
\ExpandArgs
是一个宏,它提供了一个高级接口来精细控制参数扩展。我使用它来将你的包内部设置\@demo@notation
为 L3 变量的值,而无需直接使用 L3 语言(因此无需\ExplSyntaxOn
或\ProvidesExplPackage
)。这是通过使用完成的\ExpandArgs{Nc}\let\@demo@notation{l_keys_choice_tl}
,这意味着:在使用之前\let
使用两个参数,第一个是一个未更改的单个标记(N
),第二个是一个应该通过形成宏的支撑组\csname
。因此\ExpandArgs{Nc}\let\@demo@notation{l_keys_choice_tl}
是这种低级构造的更易读的变体:
\expandafter\let\expandafter\@demo@notation\csname l_keys_choice_tl\endcsname
我希望这个解释有助于解释为什么你的
\DeclareKeys[demo-cls]
{
notation.choices:nn =
{ physics, math }
{\PassOptionsToPackage{notation=l_keys_choice_tl}{demo-pkg}}, % <- This seems to cause issues
notation.usage = load,
notation.initial:n = physics
}
没用。因为l_keys_choice_tl
不会神奇地变成真正的选择值,这是由 完成的\ExpandArgs
,并且应该在这里通过类似的方式完成(这是我的评论建议的)。