Я пытаюсь создать пользовательский пакет, который будет содержать все мои личные макросы и пользовательский класс для моего личного стиля. Я хотел передать ключевой аргумент, 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
, и должно было быть сделано аналогичными способами здесь (что и предполагал мой комментарий).