这是我之前的一个问题然而,经过几个小时的失败后,我决定直接询问这个问题。
目标
为了支持包中的四种德语变格克雷夫特,我打算定义一个新命令\crefthevariantname
,其用法如下:
\crefthevariantname{theorem}
{
{Satz}{Sätze}
, Nominativ = [der]{Satz}[die]{Sätze}
, Genitiv = [des]{Satzes}[der]{Sätze}
, Dativ = [dem]{Satz}[den]{Sätzen}
, Akkusativ = [den]{Satz}[die]{Sätze}
}
理想情况下,它应该在内部将此输入转换为:
\crefthename{theorem}
[
\str_case:NnF \l__crefthe_variant_tl
{
{ Nominativ } { der }
{ Genitiv } { des }
{ Dativ } { dem }
{ Akkusativ } { den }
} { }
]
{
\str_case:NnF \l__crefthe_variant_tl
{
{ Nominativ } { Satz }
{ Genitiv } { Satzes }
{ Dativ } { Satz }
{ Akkusativ } { Satz }
} { Satz }
}
[
\str_case:Nn \l__crefthe_variant_tl
{
{ Nominativ } { die }
{ Genitiv } { der }
{ Dativ } { den }
{ Akkusativ } { die }
} { }
]
{
\str_case:Nn \l__crefthe_variant_tl
{
{ Nominativ } { Sätze }
{ Genitiv } { Sätze }
{ Dativ } { Sätzen }
{ Akkusativ } { Sätze }
} { Sätze }
}
我已经直接测试了上述代码并且它可以工作,所以剩下要做的就是实现这种转换。
我做了什么
目前,我已经成功解析输入,代码如下:
\keys_define:nn { crefthe-variant-parse }
{
, unknown .code:n = {
\seq_put_right:No \l__crefthe_variant_variant_seq { \l_keys_key_tl }
\__crefthe_variant_append_to_seq:w #1
}
}
\bool_new:N \l__crefthe_variant_dafault_given_bool
\cs_new:Nn \crefthe_parse_variant_string:n
% #1 = clist of configuration
{
\bool_set_false:N \l__crefthe_variant_dafault_given_bool
\clist_map_inline:nn { #1 }
{
\str_if_in:nnTF { ##1 } { = }
{
\keys_set:nn { crefthe-variant-parse } { ##1 }
}
{
\bool_set_true:N \l__crefthe_variant_dafault_given_bool
\__crefthe_variant_set_default:w ##1
}
}
\__crefthe_variant_create_prop_from_seq:n { article_singular }
\__crefthe_variant_create_prop_from_seq:n { article_plural }
\__crefthe_variant_create_prop_from_seq:n { singular }
\__crefthe_variant_create_prop_from_seq:n { plural }
}
\tl_new:N \l__crefthe_variant_default_article_singular_tl
\tl_new:N \l__crefthe_variant_default_article_plural_tl
\tl_new:N \l__crefthe_variant_default_singular_tl
\tl_new:N \l__crefthe_variant_default_plural_tl
\NewDocumentCommand \__crefthe_variant_set_default:w { O{} m O{} m }
{
\tl_set:Nn \l__crefthe_variant_default_article_singular_tl { #1 }
\tl_set:Nn \l__crefthe_variant_default_article_plural_tl { #3 }
\tl_set:Nn \l__crefthe_variant_default_singular_tl { #2 }
\tl_set:Nn \l__crefthe_variant_default_plural_tl { #4 }
}
\seq_new:N \l__crefthe_variant_variant_seq
\seq_new:N \l__crefthe_variant_article_singular_seq
\seq_new:N \l__crefthe_variant_article_plural_seq
\seq_new:N \l__crefthe_variant_singular_seq
\seq_new:N \l__crefthe_variant_plural_seq
\NewDocumentCommand \__crefthe_variant_append_to_seq:w { O{} m O{} m }
{
\seq_put_right:Nn \l__crefthe_variant_article_singular_seq { #1 }
\seq_put_right:Nn \l__crefthe_variant_article_plural_seq { #3 }
\seq_put_right:Nn \l__crefthe_variant_singular_seq { #2 }
\seq_put_right:Nn \l__crefthe_variant_plural_seq { #4 }
}
\cs_new:Nn \__crefthe_variant_create_prop_from_seq:n
{
\prop_clear_new:c { l__crefthe_variant_ #1 _prop }
\int_step_inline:nn { \seq_count:c { l__crefthe_variant_ #1 _seq } }
{
\prop_put:cxx { l__crefthe_variant_ #1 _prop }
{ \seq_item:cn { l__crefthe_variant_variant_seq } { ##1 } }
{ \seq_item:cn { l__crefthe_variant_ #1 _seq } { ##1 } }
}
}
主要命令是。它将分别\crefthe_parse_variant_string:n
解析默认行(没有 的行=
,在上例中为{Satz}{Sätze}
)和其他行(如):Nominativ = [der]{Satz}[die]{Sätze}
\__crefthe_variant_set_default:w
解析默认行,将字符串保存到相应的\l__crefthe_variant_default_<type>_tl
;\__crefthe_variant_append_to_seq:w
处理其他行,每次将字符串附加到相应的行中\l__crefthe_variant_<type>_seq
。
此外,虽然我不确定这是否会对最终的解决方案有所帮助,但有了这个@egreg 的回答,有一个\__crefthe_variant_create_prop_from_seq:n
将一对seq
影响转换为一个prop
erty列表的方法。
我不知道该怎么做
我希望能够实现其中[...] {...} [...] {...}
的一部分\crefthe_pass_variant_string_to:n
,然后将其传递给\crefthename{<name>}
获得所需的结果。
但是,由于所有这些变量(无论是tl
还是seq
)都是可重用的,因此在转换为最终结果时,必须对其进行适当扩展,即存储它们的值而不是宏本身。但是,由于我没有控制扩展的经验,即使使用强大的expl3
我也很难正确实现这一点。
我唯一的目的是实现主要目标,即将输入转换为可以被接受的东西\crefthename
,即接收命令m O{} m O{} m
。因此,如果您觉得我的想法很乏味,或者有其他更好的方法,请与我分享您的意见。
平均能量损失
下面是一个 MWE。由于问题实际上是关于宏调用和扩展的,因此我没有包含有关crefthe
。在某些注释部分,您可能会看到我尝试使用马克斯·切尔诺夫'沙@egreg的代码。
\documentclass{article}
\begin{document}
\ExplSyntaxOn
\NewDocumentCommand \crefthevariantname { m m }
{
\crefthe_parse_variant_string:n { #2 }
\crefthe_pass_variant_string_to:n { \crefthename {#1} }
}
\keys_define:nn { crefthe-variant-parse }
{
, unknown .code:n = {
\seq_put_right:No \l__crefthe_variant_variant_seq { \l_keys_key_tl }
\__crefthe_variant_append_to_seq:w #1
}
}
\bool_new:N \l__crefthe_variant_dafault_given_bool
\cs_new:Nn \crefthe_parse_variant_string:n
% #1 = clist of configuration
{
\bool_set_false:N \l__crefthe_variant_dafault_given_bool
\clist_map_inline:nn { #1 }
{
\str_if_in:nnTF { ##1 } { = }
{
\keys_set:nn { crefthe-variant-parse } { ##1 }
}
{
\bool_set_true:N \l__crefthe_variant_dafault_given_bool
\__crefthe_variant_set_default:w ##1
}
}
\__crefthe_variant_create_prop_from_seq:n { article_singular }
\__crefthe_variant_create_prop_from_seq:n { article_plural }
\__crefthe_variant_create_prop_from_seq:n { singular }
\__crefthe_variant_create_prop_from_seq:n { plural }
}
\tl_new:N \l__crefthe_variant_default_article_singular_tl
\tl_new:N \l__crefthe_variant_default_article_plural_tl
\tl_new:N \l__crefthe_variant_default_singular_tl
\tl_new:N \l__crefthe_variant_default_plural_tl
\NewDocumentCommand \__crefthe_variant_set_default:w { O{} m O{} m }
{
\tl_set:Nn \l__crefthe_variant_default_article_singular_tl { #1 }
\tl_set:Nn \l__crefthe_variant_default_article_plural_tl { #3 }
\tl_set:Nn \l__crefthe_variant_default_singular_tl { #2 }
\tl_set:Nn \l__crefthe_variant_default_plural_tl { #4 }
}
\seq_new:N \l__crefthe_variant_variant_seq
\seq_new:N \l__crefthe_variant_article_singular_seq
\seq_new:N \l__crefthe_variant_article_plural_seq
\seq_new:N \l__crefthe_variant_singular_seq
\seq_new:N \l__crefthe_variant_plural_seq
\NewDocumentCommand \__crefthe_variant_append_to_seq:w { O{} m O{} m }
{
\seq_put_right:Nn \l__crefthe_variant_article_singular_seq { #1 }
\seq_put_right:Nn \l__crefthe_variant_article_plural_seq { #3 }
\seq_put_right:Nn \l__crefthe_variant_singular_seq { #2 }
\seq_put_right:Nn \l__crefthe_variant_plural_seq { #4 }
}
\cs_new:Nn \__crefthe_variant_create_prop_from_seq:n
{
\prop_clear_new:c { l__crefthe_variant_ #1 _prop }
\int_step_inline:nn { \seq_count:c { l__crefthe_variant_ #1 _seq } }
{
\prop_put:cxx { l__crefthe_variant_ #1 _prop }
{ \seq_item:cn { l__crefthe_variant_variant_seq } { ##1 } }
{ \seq_item:cn { l__crefthe_variant_ #1 _seq } { ##1 } }
}
}
% \cs_new_protected:Nn \__crefthe_variant_map_dafault:nn
% {
% \str_if_eq:onT { \l__crefthe_variant_tl } { #1 }
% {
% \prg_break:n { #2 \use_none:n }
% }
% }
% \cs_new_protected:Nn \__crefthe_variant_map:nn
% {
% \str_if_eq:onT { \l__crefthe_variant_tl } { #1 }
% {
% \prg_break:n { #2 }
% }
% }
\cs_new:Nn \crefthe_pass_variant_string_to:n
{
\bool_if:NTF \l__crefthe_variant_dafault_given_bool
{
#1
% [
% \prop_if_in:coTF { l__crefthe_variant_article_singular_prop } { \l__crefthe_variant_tl }
% {
% \prop_get:coN { l__crefthe_variant_article_singular_prop } { \l__crefthe_variant_tl } \l_tmpa_tl
% \tl_use:N \l_tmpa_tl
% }
% { \l__crefthe_variant_default_article_singular_tl }
% ]
% {
% \prop_if_in:coTF { l__crefthe_variant_singular_prop } { \l__crefthe_variant_tl }
% {
% \prop_get:coN { l__crefthe_variant_singular_prop } { \l__crefthe_variant_tl } \l_tmpa_tl
% \tl_use:N \l_tmpa_tl
% }
% { \l__crefthe_variant_default_singular_tl }
% }
% [
% \prop_if_in:coTF { l__crefthe_variant_article_plural_prop } { \l__crefthe_variant_tl }
% {
% \prop_get:coN { l__crefthe_variant_article_plural_prop } { \l__crefthe_variant_tl } \l_tmpa_tl
% \tl_use:N \l_tmpa_tl
% }
% { \l__crefthe_variant_default_article_plural_tl }
% ]
% {
% \prop_if_in:coTF { l__crefthe_variant_plural_prop } { \l__crefthe_variant_tl }
% {
% \prop_get:coN { l__crefthe_variant_plural_prop } { \l__crefthe_variant_tl } \l_tmpa_tl
% \tl_use:N \l_tmpa_tl
% }
% { \l__crefthe_variant_default_plural_tl }
% }
}
{
#1
% [
% \seq_map_pairwise_function:NNN
% \l__crefthe_variant_variant_seq
% \l__crefthe_variant_article_singular_seq
% \__crefthe_variant_map:nn
% ]
% {
% \seq_map_pairwise_function:NNN
% \l__crefthe_variant_variant_seq
% \l__crefthe_variant_singular_seq
% \__crefthe_variant_map:nn
% }
% [
% \seq_map_pairwise_function:NNN
% \l__crefthe_variant_variant_seq
% \l__crefthe_variant_article_plural_seq
% \__crefthe_variant_map:nn
% ]
% {
% \seq_map_pairwise_function:NNN
% \l__crefthe_variant_variant_seq
% \l__crefthe_variant_plural_seq
% \__crefthe_variant_map:nn
% }
}
}
\ExplSyntaxOff
Text in case of empty.
\end{document}
下面是一个带有具体示例的 MWE crefthe
(由于字数限制,我只能省略部分代码% ...
;如果需要,您可以在上面的 MWE 中找到相应的代码)。
\documentclass{article}
\usepackage{amsthm}
\usepackage{crefthe}
\newtheorem{testenv}{Testenv}
\begin{document}
\ExplSyntaxOn
\NewDocumentCommand \crefthevariantname { m m }
{
\crefthe_parse_variant_string:n { #2 }
\crefthe_pass_variant_string_to:n { \crefthename {#1} }
}
%...
\cs_new:Nn \crefthe_pass_variant_string_to:n
{
\bool_if:NTF \l__crefthe_variant_dafault_given_bool
{
#1
% ...
}
{
#1
% ...
}
}
\ExplSyntaxOff
\crefthevariantname{testenv}
{
[0]{Zero}[00]{Zero}
, Nominativ = [1]{One}[11]{Ones}
, Genitiv = [2]{Two}[22]{Twos}
, Dativ = [3]{Three}[33]{Threes}
, Akkusativ = [4]{Four}[44]{Fours}
}
\begin{testenv}\label{testenv:test}
Environment for testing...
\end{testenv}
\crefthe{testenv:test}
\crefthe[variant=Nominativ]{testenv:test}
\crefthe[variant=Genitiv]{testenv:test}
\crefthe[variant=Dativ]{testenv:test}
\crefthe[variant=Akkusativ]{testenv:test}
\end{document}
预期结果将是,0 Zero <number>
等等。我没有包括实际的介词或定冠词来测试冠词收缩,但我们希望扩展能够按预期进行。1 One <number>
2 Two <number>
以防万一,以下是 的当前版本(截至 2023/07/20)crefthe
。它包含命令选项的定义variant
和相应的宏\l__crefthe_variant_tl
。
\NeedsTeXFormat{LaTeX2e}[2022-06-01]
\ProvidesExplPackage
{crefthe}
{2023/07/20} {}
{Cross referencing with proper definite articles}
\keys_define:nn { crefthe }
{
, overwrite .bool_set:N = \l__crefthe_overwrite_bool
, overwrite .initial:n = { false }
, nameinlink .bool_set:N = \l__crefthe_nameinlink_bool
, nameinlink .initial:n = { false }
, unknown .code:n =
{ \PassOptionsToPackage { \CurrentOption } { cleveref } }
}
\ProcessKeyOptions [ crefthe ]
\bool_if:NT \l__crefthe_nameinlink_bool
{
\PassOptionsToPackage { nameinlink } { cleveref }
}
\RequirePackage { cleveref }
\RequirePackage { regexpatch }
\NewCommandCopy \crefthe_cref_original:w \cref
\NewCommandCopy \crefthe_Cref_original:w \Cref
\NewCommandCopy \crefthe_crefname_original:w \crefname
\NewCommandCopy \crefthe_Crefname_original:w \Crefname
\NewCommandCopy \crefthe_namecref_original:w \namecref
\NewCommandCopy \crefthe_nameCref_original:w \nameCref
\NewCommandCopy \crefthe_namecrefs_original:w \namecrefs
\NewCommandCopy \crefthe_nameCrefs_original:w \nameCrefs
\str_new:N \l__crefthe_tmpa_str
% \l__crefthe_prep_once_tl is for the "-" mode,
% that only passes the preposition to the first definite article;
% \l__crefthe_prep_each_tl is for the "+" mode,
% that passes the preposition to every definite article.
\tl_new:N \l__crefthe_prep_once_tl
\tl_new:N \l__crefthe_prep_each_tl
\bool_new:N \g__crefthe_uppercase_bool
\bool_new:N \g__crefthe_has_prep_bool
\NewDocumentCommand \crefthe { s t- t+ O{} m }
{
\bool_gset_false:N \g__crefthe_uppercase_bool
\__crefthe_cref_general:NNNnnN #1 #2 #3 { #4 } { #5 } \crefthe_cref_original:w
}
\NewDocumentCommand \Crefthe { s t- t+ O{} m }
{
\bool_gset_true:N \g__crefthe_uppercase_bool
\__crefthe_cref_general:NNNnnN #1 #2 #3 { #4 } { #5 } \crefthe_Cref_original:w
}
\NewDocumentCommand \namecrefthe { t- t+ O{} m }
{
\bool_gset_false:N \g__crefthe_uppercase_bool
\__crefthe_cref_general:NNNnnN \c_false_bool #1 #2 { #3 } { #4 } \crefthe_namecref_original:w
}
\NewDocumentCommand \nameCrefthe { t- t+ O{} m }
{
\bool_gset_true:N \g__crefthe_uppercase_bool
\__crefthe_cref_general:NNNnnN \c_false_bool #1 #2 { #3 } { #4 } \crefthe_nameCref_original:w
}
\NewDocumentCommand \namecrefsthe { t- t+ O{} m }
{
\bool_gset_false:N \g__crefthe_uppercase_bool
\__crefthe_cref_general:NNNnnN \c_false_bool #1 #2 { #3 } { #4 } \crefthe_namecrefs_original:w
}
\NewDocumentCommand \nameCrefsthe { t- t+ O{} m }
{
\bool_gset_true:N \g__crefthe_uppercase_bool
\__crefthe_cref_general:NNNnnN \c_false_bool #1 #2 { #3 } { #4 } \crefthe_nameCrefs_original:w
}
\keys_define:nn { crefthe-setting }
{
, variant .tl_set:N = \l__crefthe_variant_tl
, unknown .code:n = {
\bool_gset_true:N \g__crefthe_has_prep_bool
\tl_set:No \l__crefthe_prep_tl { \l_keys_key_tl }
}
}
\cs_new_protected:Nn \__crefthe_cref_general:NNNnnN
% #1 = star or not
% #2 = -
% #3 = +
% #4 = key-value
% #5 = label
% #6 = original command, such as \crefthe_cref_original:w or \crefthe_Cref_original:w
{
\tl_set:Nn \l__crefthe_variant_tl {}
\bool_gset_false:N \g__crefthe_has_prep_bool
\tl_set:Nn \l__crefthe_prep_tl {}
\keys_set:nn { crefthe-setting } { #4 }
\bool_if:NTF #2
{ \tl_set:No \l__crefthe_prep_once_tl { \l__crefthe_prep_tl } }
{
\bool_if:NTF #3
{ \tl_set:No \l__crefthe_prep_each_tl { \l__crefthe_prep_tl } }
{
% \str_set:Nx fully expands \__crefthe_prep_mode: into a string,
% then \str_case:Vn compares the value of the resulting string:
\str_set:Nx \l__crefthe_tmpa_str { \__crefthe_prep_mode: }
\str_case:Vn \l__crefthe_tmpa_str
{
{ - } { \tl_set:No \l__crefthe_prep_once_tl { \l__crefthe_prep_tl } }
{ + } { \tl_set:No \l__crefthe_prep_each_tl { \l__crefthe_prep_tl } }
}
}
}
\group_begin:
\bool_if:NTF #1
{ #6 * { #5 } }
{ #6 { #5 } }
\group_end:
\tl_gclear:N \l__crefthe_prep_each_tl
}
% \__crefthe_prep_mode: defines the default mode for supported languages
\cs_new:Nn \__crefthe_prep_mode:
{
\str_case:Vn \languagename
{
{french} { + }
{italian} { + }
{spanish} { - }
{portuguese} { + }
{brazilian} { + }
}
}
\NewDocumentCommand \crefthename { m O{} m O{} m }
{
\__crefthe_name_general:nnnnnn { #1 } { #2 } { #3 } { #4 } { #5 } { c }
}
\NewDocumentCommand \Crefthename { m O{} m O{} m }
{
\__crefthe_name_general:nnnnnn { #1 } { #2 } { #3 } { #4 } { #5 } { C }
}
\cs_new:Npn \crefthe_retrieve_space: { \skip_horizontal:n { -\tex_fontdimen:D 2 \tex_font:D~plus -\tex_fontdimen:D 3 \tex_font:D~minus -\tex_fontdimen:D 4 \tex_font:D } }
\cs_new:Nn \crefthe_empty_adjust:n
{
\tl_if_blank:nTF { #1 }
{
\crefthe_retrieve_space:
}
{
#1
}
}
\cs_new_protected:Nn \__crefthe_name_general:nnnnnn
% #1 = environment name
% #2 = singular definite article
% #3 = singular name
% #4 = plural definite article
% #5 = plural name
% #6 = c or C
{
\__crefthe_name_general_do:nnnnnn
{ #1 }
{ \crefthemark { \crefthe_empty_adjust:n { #2 } } }
{ \crefthe_empty_adjust:n { #3 } }
{ \crefthemark { \crefthe_empty_adjust:n { #4 } } }
{ \crefthe_empty_adjust:n { #5 } }
{ #6 }
}
\cs_new_protected:Nn \__crefthe_name_general_do:nnnnnn
{
\use:c { crefthe_#6refname_original:w } { #1 } { #2 #3 } { #4 #5 }
\bool_if:NT \l__crefthe_nameinlink_bool
{
\hook_gput_code:nnn { begindocument } { crefthe }
{
\crefthe_patch_format:nnnn { #6ref@#1@format } { #6ref@#1@name } { #2 } { #3 }
\crefthe_patch_format:nnnn { #6ref@#1@format@first } { #6ref@#1@name@plural } { #4 } { #5 }
\crefthe_patch_format:nnnn { #6refrange@#1@format } { #6ref@#1@name@plural } { #4 } { #5 }
\crefthe_patch_format:nnnn { #6refrange@#1@format@first } { #6ref@#1@name@plural } { #4 } { #5 }
}
}
}
\seq_new:N \g__crefthe_already_patched_seq
\cs_new_protected:Nn \crefthe_patch_format:nnnn
% #1 = name of the format command
% #2 = name of the command after the hyperlink beginning mark
% #3 = new content before the mark
% #4 = new content after the mark
{
\seq_if_in:NnF \g__crefthe_already_patched_seq { #1 - #2 }
{
\makeatletter
\tl_set:No \l_tmpa_tl { #3 }
\tl_set:No \l_tmpb_tl { #4 }
\exp_args:Nc \regexpatchcmd { #1 }
{ (\cP\# .) \c{ #2 } }
{ \u{l_tmpa_tl} \1 \u{l_tmpb_tl} }
{ } { \msg_warning:nnn { crefthe } { format-patch-failed } { #1 } }
\makeatother
\seq_gput_right:Nn \g__crefthe_already_patched_seq { #1 - #2 }
}
}
\msg_new:nnn { crefthe }
{ format-patch-failed }
{ Failed~to~patch~the~format~"\iow_char:N \\#1"! }
\cs_generate_variant:Nn \text_lowercase:n { V }
\NewDocumentCommand \crefthemark { m }
{
\crefthe_contraction:Ve \l__crefthe_prep_each_tl
{ \crefthe_contraction:Vn \l__crefthe_prep_once_tl { #1 } }
\tl_gclear:N \l__crefthe_prep_once_tl
\tl_gset:Nx \l__crefthe_prep_each_tl
{ \text_lowercase:V \l__crefthe_prep_each_tl }
\str_if_eq:eeF { \str_tail:n { #1 } } { ' } { ~ }
\bool_gset_false:N \g__crefthe_uppercase_bool
}
\prg_generate_conditional_variant:Nnn \str_case_e:nn { ev } { T, F, TF }
\cs_new:Nn \crefthe_contraction:nn
{
\exp_args:Ne \__crefthe_contraction:nnn
{ \text_lowercase:n { #2 } } { #1 } { #2 }
}
\cs_generate_variant:Nn \crefthe_contraction:nn { V, Ve }
\cs_new:Nn \__crefthe_contraction:nnn
{
% #1 is \text_lowercase:n { #3 }
% #2 is the preposition
\tl_if_blank:nTF { #2 }
{ #3 }
{
\tl_if_exist:cTF { c_crefthe_contraction_rule_ \languagename _tl }
{
\exp_args:Ne \__crefthe_conditional_uppercase:n
{
\str_case_e:evF { #2~#1 }
{ c_crefthe_contraction_rule_ \languagename _tl }
{ #2~#1 }
}
}
{ #2~#3 }
}
}
\cs_new:Nn \__crefthe_conditional_uppercase:n
{
\bool_if:NTF \g__crefthe_uppercase_bool
{ \text_titlecase_first:n }
{ \use:n }
{ #1 }
}
\NewDocumentCommand \crefthepatchname { m }
{
\clist_map_inline:nn { #1 }
{
\crefthe_patch_name:n { ##1 }
}
}
\cs_new:Nn \crefthe_patch_name:n
{
\tl_gput_left:cn { cref@#1@name } { \crefthemark { \crefthe_empty_adjust:n {} } }
\tl_gput_left:cn { cref@#1@name@plural } { \crefthemark { \crefthe_empty_adjust:n {} } }
\tl_gput_left:cn { Cref@#1@name } { \crefthemark { \crefthe_empty_adjust:n {} } }
\tl_gput_left:cn { Cref@#1@name@plural } { \crefthemark { \crefthe_empty_adjust:n {} } }
}
\hook_gput_code:nnn { begindocument/end } { crefthe }
{
\bool_if:NT \l__crefthe_overwrite_bool
{
\RenewCommandCopy \cref \crefthe
\RenewCommandCopy \Cref \Crefthe
\RenewCommandCopy \crefname \crefthename
\RenewCommandCopy \Crefname \Crefthename
}
}
\tl_const:Nn \c_crefthe_contraction_rule_french_tl
{
{ à~le } { au }
{ à~les } { aux }
{ de~le } { du }
{ de~les } { des }
{ À~le } { Au }
{ À~les } { Aux }
{ De~le } { Du }
{ De~les } { Des }
}
\tl_const:Nn \c_crefthe_contraction_rule_ngerman_tl
{
{ an~dem } { am }
{ an~das } { ans }
{ bei~dem } { beim }
{ in~dem } { im }
{ in~das } { ins }
{ von~dem } { vom }
{ zu~dem } { zum }
{ zu~der } { zur }
{ An~dem } { Am }
{ An~das } { Ans }
{ Bei~dem } { Beim }
{ In~dem } { Im }
{ In~das } { Ins }
{ Von~dem } { Vom }
{ Zu~dem } { Zum }
{ Zu~der } { Zur }
}
\tl_const:Nn \c_crefthe_contraction_rule_italian_tl
{
{ a~il } { al }
{ a~lo } { allo }
{ a~l' } { all' }
{ a~la } { alla }
{ di~il } { del }
{ di~lo } { dello }
{ di~l' } { dell' }
{ di~la } { della }
{ da~il } { dal }
{ da~lo } { dallo }
{ da~l' } { dall' }
{ da~la } { dalla }
{ in~il } { nel }
{ in~lo } { nello }
{ in~l' } { nell' }
{ in~la } { nella }
{ su~il } { sul }
{ su~lo } { sullo }
{ su~l' } { sull' }
{ su~la } { sulla }
{ a~i } { ai }
{ a~gli } { agli }
{ a~le } { alle }
{ di~i } { dei }
{ di~gli } { degli }
{ di~le } { delle }
{ da~i } { dai }
{ da~gli } { dagli }
{ da~le } { dalle }
{ in~i } { nei }
{ in~gli } { negli }
{ in~le } { nelle }
{ su~i } { sui }
{ su~gli } { sugli }
{ su~le } { sulle }
{ A~il } { Al }
{ A~lo } { Allo }
{ A~l' } { All' }
{ A~la } { Alla }
{ Di~il } { Del }
{ Di~lo } { Dello }
{ Di~l' } { Dell' }
{ Di~la } { Della }
{ Da~il } { Dal }
{ Da~lo } { Dallo }
{ Da~l' } { Dall' }
{ Da~la } { Dalla }
{ In~il } { Nel }
{ In~lo } { Nello }
{ In~l' } { Nell' }
{ In~la } { Nella }
{ Su~il } { Sul }
{ Su~lo } { Sullo }
{ Su~l' } { Sull' }
{ Su~la } { Sulla }
{ A~i } { Ai }
{ A~gli } { Agli }
{ A~le } { Alle }
{ Di~i } { Dei }
{ Di~gli } { Degli }
{ Di~le } { Delle }
{ Da~i } { Dai }
{ Da~gli } { Dagli }
{ Da~le } { Dalle }
{ In~i } { Nei }
{ In~gli } { Negli }
{ In~le } { Nelle }
{ Su~i } { Sui }
{ Su~gli } { Sugli }
{ Su~le } { Sulle }
}
\tl_const:Nn \c_crefthe_contraction_rule_spanish_tl
{
{ a~el } { al }
{ de~el } { del }
{ A~el } { Al }
{ De~el } { Del }
}
\tl_const:Nn \c_crefthe_contraction_rule_portuguese_tl
{
{ a~o } { ao }
{ a~a } { à }
{ a~os } { aos }
{ a~as } { às }
{ de~o } { do }
{ de~a } { da }
{ de~os } { dos }
{ de~as } { das }
{ em~o } { no }
{ em~a } { na }
{ em~os } { nos }
{ em~as } { nas }
{ A~o } { Ao }
{ A~a } { À }
{ A~os } { Aos }
{ A~as } { Às }
{ De~o } { Do }
{ De~a } { Da }
{ De~os } { Dos }
{ De~as } { Das }
{ Em~o } { No }
{ Em~a } { Na }
{ Em~os } { Nos }
{ Em~as } { Nas }
}
\tl_const:Nx \c_crefthe_contraction_rule_brazilian_tl
{ \exp_not:V \c_crefthe_contraction_rule_portuguese_tl }
\endinput
%%
%% End of file `crefthe.sty'.
答案1
我想指出的是,我不太喜欢这个代码。我认为界面不干净,你应该改为\crefthename
支持指定变体的可选参数。
但是下面的代码可以相当直接地实现你想要的效果。我们需要的变量太多了,但我希望 10 个变量还是可以的。可以对速度进行一些优化,然后\tl_item:Nn
改用\exp_args:No \exp_not:o { \exp_after:wN \use_i:nnnn \l__crefthe_<variable>_tl }
其他方法,但我怀疑这样做是否值得,因为代码有太多更严重的性能问题,优化无法改变。
无论如何,这里什么也没有:
\documentclass{article}
\usepackage{amsthm}
\usepackage{crefthe}
\newtheorem{testenv}{Testenv}
\begin{document}
\ExplSyntaxOn
\NewDocumentCommand \crefthevariantname { m m }
{
\crefthe_parse_variant:n { #2 }
\crefthe_pass_variant_to:n { \crefthename {#1} }
}
% sn: singular noun, pn: plural noun, sa: singular article, pa: plural article
\tl_new:N \l__crefthe_variant_sn_tl
\tl_new:N \l__crefthe_variant_pn_tl
\tl_new:N \l__crefthe_variant_sa_tl
\tl_new:N \l__crefthe_variant_pa_tl
\tl_new:N \l__crefthe_variant_default_sn_tl
\tl_new:N \l__crefthe_variant_default_pn_tl
\tl_new:N \l__crefthe_variant_default_sa_tl
\tl_new:N \l__crefthe_variant_default_pa_tl
\bool_new:N \l__crefthe_variant_default_bool
\cs_new_protected:Npn \crefthe_parse_variant:n #1
{
\tl_clear:N \l__crefthe_variant_singular_noun_tl
\tl_clear:N \l__crefthe_variant_plural_noun_tl
\tl_clear:N \l__crefthe_variant_singular_article_tl
\tl_clear:N \l__crefthe_variant_plural_article_tl
\tl_clear:N \l__crefthe_variant_default_sn_tl
\tl_clear:N \l__crefthe_variant_default_pn_tl
\tl_clear:N \l__crefthe_variant_default_sa_tl
\tl_clear:N \l__crefthe_variant_default_pa_tl
\bool_set_false:N \l__crefthe_variant_default_bool
\keyval_parse:NNn
\__crefthe_parse_variant_default:n
\__crefthe_parse_variant_value:nn
{#1}
}
\tl_new:N \l__crefthe_parsed_tl
% this is wrong! That's not a document command, interface should be cleaner.
\NewDocumentCommand \__crefthe_variant_parser:w { O{} m O{} m }
{
\tl_set:Nn \l__crefthe_parsed_tl { {#1} {#2} {#3} {#4} }
\use_none_delimit_by_q_stop:w
}
\cs_new_protected:Npn \__crefthe_parse_variant_default:n #1
{
\bool_set_true:N \l__crefthe_variant_default_bool
\__crefthe_variant_parser:w #1 {} {} \q_stop
\tl_set:Nx \l__crefthe_variant_default_sa_tl
{ \tl_item:Nn \l__crefthe_parsed_tl {1} }
\tl_set:Nx \l__crefthe_variant_default_sn_tl
{ \tl_item:Nn \l__crefthe_parsed_tl {2} }
\tl_set:Nx \l__crefthe_variant_default_pa_tl
{ \tl_item:Nn \l__crefthe_parsed_tl {3} }
\tl_set:Nx \l__crefthe_variant_default_pn_tl
{ \tl_item:Nn \l__crefthe_parsed_tl {4} }
}
\cs_new_protected:Npn \__crefthe_parse_variant_value:nn #1#2
{
\__crefthe_variant_parser:w #2 {} {} \q_stop
\tl_put_right:Nx \l__crefthe_variant_sa_tl
{ { \tl_to_str:n {#1} } { \tl_item:Nn \l__crefthe_parsed_tl {1} } }
\tl_put_right:Nx \l__crefthe_variant_sn_tl
{ { \tl_to_str:n {#1} } { \tl_item:Nn \l__crefthe_parsed_tl {2} } }
\tl_put_right:Nx \l__crefthe_variant_pa_tl
{ { \tl_to_str:n {#1} } { \tl_item:Nn \l__crefthe_parsed_tl {3} } }
\tl_put_right:Nx \l__crefthe_variant_pn_tl
{ { \tl_to_str:n {#1} } { \tl_item:Nn \l__crefthe_parsed_tl {4} } }
}
\cs_new_protected:Npn \crefthe_pass_variant_to:n #1
{
\use:e
{
\exp_not:n {#1}
\bool_if:NTF \l__crefthe_variant_default_bool
{
[
\exp_not:n { \str_case:NnF \l__crefthe_variant_tl }
{ \exp_not:o \l__crefthe_variant_sa_tl }
{ \exp_not:o \l__crefthe_variant_default_sa_tl }
]
{
\exp_not:n { \str_case:NnF \l__crefthe_variant_tl }
{ \exp_not:o \l__crefthe_variant_sn_tl }
{ \exp_not:o \l__crefthe_variant_default_sn_tl }
}
[
\exp_not:n { \str_case:NnF \l__crefthe_variant_tl }
{ \exp_not:o \l__crefthe_variant_pa_tl }
{ \exp_not:o \l__crefthe_variant_default_pa_tl }
]
{
\exp_not:n { \str_case:NnF \l__crefthe_variant_tl }
{ \exp_not:o \l__crefthe_variant_pa_tl }
{ \exp_not:o \l__crefthe_variant_default_pa_tl }
}
}
{
[
\exp_not:n { \str_case:Nn \l__crefthe_variant_tl }
{ \exp_not:o \l__crefthe_variant_sa_tl }
]
{
\exp_not:n { \str_case:Nn \l__crefthe_variant_tl }
{ \exp_not:o \l__crefthe_variant_sn_tl }
}
[
\exp_not:n { \str_case:Nn \l__crefthe_variant_tl }
{ \exp_not:o \l__crefthe_variant_pa_tl }
]
{
\exp_not:n { \str_case:Nn \l__crefthe_variant_tl }
{ \exp_not:o \l__crefthe_variant_pa_tl }
}
}
}
}
\ExplSyntaxOff
\crefthevariantname{testenv}
{
[0]{Zero}[00]{Zero}
, Nominativ = [1]{One}[11]{Ones}
, Genitiv = [2]{Two}[22]{Twos}
, Dativ = [3]{Three}[33]{Threes}
, Akkusativ = [4]{Four}[44]{Fours}
}
\begin{testenv}\label{testenv:test}
Environment for testing...
\end{testenv}
\crefthe{testenv:test}
\crefthe[variant=Nominativ]{testenv:test}
\crefthe[variant=Genitiv]{testenv:test}
\crefthe[variant=Dativ]{testenv:test}
\crefthe[variant=Akkusativ]{testenv:test}
\end{document}