私は、標準的なプリアンブルを整理するために一連の関数をラップする独自の定理パッケージを作成しようとしています。その際に、次の問題に行き詰まりました。新しい定理のような環境とそれに対応する名前をcleveref
、単一のメソッドで単一の呼び出しによって定義する関数を作成しようとしています。しかし、何らかの理由で、これが機能しません。
以下に 2 つのアプローチの最小限の例を示します。前者は私が自然に行うことで、後者では、現在より広範なパッケージを記述している 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
ただし、毎回機能を設定する理由がわかりません。