Я пытаюсь написать свой собственный пакет теорем, который оборачивает кучу функций, чтобы упорядочить мою стандартную преамбулу. При этом я застрял со следующей проблемой: я пытаюсь создать функцию для определения новой среды, похожей на теорему, и соответствующих cleveref
имен — и то, и другое в одном методе одним вызовом. Однако по какой-то причине я не могу заставить это работать.
Ниже приведен минимальный пример с двумя подходами: первый — это то, что я бы сделал естественным образом, во втором я пытаюсь использовать синтаксис latex3, в котором я в настоящее время пишу более широкий пакет (то есть: я полагаю, что для этой проблемы это кажется немного излишним, но я все равно включил его, потому что это ближе к моему реальному варианту использования).
\documentclass{article}
\usepackage{cleveref}
\begin{document}
% Version A
\NewDocumentCommand{\myfooA}{m m m m}{
\newtheorem{#1}{#2}
\Crefname{#1}{#3}{#4}
}
% Version B
\ExplSyntaxOn
\NewDocumentCommand{\myfooB}{m m m m}{
\newtheorem{#1}{#2}
\tl_set:Nn \l_crefname_tl {#1}
\tl_set:Nn \l_name_tl {#3}
\tl_set:Nn \l_names_tl {#4}
\cs_set:Npn \l_mycrefname_cs ##1##2##3 {\Crefname{##1}{##2}{##3}}
\exp_args:Nooo \l_mycrefname_cs \l_crefname_tl \l_name_tl \l_names_tl
}
\ExplSyntaxOff
% Test Version A
\myfooA{defA}{Definition}{Definition A}{Definitions A}
\begin{defA}\label{defA}
Some Definition A
\end{defA}
\Cref{defA}
% Test Version B
\myfooB{defB}{Definition}{Definition B}{Definitions B}
\begin{defB}\label{defB}
Some Definition B
\end{defB}
\Cref{defB}
\end{document}
В обоих случаях я получаю сообщение об ошибке:
LaTeX: Cref reference format for label type `defA' undefined.
соответственно то же самое для \defB
.
Кто-нибудь из вас знает, что здесь происходит, и что я делаю неправильно?
решение1
Обе ваши команды работают при условии, что они определены и вызваны в преамбуле документа.
\documentclass{article}
\usepackage{cleveref}
\NewDocumentCommand{\myfooA}{m m m m}{
\newtheorem{#1}{#2}
\Crefname{#1}{#3}{#4}
}
% Version B
\ExplSyntaxOn
\NewDocumentCommand{\myfooB}{m m m m}{
\newtheorem{#1}{#2}
\tl_set:Nn \l_crefname_tl {#1}
\tl_set:Nn \l_name_tl {#3}
\tl_set:Nn \l_names_tl {#4}
\cs_set:Npn \l_mycrefname_cs ##1##2##3 {\Crefname{##1}{##2}{##3}}
\exp_args:Nooo \l_mycrefname_cs \l_crefname_tl \l_name_tl \l_names_tl
}
\ExplSyntaxOff
\myfooA{defA}{Definition}{Definition A}{Definitions A}
\myfooB{defB}{Definition}{Definition B}{Definitions B}
\begin{document}
% Version A
% Test Version A
\begin{defA}\label{defA}
Some Definition A
\end{defA}
\Cref{defA}
% Test Version B
\begin{defB}\label{defB}
Some Definition B
\end{defB}
\Cref{defB}
\end{document}
решение2
Код для определения сред, подобных теоремам, следует поместить в преамбулу, поскольку это «глобальная» настройка.
Код expl3
, который вы используете, плох в нескольких местах. Вот очищенная версия.
\ExplSyntaxOn
\NewDocumentCommand{\definetheorem}{m m m m}
{
\newtheorem{#1}{#2}
\uzername_crefname:nnn { #1 } { #3 } { #4 }
}
\tl_new:N \l_uzername_crefname_tl
\tl_new:N \l_uzername_name_tl
\tl_new:N \l_uzername_names_tl
\cs_new_protected:Npn \uzername_crefname_make:nnn {} % initialize
\cs_generate_variant:Nn \uzername_crefname_make:nnn { VVV }
\cs_new_protected:Npn \uzername_crefname:nnn #1#2#3
% alternative, using signature instead of parameter text:
% \cs_new_protected:Nn \uzername_crefname:nnn
{
\tl_set:Nn \l_uzername_crefname_tl {#1}
\tl_set:Nn \l_uzername_name_tl {#2}
\tl_set:Nn \l_uzername_names_tl {#3}
\cs_set_protected:Npn \uzername_crefname_make:nnn ##1##2##3 {\Crefname{##1}{##2}{##3}}
\uzername_crefname_make:VVV \l_uzername_crefname_tl \l_uzername_name_tl \l_uzername_names_tl
}
\ExplSyntaxOff
Хотя я не понимаю, зачем каждый раз настраивать функцию.