diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/zref-clever/zref-clever.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/zref-clever/zref-clever.dtx | 3350 |
1 files changed, 2163 insertions, 1187 deletions
diff --git a/Master/texmf-dist/source/latex/zref-clever/zref-clever.dtx b/Master/texmf-dist/source/latex/zref-clever/zref-clever.dtx index 3027bcab15e..d850476b4cf 100644 --- a/Master/texmf-dist/source/latex/zref-clever/zref-clever.dtx +++ b/Master/texmf-dist/source/latex/zref-clever/zref-clever.dtx @@ -162,7 +162,7 @@ % % Identify the package. % \begin{macrocode} -\ProvidesExplPackage {zref-clever} {2022-01-10} {0.1.2-alpha} +\ProvidesExplPackage {zref-clever} {2022-01-28} {0.2.0-alpha} {Clever LaTeX cross-references based on zref} % \end{macrocode} % @@ -398,7 +398,7 @@ { \bool_if:nTF { \prop_if_in_p:Nn \l_@@_counter_resetby_prop {#1} } - { \prop_item:Nn \l_@@_counter_resetby_prop {#1} } + { \prop_item:Nn \l_@@_counter_resetby_prop {#1} } { \seq_map_tokens:Nn \l_@@_counter_resetters_seq { \@@_counter_reset_by_aux:nn {#1} } @@ -523,11 +523,6 @@ } \msg_new:nnn { zref-clever } { key-requires-value } { The~'#1'~key~'#2'~requires~a~value~\msg_line_context:. } -\msg_new:nnn { zref-clever } { key-boolean-or-empty } - { - The~key~'#1'~only~accepts~the~values~'true',~'false'~ - or~an~empty~value~\msg_line_context:. - } \msg_new:nnn { zref-clever } { language-declared } { Language~'#1'~is~already~declared~\msg_line_context:.~Nothing~to~do. } \msg_new:nnn { zref-clever } { unknown-language-alias } @@ -544,7 +539,7 @@ } \msg_new:nnn { zref-clever } { unknown-language-opt } { - Language~'#1'~is~unknown~\msg_line_context:.~Using~default.~ + Language~'#1'~is~unknown~\msg_line_context:.~ See~documentation~for~'\iow_char:N\\zcDeclareLanguage'~and~ '\iow_char:N\\zcDeclareLanguageAlias'. } @@ -607,15 +602,6 @@ { Option~'#1'~is~only~available~after~\iow_char:N\\begin\{document\}. } \msg_new:nnn { zref-clever } { langfile-loaded } { Loaded~'#1'~language~file. } -\msg_new:nnn { zref-clever } { langfile-not-available } - { Language~file~for~'#1'~not~available~\msg_line_context:. } -\msg_new:nnn { zref-clever } { unknown-language-load } - { - Language~'#1'~is~unknown~\msg_line_context:.~ - Unable~to~load~language~file.~See~documentation~for~ - '\iow_char:N\\zcDeclareLanguage'~and~ - '\iow_char:N\\zcDeclareLanguageAlias'. - } \msg_new:nnn { zref-clever } { zref-property-undefined } { Option~'ref=#1'~requested~\msg_line_context:.~ @@ -641,6 +627,12 @@ Unknown~compatibility~module~'#1'~given~to~option~'nocompat'.~ Nothing~to~do. } +\msg_new:nnn { zref-clever } { refbounds-must-be-four } + { + The~value~of~option~'#1'~must~be~a~comma~sepatared~list~ + of~four~items.~We~received~'#2'~items~\msg_line_context:.~ + Option~not~set. + } \msg_new:nnn { zref-clever } { missing-zref-check } { Option~'check'~requested~\msg_line_context:.~ @@ -652,11 +644,6 @@ { Reference~property~'#1'~undefined~for~label~'#2'~\msg_line_context:. } \msg_new:nnn { zref-clever } { missing-name } { Reference~format~option~'#1'~undefined~for~type~'#2'~\msg_line_context:. } -\msg_new:nnn { zref-clever } { missing-string } - { - We~couldn't~find~a~value~for~reference~option~'#1'~\msg_line_context:.~ - But~we~should~have:~throw~a~rock~at~the~maintainer. - } \msg_new:nnn { zref-clever } { single-element-range } { Range~for~type~'#1'~resulted~in~single~element~\msg_line_context:. } \msg_new:nnn { zref-clever } { compat-package } @@ -724,21 +711,414 @@ % \end{macro} % % +% \subsection{Option infra} +% +% This section provides the functions in which the variables naming scheme of +% the package options is embodied, and some basic general functions to query +% these option variables. +% +% I had originally implemented the option handling of the package based on +% property lists, which are definitely very convenient. But as the number of +% options grew, I started to get concerned about the performance implications. +% That there was a toll was noticeable, even when we could live with it, of +% course. Indeed, at the time of writing, the typesetting of a reference +% queries about 24 different option values, most of them once per type-block, +% each of these queries can be potentially made in up to 5 option scope +% levels. Considering the size of the built-in language files is running at +% the hundreds, the package does have a lot of work to do in querying option +% values alone, and thus it is best to smooth things in this area as much as +% possible. This also gives me some peace of mind that the package will scale +% well in the long term. For some interesting discussion about alternative +% methods and their performance implications, see +% \url{https://tex.stackexchange.com/q/147966}. \contributor{Phelype Oleinik} +% also offered some insight on the matter at +% \url{https://tex.stackexchange.com/questions/629946/#comment1571118_629946}. +% The only real downside of this change is that we can no longer list the +% whole set of options in place at a given moment, which was useful for the +% purposes of regression testing, since we don't know what the whole set of +% active options is. +% +% +% \begin{macro}[EXP]{\@@_opt_varname_general:nn} +% Defines, and leaves in the input stream, the csname of the variable used +% to store the general \meta{option}. The data type of the variable must be +% specified (\texttt{tl}, \texttt{seq}, \texttt{bool}, etc.). +% \begin{syntax} +% \cs{@@_opt_varname_general:nn} \Arg{option} \Arg{data type} +% \end{syntax} +% \begin{macrocode} +\cs_new:Npn \@@_opt_varname_general:nn #1#2 + { l_@@_opt_general_ #1 _ #2 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_opt_varname_type:nnn} +% Defines, and leaves in the input stream, the csname of the variable used +% to store the type-specific \meta{option} for \meta{ref type}. +% \begin{syntax} +% \cs{@@_opt_varname_type:nnn} \Arg{ref type} \Arg{option} \Arg{data type} +% \end{syntax} +% \begin{macrocode} +\cs_new:Npn \@@_opt_varname_type:nnn #1#2#3 + { l_@@_opt_type_ #1 _ #2 _ #3 } +\cs_generate_variant:Nn \@@_opt_varname_type:nnn { enn , een } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_opt_varname_language:nnn} +% Defines, and leaves in the input stream, the csname of the variable used +% to store the language \meta{option} for \meta{lang} (for general language +% options, those set with \cs{zcDeclareLanguage}). The +% ``\texttt{lang_unknown}'' branch should be guarded against, such as we +% normally should not get there, but this function \emph{must} return some +% valid csname. The random part is there so that, in the circumstance this +% could not be avoided, we (hopefully) don't retrieve the value for an +% ``unknown language'' inadvertently. +% \begin{syntax} +% \cs{@@_opt_varname_language:nnn} \Arg{lang} \Arg{option} \Arg{data type} +% \end{syntax} +% \begin{macrocode} +\cs_new:Npn \@@_opt_varname_language:nnn #1#2#3 + { + \@@_language_if_declared:nTF {#1} + { + g_@@_opt_language_ + \tl_use:c { \@@_language_varname:n {#1} } + _ #2 _ #3 + } + { g_@@_opt_lang_unknown_ \int_rand:n { 1000000 } _ #3 } + } +\cs_generate_variant:Nn \@@_opt_varname_language:nnn { enn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_opt_varname_lang_default:nnn} +% Defines, and leaves in the input stream, the csname of the variable used +% to store the language-specific default reference format \meta{option} for +% \meta{lang}. +% \begin{syntax} +% \cs{@@_opt_varname_lang_default:nnn} \Arg{lang} \Arg{option} \Arg{data type} +% \end{syntax} +% \begin{macrocode} +\cs_new:Npn \@@_opt_varname_lang_default:nnn #1#2#3 + { + \@@_language_if_declared:nTF {#1} + { + g_@@_opt_lang_ + \tl_use:c { \@@_language_varname:n {#1} } + _default_ #2 _ #3 + } + { g_@@_opt_lang_unknown_ \int_rand:n { 1000000 } _ #3 } + } +\cs_generate_variant:Nn \@@_opt_varname_lang_default:nnn { enn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_opt_varname_lang_type:nnnn} +% Defines, and leaves in the input stream, the csname of the variable used +% to store the language- and type-specific reference format \meta{option} +% for \meta{lang} and \meta{ref type}. +% \begin{syntax} +% \cs{@@_opt_varname_lang_type:nnnn} \Arg{lang} \Arg{ref type} +% ~~\Arg{option} \Arg{data type} +% \end{syntax} +% \begin{macrocode} +\cs_new:Npn \@@_opt_varname_lang_type:nnnn #1#2#3#4 + { + \@@_language_if_declared:nTF {#1} + { + g_@@_opt_lang_ + \tl_use:c { \@@_language_varname:n {#1} } + _type_ #2 _ #3 _ #4 + } + { g_@@_opt_lang_unknown_ \int_rand:n { 1000000 } _ #4 } + } +\cs_generate_variant:Nn + \@@_opt_varname_lang_type:nnnn { eenn , eeen } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_opt_varname_fallback:nn} +% Defines, and leaves in the input stream, the csname of the variable used +% to store the fallback \meta{option}. +% \begin{syntax} +% \cs{@@_opt_varname_fallback:nn} \Arg{option} \Arg{data type} +% \end{syntax} +% \begin{macrocode} +\cs_new:Npn \@@_opt_varname_fallback:nn #1#2 + { c_@@_opt_fallback_ #1 _ #2 } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro} +% { +% \@@_opt_tl_unset:N , +% \@@_opt_tl_gunset:N , +% } +% Unset \meta{option tl}. These functions \emph{define} what means to be +% unset for an option token list, and it must match what the conditional +% \cs{@@_opt_tl_if_set:N} tests for. +% \begin{syntax} +% \cs{@@_opt_tl_unset:N} \Arg{option tl} +% \cs{@@_opt_tl_gunset:N} \Arg{option tl} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_opt_tl_unset:N #1 + { \tl_set_eq:NN #1 \c_novalue_tl } +\cs_new_protected:Npn \@@_opt_tl_gunset:N #1 + { \tl_gset_eq:NN #1 \c_novalue_tl } +\cs_generate_variant:Nn \@@_opt_tl_unset:N { c } +\cs_generate_variant:Nn \@@_opt_tl_gunset:N { c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP,TF]{\@@_opt_tl_if_set:N} +% \begin{syntax} +% \cs{@@_opt_tl_if_set:N(TF)} \Arg{option tl} \Arg{true} \Arg{false} +% \end{syntax} +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_opt_tl_if_set:N #1 { F , TF } + { + \bool_lazy_and:nnTF + { \tl_if_exist_p:N #1 } + { ! \tl_if_novalue_p:n {#1} } + { \prg_return_true: } + { \prg_return_false: } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_opt_tl_gset_if_new:Nn} +% \begin{syntax} +% \cs{@@_opt_tl_gset_if_new:Nn} \Arg{option tl} \Arg{value} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_opt_tl_gset_if_new:Nn #1#2 + { + \@@_opt_tl_if_set:NF #1 + { \tl_gset:Nn #1 {#2} } + } +\cs_generate_variant:Nn \@@_opt_tl_gset_if_new:Nn { cn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[TF]{\@@_opt_tl_get:NN} +% \begin{syntax} +% \cs{@@_opt_tl_get:NN(TF)} \Arg{option tl to get} \Arg{tl var to set} +% ~~\Arg{true} \Arg{false} +% \end{syntax} +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \@@_opt_tl_get:NN #1#2 { F } + { + \@@_opt_tl_if_set:NTF #1 + { + \tl_set_eq:NN #2 #1 + \prg_return_true: + } + { \prg_return_false: } + } +\prg_generate_conditional_variant:Nnn + \@@_opt_tl_get:NN { cN } { F } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro} +% { +% \@@_opt_seq_set_clist_split:Nn , +% \@@_opt_seq_gset_clist_split:Nn , +% } +% \begin{syntax} +% \cs{@@_opt_seq_set_clist_split:Nn} \Arg{option seq} \Arg{value} +% \cs{@@_opt_seq_gset_clist_split:Nn} \Arg{option seq} \Arg{value} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_opt_seq_set_clist_split:Nn #1#2 + { \seq_set_split:Nnn #1 { , } {#2} } +\cs_new_protected:Npn \@@_opt_seq_gset_clist_split:Nn #1#2 + { \seq_gset_split:Nnn #1 { , } {#2} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \@@_opt_seq_unset:N , +% \@@_opt_seq_gunset:N , +% } +% Unset \meta{option seq}. These functions \emph{define} what means to be +% unset for an option sequence, and it must match what the conditional +% \cs{@@_opt_seq_if_set:N} tests for. +% \begin{syntax} +% \cs{@@_opt_seq_unset:N} \Arg{option seq} +% \cs{@@_opt_seq_gunset:N} \Arg{option seq} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_opt_seq_unset:N #1 + { \cs_set_eq:NN #1 \scan_stop: } +\cs_new_protected:Npn \@@_opt_seq_gunset:N #1 + { \cs_gset_eq:NN #1 \scan_stop: } +\cs_generate_variant:Nn \@@_opt_seq_unset:N { c } +\cs_generate_variant:Nn \@@_opt_seq_gunset:N { c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP,TF]{\@@_opt_seq_if_set:N} +% \begin{syntax} +% \cs{@@_opt_seq_if_set:N(TF)} \Arg{option seq} \Arg{true} \Arg{false} +% \end{syntax} +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_opt_seq_if_set:N #1 { F , TF } + { \seq_if_exist:NTF #1 { \prg_return_true: } { \prg_return_false: } } +\prg_generate_conditional_variant:Nnn + \@@_opt_seq_if_set:N { c } { F , TF } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[TF]{\@@_opt_seq_get:NN} +% \begin{syntax} +% \cs{@@_opt_seq_get:NN(TF)} \Arg{option seq to get} \Arg{seq var to set} +% ~~\Arg{true} \Arg{false} +% \end{syntax} +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \@@_opt_seq_get:NN #1#2 { F } + { + \@@_opt_seq_if_set:NTF #1 + { + \seq_set_eq:NN #2 #1 + \prg_return_true: + } + { \prg_return_false: } + } +\prg_generate_conditional_variant:Nnn + \@@_opt_seq_get:NN { cN } { F } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro} +% { +% \@@_opt_bool_unset:N , +% \@@_opt_bool_gunset:N , +% } +% Unset \meta{option bool}. These functions \emph{define} what means to be +% unset for an option boolean, and it must match what the conditional +% \cs{@@_opt_bool_if_set:N} tests for. The particular definition we are +% employing here has some relevant implications. Setting the boolean +% variable to \cs{scan_stop:} (aka, \cs{relax}) means we can \emph{never} +% test the variable without first testing if it is \emph{set}. +% \cs{@@_opt_bool_if:N} does this conveniently. +% \begin{syntax} +% \cs{@@_opt_bool_unset:N} \Arg{option bool} +% \cs{@@_opt_bool_gunset:N} \Arg{option bool} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_opt_bool_unset:N #1 + { \cs_set_eq:NN #1 \scan_stop: } +\cs_new_protected:Npn \@@_opt_bool_gunset:N #1 + { \cs_gset_eq:NN #1 \scan_stop: } +\cs_generate_variant:Nn \@@_opt_bool_unset:N { c } +\cs_generate_variant:Nn \@@_opt_bool_gunset:N { c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP,TF]{\@@_opt_bool_if_set:N} +% \begin{syntax} +% \cs{@@_opt_bool_if_set:N(TF)} \Arg{option bool} \Arg{true} \Arg{false} +% \end{syntax} +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_opt_bool_if_set:N #1 { F , TF } + { \bool_if_exist:NTF #1 { \prg_return_true: } { \prg_return_false: } } +\prg_generate_conditional_variant:Nnn + \@@_opt_bool_if_set:N { c } { F , TF } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}[TF]{\@@_opt_bool_get:NN} +% \begin{syntax} +% \cs{@@_opt_bool_get:NN(TF)} \Arg{option bool to get} \Arg{bool var to set} +% ~~\Arg{true} \Arg{false} +% \end{syntax} +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \@@_opt_bool_get:NN #1#2 { F } + { + \@@_opt_bool_if_set:NTF #1 + { + \bool_set_eq:NN #2 #1 + \prg_return_true: + } + { \prg_return_false: } + } +\prg_generate_conditional_variant:Nnn + \@@_opt_bool_get:NN { cN } { F } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP,TF]{\@@_opt_bool_if:N} +% \begin{syntax} +% \cs{@@_opt_bool_if:N(TF)} \Arg{option bool} \Arg{true} \Arg{false} +% \end{syntax} +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_opt_bool_if:N #1 { T , F , TF } + { + \@@_opt_bool_if_set:NTF #1 + { \bool_if:NTF #1 { \prg_return_true: } { \prg_return_false: } } + { \prg_return_false: } + } +\prg_generate_conditional_variant:Nnn + \@@_opt_bool_if:N { c } { T , F , TF } +% \end{macrocode} +% \end{macro} +% +% +% % \subsection{Reference format} % % For a general discussion on the precedence rules for reference format % options, see Section ``Reference format'' in the User manual. Internally, -% these precedence rules are handled / enforced in -% \cs{@@_get_ref_opt_typeset:nN}, \cs{@@_get_ref_opt_font:nN}, and +% these precedence rules are handled / enforced in \cs{@@_get_rf_opt_tl:nnnN}, +% \cs{@@_get_rf_opt_seq:nnnN}, \cs{@@_get_rf_opt_bool:nnnnN}, and % \cs{@@_type_name_setup:} which are the basic functions to retrieve proper -% values for reference format settings. The ``fallback'' settings are stored -% in \cs{g_@@_fallback_unknown_lang_prop}. +% values for reference format settings. +% +% The fact that we have multiple scopes to set reference format options has +% some implications for how we handle these options, and for the resulting UI. +% Since there is a clear precedence rule between the different levels, setting +% an option at a high priority level shadows everything below it. Hence, it +% may be relevant to be able to ``unset'' these options too, so as to be able +% go back to the lower precedence level of the language-specific options at +% any given point. However, since many of these options are token lists, or +% clists, for which ``empty'' is a legitimate value, we cannot rely on +% emptiness to distinguish that particular intention. How to deal with it, +% depends on the kind of option (its data type, to be precise). For token +% lists and clists/sequences, we leverage the distinction of an ``empty valued +% key'' (\texttt{key=} or \texttt{key=\{\}}) from a ``key with no value'' +% (\texttt{key}). This distinction is captured internally by the lower-level +% key parsing, but must be made explicit in \cs{keys_define:nn} by means of +% the \texttt{.default:x} property of the key. For the technique, by +% \contributor{Jonathan P.\ Spratte}, aka `Skillmon', and some discussion +% about it, including further insights by \contributor{Phelype Oleinik}, see +% \url{https://tex.stackexchange.com/q/614690} and +% \url{https://github.com/latex3/latex3/pull/988}. For booleans, the +% situation is different, since they cannot meaningfully receive an empty +% value and the ``key with no value'' is a handy and expected shorthand for +% \texttt{key=true}. Therefore, for reference format option booleans, we use +% a third value ``\texttt{unset}'' for this purpose. In the language files +% the ``unsetting'' behavior is less meaningful, since they only change any +% variable if it is unset to start with, so that unsetting an unset variable +% would be redundant. However, for UI symmetry also in the language files +% keys with no value should not be considered ``empty'' and boolean +% \texttt{unset} values should exist. They are just no-op. % % % \begin{macro} % { % \l_@@_setup_type_tl , -% \l_@@_base_language_tl , +% \l_@@_setup_language_tl , % \l_@@_lang_decl_case_tl , % \l_@@_lang_declension_seq , % \l_@@_lang_gender_seq , @@ -746,11 +1126,10 @@ % Store ``current'' type, language, and declension cases in different places % for type-specific and language-specific options handling, notably in % \cs{@@_provide_langfile:n}, \cs{zcRefTypeSetup}, and -% \cs{zcLanguageSetup}. But also for language options retrieval, in -% \cs{@@_get_lang_opt_type:nnnN} and \cs{@@_get_lang_opt_default:nnN}. +% \cs{zcLanguageSetup}, but also for language specific options retrieval. % \begin{macrocode} \tl_new:N \l_@@_setup_type_tl -\tl_new:N \l_@@_base_language_tl +\tl_new:N \l_@@_setup_language_tl \tl_new:N \l_@@_lang_decl_case_tl \seq_new:N \l_@@_lang_declension_seq \seq_new:N \l_@@_lang_gender_seq @@ -760,20 +1139,22 @@ % % \begin{macro} % { -% \c_@@_ref_options_necessarily_not_type_specific_seq , -% \c_@@_ref_options_possibly_type_specific_seq , -% \c_@@_ref_options_type_names_seq , -% \c_@@_ref_options_font_seq , -% \c_@@_ref_options_typesetup_seq , -% \c_@@_ref_options_reference_seq , +% \c_@@_rf_opts_tl_not_type_specific_seq , +% \c_@@_rf_opts_tl_maybe_type_specific_seq , +% \c_@@_rf_opts_seq_refbounds_seq , +% \c_@@_rf_opts_bool_maybe_type_specific_seq , +% \c_@@_rf_opts_tl_type_names_seq , +% \c_@@_rf_opts_tl_font_seq , +% \c_@@_rf_opts_tl_typesetup_seq , +% \c_@@_rf_opts_tl_reference_seq , % } -% Lists of reference format related options in ``categories''. Since -% these options are set in different scopes, and at different places, -% storing the actual lists in centralized variables makes the job not only -% easier later on, but also keeps things consistent. +% Lists of reference format options in ``categories''. Since these +% options are set in different scopes, and at different places, storing +% the actual lists in centralized variables makes the job not only easier +% later on, but also keeps things consistent. % \begin{macrocode} \seq_const_from_clist:Nn - \c_@@_ref_options_necessarily_not_type_specific_seq + \c_@@_rf_opts_tl_not_type_specific_seq { tpairsep , tlistsep , @@ -781,24 +1162,44 @@ notesep , } \seq_const_from_clist:Nn - \c_@@_ref_options_possibly_type_specific_seq + \c_@@_rf_opts_tl_maybe_type_specific_seq { namesep , pairsep , listsep , lastsep , rangesep , - preref , - postref , + namefont , + reffont , + } +\seq_const_from_clist:Nn + \c_@@_rf_opts_seq_refbounds_seq + { + refbounds-first , + refbounds-first-sg , + refbounds-first-pb , + refbounds-first-rb , + refbounds-mid , + refbounds-mid-rb , + refbounds-mid-re , + refbounds-last , + refbounds-last-pe , + refbounds-last-re , + } +\seq_const_from_clist:Nn + \c_@@_rf_opts_bool_maybe_type_specific_seq + { + cap , + abbrev , } % \end{macrocode} % Only ``type names'' are ``necessarily type-specific'', which makes them % somewhat special on the retrieval side of things. In short, they don't have -% their values queried by \cs{@@_get_ref_opt_typeset:nN}, but by +% their values queried by \cs{@@_get_rf_opt_tl:nnnN}, but by % \cs{@@_type_name_setup:}. % \begin{macrocode} \seq_const_from_clist:Nn - \c_@@_ref_options_type_names_seq + \c_@@_rf_opts_tl_type_names_seq { Name-sg , name-sg , @@ -810,71 +1211,156 @@ name-pl-ab , } % \end{macrocode} -% \cs{c_@@_ref_options_font_seq} are technically ``possibly type-specific'', -% but are not ``language-specific'', so we separate them. +% And, finally, some combined groups of the above variables, for convenience. % \begin{macrocode} -\seq_const_from_clist:Nn - \c_@@_ref_options_font_seq +\seq_new:N \c_@@_rf_opts_tl_typesetup_seq +\seq_gconcat:NNN \c_@@_rf_opts_tl_typesetup_seq + \c_@@_rf_opts_tl_maybe_type_specific_seq + \c_@@_rf_opts_tl_type_names_seq +\seq_new:N \c_@@_rf_opts_tl_reference_seq +\seq_gconcat:NNN \c_@@_rf_opts_tl_reference_seq + \c_@@_rf_opts_tl_not_type_specific_seq + \c_@@_rf_opts_tl_maybe_type_specific_seq +% \end{macrocode} +% \end{macro} +% +% +% We set here also the ``derived'' \texttt{refbounds} options, which are the +% same for every option scope. +% +% \begin{macrocode} +\clist_map_inline:nn { - namefont , - reffont , + reference , + typesetup , + langsetup , + langfile , + } + { + \keys_define:nn { zref-clever/ #1 } + { + +refbounds-first .meta:n = + { + refbounds-first = {##1} , + refbounds-first-sg = {##1} , + refbounds-first-pb = {##1} , + refbounds-first-rb = {##1} , + } , + +refbounds-first .default:x = \c_novalue_tl , + +refbounds-mid .meta:n = + { + refbounds-mid = {##1} , + refbounds-mid-rb = {##1} , + refbounds-mid-re = {##1} , + } , + +refbounds-mid .default:x = \c_novalue_tl , + +refbounds-last .meta:n = + { + refbounds-last = {##1} , + refbounds-last-pe = {##1} , + refbounds-last-re = {##1} , + } , + +refbounds-last .default:x = \c_novalue_tl , + +refbounds-rb .meta:n = + { + refbounds-first-rb = {##1} , + refbounds-mid-rb = {##1} , + } , + +refbounds-rb .default:x = \c_novalue_tl , + +refbounds-re .meta:n = + { + refbounds-mid-re = {##1} , + refbounds-last-re = {##1} , + } , + +refbounds-re .default:x = \c_novalue_tl , + +refbounds .meta:n = + { + +refbounds-first = {##1} , + +refbounds-mid = {##1} , + +refbounds-last = {##1} , + } , + +refbounds .default:x = \c_novalue_tl , + refbounds .meta:n = { +refbounds = {##1} } , + refbounds .default:x = \c_novalue_tl , + } } % \end{macrocode} -% And, finally, some combined groups of the above variables, for convenience. +% +% +% \subsection{Languages} +% +% +% \begin{macro}[EXP]{\@@_language_varname:n} +% Defines, and leaves in the input stream, the csname of the variable used +% to store the \meta{base language} (as the value of this variable) for +% a \meta{language} declared for \pkg{zref-clever}. +% \begin{syntax} +% \cs{@@_language_varname:n} \Arg{language} +% \end{syntax} % \begin{macrocode} -\seq_new:N \c_@@_ref_options_typesetup_seq -\seq_gconcat:NNN \c_@@_ref_options_typesetup_seq - \c_@@_ref_options_possibly_type_specific_seq - \c_@@_ref_options_type_names_seq -\seq_gconcat:NNN \c_@@_ref_options_typesetup_seq - \c_@@_ref_options_typesetup_seq - \c_@@_ref_options_font_seq -\seq_new:N \c_@@_ref_options_reference_seq -\seq_gconcat:NNN \c_@@_ref_options_reference_seq - \c_@@_ref_options_necessarily_not_type_specific_seq - \c_@@_ref_options_possibly_type_specific_seq -\seq_gconcat:NNN \c_@@_ref_options_reference_seq - \c_@@_ref_options_reference_seq - \c_@@_ref_options_font_seq +\cs_new:Npn \@@_language_varname:n #1 + { g_@@_declared_language_ #1 _tl } % \end{macrocode} % \end{macro} % +% \begin{macro}[EXP]{\zrefclever_language_varname:n} +% A public version of \cs{@@_language_varname:n} for use in +% \pkg{zref-vario}. +% \begin{macrocode} +\cs_set_eq:NN \zrefclever_language_varname:n + \@@_language_varname:n +% \end{macrocode} +% \end{macro} % +% \begin{macro}[EXP,TF]{\@@_language_if_declared:n} +% A language is considered to be declared for \pkg{zref-clever} if it passes +% this conditional, which requires that a variable with +% \cs{@@_language_varname:n}\texttt{\{\meta{language}\}} exists. +% \begin{syntax} +% \cs{@@_language_if_declared:n(TF)} \Arg{language} +% \end{syntax} +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_language_if_declared:n #1 { T , F , TF } + { + \tl_if_exist:cTF { \@@_language_varname:n {#1} } + { \prg_return_true: } + { \prg_return_false: } + } +\prg_generate_conditional_variant:Nnn + \@@_language_if_declared:n { x } { T , F , TF } +% \end{macrocode} +% \end{macro} % -% \subsection{Languages} -% -% \begin{macro}{\g_@@_languages_prop} -% Stores the names of known languages and the mapping from ``language name'' -% to ``base language name''. Whether or not a language or alias is known to -% \pkg{zref-clever} is decided by its presence in this property list. A -% ``base language'' (loose concept here, meaning just ``the name we gave for -% the language file in that particular language'') is just like any other -% one, the only difference is that the ``language name'' happens to be the -% same as the ``base language name'', in other words, it is an ``alias to -% itself''. +% \begin{macro}[EXP,TF]{\zrefclever_language_if_declared:n} +% A public version of \cs{@@_language_if_declared:n} for use in +% \pkg{zref-vario}. % \begin{macrocode} -\prop_new:N \g_@@_languages_prop +\prg_set_eq_conditional:NNn \zrefclever_language_if_declared:n + \@@_language_if_declared:n { TF } % \end{macrocode} % \end{macro} % % % \begin{macro}[int]{\zcDeclareLanguage} -% Declare a new language for use with \pkg{zref-clever}. \meta{language} is -% taken to be both the ``language name'' and the ``base language name''. -% \oarg{options} receive a \texttt{k=v} set of options, with three valid -% options. The first, \opt{declension}, takes the noun declension cases -% prefixes for \meta{language} as a comma separated list, whose first -% element is taken to be the default case. The second, \opt{gender}, -% receives the genders for \meta{language} as comma separated list. The -% third, \opt{allcaps}, receives no value, and indicates that for -% \meta{language} all nouns must be capitalized for grammatical reasons, in -% which case, the \opt{cap} option is disregarded for \meta{language}. If -% \meta{language} is already known, just warn. This implies a particular -% restriction regarding \oarg{options}, namely that these options, when -% defined by the package, cannot be redefined by the user. This is -% deliberate, otherwise the built-in language files would become much too -% sensitive to this particular user input, and unnecessarily so. -% \cs{zcDeclareLanguage} is preamble only. +% Declare a new language for use with \pkg{zref-clever}. \meta{language} is +% taken to be both the ``language name'' and the ``base language name''. A +% ``base language'' (loose concept here, meaning just ``the name we gave for +% the language file in that particular language'') is just like any other one, +% the only difference is that the ``language name'' happens to be the same as +% the ``base language name'', in other words, it is an ``alias to itself''. +% \oarg{options} receive a \texttt{k=v} set of options, with three valid +% options. The first, \opt{declension}, takes the noun declension cases +% prefixes for \meta{language} as a comma separated list, whose first element +% is taken to be the default case. The second, \opt{gender}, receives the +% genders for \meta{language} as comma separated list. The third, +% \opt{allcaps}, is a boolean, and indicates that for \meta{language} all +% nouns must be capitalized for grammatical reasons, in which case, the +% \opt{cap} option is disregarded for \meta{language}. If \meta{language} is +% already known, just warn. This implies a particular restriction regarding +% \oarg{options}, namely that these options, when defined by the package, +% cannot be redefined by the user. This is deliberate, otherwise the built-in +% language files would become much too sensitive to this particular user +% input, and unnecessarily so. \cs{zcDeclareLanguage} is preamble only. % \begin{syntax} % \cs{zcDeclareLanguage} \oarg{options} \marg{language} % \end{syntax} @@ -884,13 +1370,13 @@ \group_begin: \tl_if_empty:nF {#2} { - \prop_if_in:NnTF \g_@@_languages_prop {#2} + \@@_language_if_declared:nTF {#2} { \msg_warning:nnn { zref-clever } { language-declared } {#2} } { - \prop_gput:Nnn \g_@@_languages_prop {#2} {#2} - \prop_new:c { g_@@_lang_ #2 _prop } - \tl_set:Nn \l_@@_base_language_tl {#2} - \keys_set:nn { zref-clever / declarelang } {#1} + \tl_new:c { \@@_language_varname:n {#2} } + \tl_gset:cn { \@@_language_varname:n {#2} } {#2} + \tl_set:Nn \l_@@_setup_language_tl {#2} + \keys_set:nn { zref-clever/declarelang } {#1} } } \group_end: @@ -903,7 +1389,7 @@ % \begin{macro}[int]{\zcDeclareLanguageAlias} % Declare \meta{language alias} to be an alias of \meta{aliased language} % (or ``base language''). \meta{aliased language} must be already known to -% \pkg{zref-clever}, as stored in \cs{g_@@_languages_prop}. +% \pkg{zref-clever}. % \cs{zcDeclareLanguageAlias} is preamble only. % \begin{syntax} % \cs{zcDeclareLanguageAlias} \marg{language alias} \marg{aliased language} @@ -913,11 +1399,10 @@ { \tl_if_empty:nF {#1} { - \prop_if_in:NnTF \g_@@_languages_prop {#2} + \@@_language_if_declared:nTF {#2} { - \exp_args:NNnx - \prop_gput:Nnn \g_@@_languages_prop {#1} - { \prop_item:Nn \g_@@_languages_prop {#2} } + \tl_gset:cx { \@@_language_varname:n {#1} } + { \tl_use:c { \@@_language_varname:n {#2} } } } { \msg_warning:nnn { zref-clever } { unknown-language-alias } {#2} } } @@ -929,50 +1414,60 @@ % % % \begin{macrocode} -\keys_define:nn { zref-clever / declarelang } +\keys_define:nn { zref-clever/declarelang } { declension .code:n = { - \prop_gput:cnn - { g_@@_lang_ \l_@@_base_language_tl _prop } - { declension } {#1} + \seq_gset_from_clist:cn + { + \@@_opt_varname_language:enn + { \l_@@_setup_language_tl } { declension } { seq } + } + {#1} } , declension .value_required:n = true , gender .code:n = { - \prop_gput:cnn - { g_@@_lang_ \l_@@_base_language_tl _prop } - { gender } {#1} + \seq_gset_from_clist:cn + { + \@@_opt_varname_language:enn + { \l_@@_setup_language_tl } { gender } { seq } + } + {#1} } , gender .value_required:n = true , - allcaps .code:n = + allcaps .choices:nn = + { true , false } { - \prop_gput:cnn - { g_@@_lang_ \l_@@_base_language_tl _prop } - { allcaps } { true } + \use:c { bool_gset_ \l_keys_choice_tl :c } + { + \@@_opt_varname_language:enn + { \l_@@_setup_language_tl } { allcaps } { bool } + } } , - allcaps .value_forbidden:n = true , + allcaps .default:n = true , } % \end{macrocode} % % % -% \begin{macro}{\@@_process_language_options:} +% \begin{macro}{\@@_process_language_settings:} % Auxiliary function for \cs{@@_zcref:nnn}, responsible for processing -% options from \cs{zcDeclareLanguage}. It is necessary to separate them -% from the reference options machinery because their behavior is language -% dependent, but the language itself can also be set as an option -% (\opt{lang}, value stored in \cs{l_@@_ref_language_tl}). Hence, we must -% validate these options after the reference options have been set. It is -% expected to be called right (or soon) after \cs{keys_set:nn} in -% \cs{@@_zcref:nnn}, where current values for \cs{l_@@_ref_language_tl} and -% \cs{l_@@_ref_decl_case_tl} are in place. -% \begin{macrocode} -\cs_new_protected:Npn \@@_process_language_options: - { - \exp_args:NNx \prop_get:NnNTF \g_@@_languages_prop +% language related settings. It is necessary to separate them from the +% reference options machinery for two reasons. First, because their +% behavior is language dependent, but the language itself can also be set as +% an option (\opt{lang}, value stored in \cs{l_@@_ref_language_tl}). +% Second, some of its tasks must be done regardless of any option being +% given (e.g. the default declension case, the \opt{allcaps} option). +% Hence, we must validate the language settings after the reference options +% have been set. It is expected to be called right (or soon) after +% \cs{keys_set:nn} in \cs{@@_zcref:nnn}, where current values for +% \cs{l_@@_ref_language_tl} and \cs{l_@@_ref_decl_case_tl} are in place. +% \begin{macrocode} +\cs_new_protected:Npn \@@_process_language_settings: + { + \@@_language_if_declared:xTF { \l_@@_ref_language_tl } - \l_@@_base_language_tl { % \end{macrocode} % Validate the declension case (\opt{d}) option against the declared cases for @@ -982,16 +1477,13 @@ % clearing the variable, depending on the language setup. And also issues a % warning about it. % \begin{macrocode} - \exp_args:NNx \seq_set_from_clist:Nn - \l_@@_lang_declension_seq + \@@_opt_seq_get:cNF { - \prop_item:cn - { - g_@@_lang_ - \l_@@_base_language_tl _prop - } - { declension } + \@@_opt_varname_language:enn + { \l_@@_ref_language_tl } { declension } { seq } } + \l_@@_lang_declension_seq + { \seq_clear:N \l_@@_lang_declension_seq } \seq_if_empty:NTF \l_@@_lang_declension_seq { \tl_if_empty:NF \l_@@_ref_decl_case_tl @@ -1027,16 +1519,13 @@ % reference language. If the user value for the latter does not match the % genders declared for the former, clear \cs{l_@@_ref_gender_tl} and warn. % \begin{macrocode} - \exp_args:NNx \seq_set_from_clist:Nn - \l_@@_lang_gender_seq + \@@_opt_seq_get:cNF { - \prop_item:cn - { - g_@@_lang_ - \l_@@_base_language_tl _prop - } - { gender } + \@@_opt_varname_language:enn + { \l_@@_ref_language_tl } { gender } { seq } } + \l_@@_lang_gender_seq + { \seq_clear:N \l_@@_lang_gender_seq } \seq_if_empty:NTF \l_@@_lang_gender_seq { \tl_if_empty:NF \l_@@_ref_gender_tl @@ -1064,20 +1553,15 @@ } } % \end{macrocode} -% Ensure the \opt{cap} in \cs{l_@@_ref_options_prop} is set to \texttt{true} -% when the language was declared with \opt{allcaps} option. +% Ensure the general \opt{cap} is set to \texttt{true} when the language was +% declared with \opt{allcaps} option. % \begin{macrocode} - \str_if_eq:eeT + \@@_opt_bool_if:cT { - \prop_item:cn - { - g_@@_lang_ - \l_@@_base_language_tl _prop - } - { allcaps } + \@@_opt_varname_language:enn + { \l_@@_ref_language_tl } { allcaps } { bool } } - { true } - { \prop_put:Nnn \l_@@_ref_options_prop { cap } { true } } + { \keys_set:nn { zref-clever/reference } { cap = true } } } { % \end{macrocode} @@ -1154,13 +1638,11 @@ % \cs{@@_provide_langfile:n} is only meant to load the built-in language % files. For languages declared by the user, or for any settings to a known % language made with \cs{zcLanguageSetup}, values are populated directly to a -% variable \cs{g_@@_lang_\meta{language}_prop}. Hence, there is no need to -% ``load'' anything in this case: definitions and assignments made by the user -% are performed immediately. +% corresponding variables. Hence, there is no need to ``load'' anything in +% this case: definitions and assignments made by the user are performed +% immediately. % % -% \subsubsection*{Provide} -% % \begin{macro}{\g_@@_loaded_langfiles_seq} % Used to keep track of whether a language file has already been loaded or % not. @@ -1169,14 +1651,6 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\l_@@_load_langfile_verbose_bool} -% Controls whether \cs{@@_provide_langfile:n} fails silently or verbosely -% in case of unknown languages or not found language files. -% \begin{macrocode} -\bool_new:N \l_@@_load_langfile_verbose_bool -% \end{macrocode} -% \end{macro} -% % % \begin{macro}{\@@_provide_langfile:n} % Load language file for known \meta{language} if it is available and if it @@ -1189,77 +1663,61 @@ { \group_begin: \@bsphack - \prop_get:NnNTF \g_@@_languages_prop {#1} - \l_@@_base_language_tl + \@@_language_if_declared:nT {#1} { - \seq_if_in:NVF + \seq_if_in:NxF \g_@@_loaded_langfiles_seq - \l_@@_base_language_tl + { \tl_use:c { \@@_language_varname:n {#1} } } { \exp_args:Nx \file_get:nnNTF - { zref-clever- \l_@@_base_language_tl .lang } + { + zref-clever- + \tl_use:c { \@@_language_varname:n {#1} } + .lang + } { \ExplSyntaxOn } \l_tmpa_tl { + \tl_set:Nn \l_@@_setup_language_tl {#1} \tl_clear:N \l_@@_setup_type_tl - \exp_args:NNx \seq_set_from_clist:Nn - \l_@@_lang_declension_seq + \@@_opt_seq_get:cNF { - \prop_item:cn - { - g_@@_lang_ - \l_@@_base_language_tl _prop - } - { declension } + \@@_opt_varname_language:nnn + {#1} { declension } { seq } } + \l_@@_lang_declension_seq + { \seq_clear:N \l_@@_lang_declension_seq } \seq_if_empty:NTF \l_@@_lang_declension_seq { \tl_clear:N \l_@@_lang_decl_case_tl } { \seq_get_left:NN \l_@@_lang_declension_seq \l_@@_lang_decl_case_tl } - \exp_args:NNx \seq_set_from_clist:Nn - \l_@@_lang_gender_seq + \@@_opt_seq_get:cNF { - \prop_item:cn - { - g_@@_lang_ - \l_@@_base_language_tl _prop - } - { gender } + \@@_opt_varname_language:nnn + {#1} { gender } { seq } } - \keys_set:nV { zref-clever / langfile } \l_tmpa_tl - \seq_gput_right:NV \g_@@_loaded_langfiles_seq - \l_@@_base_language_tl - \msg_note:nnx { zref-clever } { langfile-loaded } - { \l_@@_base_language_tl } + \l_@@_lang_gender_seq + { \seq_clear:N \l_@@_lang_gender_seq } + \keys_set:nV { zref-clever/langfile } \l_tmpa_tl + \seq_gput_right:Nx \g_@@_loaded_langfiles_seq + { \tl_use:c { \@@_language_varname:n {#1} } } + \msg_info:nnx { zref-clever } { langfile-loaded } + { \tl_use:c { \@@_language_varname:n {#1} } } } { - \bool_if:NT \l_@@_load_langfile_verbose_bool - { - \msg_warning:nnx { zref-clever } { langfile-not-available } - { \l_@@_base_language_tl } - } % \end{macrocode} % Even if we don't have the actual language file, we register it as % ``loaded''. At this point, it is a known language, properly declared. -% There is no point in trying to load it multiple times, because users cannot -% really provide the language files (well, technically they could, but we are -% working so they don't need to, and have better ways to do what they want). -% And if the users had provided some language-specific options themselves, by -% means of \cs{zcLanguageSetup}, everything would be in place, and they could -% use the \opt{lang} option multiple times, and the -% \texttt{langfile-not-available} warning would never go away. -% \begin{macrocode} - \seq_gput_right:NV \g_@@_loaded_langfiles_seq - \l_@@_base_language_tl +% There is no point in trying to load it multiple times, if it was not found +% the first time, it won't be the next. +% \begin{macrocode} + \seq_gput_right:Nx \g_@@_loaded_langfiles_seq + { \tl_use:c { \@@_language_varname:n {#1} } } } } } - { - \bool_if:NT \l_@@_load_langfile_verbose_bool - { \msg_warning:nnn { zref-clever } { unknown-language-load } {#1} } - } \@esphack \group_end: } @@ -1268,60 +1726,6 @@ % \end{macro} % % -% \begin{macro}{\@@_provide_langfile_verbose:n} -% Does the same as \cs{@@_provide_langfile:n}, but warns if the loading of -% the language file has failed. -% \begin{syntax} -% \cs{@@_provide_langfile_verbose:n} \Arg{language} -% \end{syntax} -% \begin{macrocode} -\cs_new_protected:Npn \@@_provide_langfile_verbose:n #1 - { - \group_begin: - \bool_set_true:N \l_@@_load_langfile_verbose_bool - \@@_provide_langfile:n {#1} - \group_end: - } -\cs_generate_variant:Nn \@@_provide_langfile_verbose:n { x } -% \end{macrocode} -% \end{macro} -% -% -% \begin{macro} -% { -% \@@_provide_lang_opt_type:nn , -% \@@_provide_lang_opt_default:nn , -% } -% A couple of auxiliary functions for the of -% \texttt{{zref-clever/langfile}} keys set in -% \cs{@@_provide_langfile:n}. They respectively ``provide'' (i.e. set if -% it value does not exist, do nothing if it already does) ``type-specific'' -% and ``default'' language options. Both receive \meta{key} and -% \meta{value} as arguments, but \cs{@@_provide_lang_opt_type:nn} -% relies on the current value of \cs{l_@@_setup_type_tl}, as set by the -% \texttt{type} key. -% \begin{syntax} -% \cs{@@_provide_lang_opt_type:nn} \Arg{key} \Arg{value} -% \cs{@@_provide_lang_opt_default:nn} \Arg{key} \Arg{value} -% \end{syntax} -% \begin{macrocode} -\cs_new_protected:Npn \@@_provide_lang_opt_type:nn #1#2 - { - \exp_args:Nnx \prop_gput_if_new:cnn - { g_@@_lang_ \l_@@_base_language_tl _prop } - { type- \l_@@_setup_type_tl - #1 } {#2} - } -\cs_generate_variant:Nn \@@_provide_lang_opt_type:nn { nV } -\cs_new_protected:Npn \@@_provide_lang_opt_default:nn #1#2 - { - \prop_gput_if_new:cnn - { g_@@_lang_ \l_@@_base_language_tl _prop } - { default- #1 } {#2} - } -\cs_generate_variant:Nn \@@_provide_lang_opt_default:nn { nV } -% \end{macrocode} -% \end{macro} -% % % The set of keys for \texttt{{zref-clever/langfile}}, which is used to % process the language files in \cs{@@_provide_langfile:n}. The no-op cases @@ -1330,7 +1734,7 @@ % placed there nevertheless, and can be leveraged in regression tests. % % \begin{macrocode} -\keys_define:nn { zref-clever / langfile } +\keys_define:nn { zref-clever/langfile } { type .code:n = { @@ -1344,14 +1748,14 @@ \seq_if_empty:NTF \l_@@_lang_declension_seq { \msg_info:nnxx { zref-clever } { language-no-decl-setup } - { \l_@@_base_language_tl } {#1} + { \l_@@_setup_language_tl } {#1} } { \seq_if_in:NnTF \l_@@_lang_declension_seq {#1} { \tl_set:Nn \l_@@_lang_decl_case_tl {#1} } { \msg_info:nnxx { zref-clever } { unknown-decl-case } - {#1} { \l_@@_base_language_tl } + {#1} { \l_@@_setup_language_tl } \seq_get_left:NN \l_@@_lang_declension_seq \l_@@_lang_decl_case_tl } @@ -1359,12 +1763,13 @@ } , case .value_required:n = true , + gender .default:x = \c_novalue_tl , gender .code:n = { \seq_if_empty:NTF \l_@@_lang_gender_seq { \msg_info:nnxxx { zref-clever } { language-no-gender } - { \l_@@_base_language_tl } { gender } {#1} + { \l_@@_setup_language_tl } { gender } {#1} } { \tl_if_empty:NTF \l_@@_setup_type_tl @@ -1373,71 +1778,64 @@ { option-only-type-specific } { gender } } { - \clist_clear:N \l_tmpa_clist - \clist_map_inline:nn {#1} + \tl_if_novalue:nF {#1} { - \seq_if_in:NnTF \l_@@_lang_gender_seq {##1} - { \clist_put_right:Nn \l_tmpa_clist {##1} } + \seq_clear:N \l_tmpa_seq + \clist_map_inline:nn {#1} { - \msg_info:nnxx { zref-clever } - { gender-not-declared } - { \l_@@_base_language_tl } {##1} + \seq_if_in:NnTF \l_@@_lang_gender_seq {##1} + { \seq_put_right:Nn \l_tmpa_seq {##1} } + { + \msg_info:nnxx { zref-clever } + { gender-not-declared } + { \l_@@_setup_language_tl } {##1} + } + } + \@@_opt_seq_if_set:cF + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + { gender } + { seq } + } + { + \seq_gset_eq:cN + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + { gender } + { seq } + } + \l_tmpa_seq } - } - \clist_if_empty:NF \l_tmpa_clist - { - \exp_args:Nnx \@@_provide_lang_opt_type:nn - { gender } { \clist_use:Nn \l_tmpa_clist { , } } } } } } , - gender .value_required:n = true , - - cap .choices:nn = - { true , false } - { - \tl_if_empty:NTF \l_@@_setup_type_tl - { - \@@_provide_lang_opt_default:nV - { cap } \l_keys_choice_tl - } - { - \@@_provide_lang_opt_type:nV - { cap } \l_keys_choice_tl - } - } , - cap .default:n = true , - nocap .meta:n = { cap = false } , - nocap .value_forbidden:n = true , - - abbrev .choices:nn = - { true , false } - { - \tl_if_empty:NTF \l_@@_setup_type_tl - { - \@@_provide_lang_opt_default:nV - { abbrev } \l_keys_choice_tl - } - { - \@@_provide_lang_opt_type:nV - { abbrev } \l_keys_choice_tl - } - } , - abbrev .default:n = true , - noabbrev .meta:n = { abbrev = false }, - noabbrev .value_forbidden:n = true , } \seq_map_inline:Nn - \c_@@_ref_options_necessarily_not_type_specific_seq + \c_@@_rf_opts_tl_not_type_specific_seq { - \keys_define:nn { zref-clever / langfile } + \keys_define:nn { zref-clever/langfile } { - #1 .value_required:n = true , + #1 .default:x = \c_novalue_tl , #1 .code:n = { \tl_if_empty:NTF \l_@@_setup_type_tl - { \@@_provide_lang_opt_default:nn {#1} {##1} } + { + \tl_if_novalue:nF {##1} + { + \@@_opt_tl_gset_if_new:cn + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { tl } + } + {##1} + } + } { \msg_info:nnn { zref-clever } { option-not-type-specific } {#1} @@ -1446,25 +1844,48 @@ } } \seq_map_inline:Nn - \c_@@_ref_options_possibly_type_specific_seq + \c_@@_rf_opts_tl_maybe_type_specific_seq { - \keys_define:nn { zref-clever / langfile } + \keys_define:nn { zref-clever/langfile } { - #1 .value_required:n = true , + #1 .default:x = \c_novalue_tl , #1 .code:n = { \tl_if_empty:NTF \l_@@_setup_type_tl - { \@@_provide_lang_opt_default:nn {#1} {##1} } - { \@@_provide_lang_opt_type:nn {#1} {##1} } + { + \tl_if_novalue:nF {##1} + { + \@@_opt_tl_gset_if_new:cn + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { tl } + } + {##1} + } + } + { + \tl_if_novalue:nF {##1} + { + \@@_opt_tl_gset_if_new:cn + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { tl } + } + {##1} + } + } } , } } \seq_map_inline:Nn - \c_@@_ref_options_type_names_seq + \c_@@_rf_opts_tl_type_names_seq { - \keys_define:nn { zref-clever / langfile } + \keys_define:nn { zref-clever/langfile } { - #1 .value_required:n = true , + #1 .default:x = \c_novalue_tl , #1 .code:n = { \tl_if_empty:NTF \l_@@_setup_type_tl @@ -1474,37 +1895,230 @@ } { \tl_if_empty:NTF \l_@@_lang_decl_case_tl - { \@@_provide_lang_opt_type:nn {#1} {##1} } { - \@@_provide_lang_opt_type:nn - { \l_@@_lang_decl_case_tl - #1 } {##1} + \tl_if_novalue:nF {##1} + { + \@@_opt_tl_gset_if_new:cn + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { tl } + } + {##1} + } + } + { + \tl_if_novalue:nF {##1} + { + \@@_opt_tl_gset_if_new:cn + { + \@@_opt_varname_lang_type:eeen + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + { \l_@@_lang_decl_case_tl - #1 } { tl } + } + {##1} + } + } + } + } , + } + } +\seq_map_inline:Nn + \c_@@_rf_opts_seq_refbounds_seq + { + \keys_define:nn { zref-clever/langfile } + { + #1 .default:x = \c_novalue_tl , + #1 .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \tl_if_novalue:nF {##1} + { + \@@_opt_seq_if_set:cF + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } {#1} { seq } + } + { + \seq_gclear:N \g_tmpa_seq + \@@_opt_seq_gset_clist_split:Nn + \g_tmpa_seq {##1} + \bool_lazy_or:nnTF + { \tl_if_empty_p:n {##1} } + { + \int_compare_p:nNn + { \seq_count:N \g_tmpa_seq } = { 4 } + } + { + \seq_gset_eq:cN + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { seq } + } + \g_tmpa_seq + } + { + \msg_info:nnxx { zref-clever } + { refbounds-must-be-four } + {#1} { \seq_count:N \g_tmpa_seq } + } + } + } + } + { + \tl_if_novalue:nF {##1} + { + \@@_opt_seq_if_set:cF + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } {#1} { seq } + } + { + \seq_gclear:N \g_tmpa_seq + \@@_opt_seq_gset_clist_split:Nn + \g_tmpa_seq {##1} + \bool_lazy_or:nnTF + { \tl_if_empty_p:n {##1} } + { + \int_compare_p:nNn + { \seq_count:N \g_tmpa_seq } = { 4 } + } + { + \seq_gset_eq:cN + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { seq } + } + \g_tmpa_seq + } + { + \msg_info:nnxx { zref-clever } + { refbounds-must-be-four } + {#1} { \seq_count:N \g_tmpa_seq } + } + } } } } , } } +\seq_map_inline:Nn + \c_@@_rf_opts_bool_maybe_type_specific_seq + { + \keys_define:nn { zref-clever/langfile } + { + #1 .choice: , + #1 / true .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \@@_opt_bool_if_set:cF + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { bool } + } + { + \bool_gset_true:c + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { bool } + } + } + } + { + \@@_opt_bool_if_set:cF + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { bool } + } + { + \bool_gset_true:c + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { bool } + } + } + } + } , + #1 / false .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \@@_opt_bool_if_set:cF + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { bool } + } + { + \bool_gset_false:c + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { bool } + } + } + } + { + \@@_opt_bool_if_set:cF + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { bool } + } + { + \bool_gset_false:c + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { bool } + } + } + } + } , + #1 / unset .code:n = { } , + #1 .default:n = true , + no #1 .meta:n = { #1 = false } , + no #1 .value_forbidden:n = true , + } + } % \end{macrocode} % % % -% \subsubsection*{Fallback} -% -% All ``strings'' queried with \cs{@@_get_ref_opt_typeset:nN} -- in practice, -% those in either \cs{c_@@_ref_options_necessarily_not_type_specific_seq} or -% \cs{c_@@_ref_options_possibly_type_specific_seq} -- must have their values -% set for ``fallback'', even if to empty ones, since this is what will be -% retrieved in the absence of a proper language-specific option, which will be -% the case if \pkg{babel} or \pkg{polyglossia} is loaded and sets a language -% which \pkg{zref-clever} does not know. On the other hand, ``type names'' -% are not looked for in ``fallback'', since it is indeed impossible to provide -% any reasonable value for them for a ``specified but unknown language''. -% Also ``font'' options -- those in \cs{c_@@_ref_options_font_seq}, and -% queried with \cs{@@_get_ref_opt_font:nN} -- do not need to be provided here, -% since the later function sets an empty value if the option is not found. +% It is convenient for a number of language typesetting options (some basic +% separators) to have some ``fallback'' value available in case \pkg{babel} or +% \pkg{polyglossia} is loaded and sets a language which \pkg{zref-clever} does +% not know. On the other hand, ``type names'' are not looked for in +% ``fallback'', since it is indeed impossible to provide any reasonable value +% for them for a ``specified but unknown language''. Other typesetting +% options, for which it is not a problem being empty, need not be catered for +% with a fallback value. % % \begin{macrocode} -\prop_new:N \g_@@_fallback_unknown_lang_prop -\prop_gset_from_keyval:Nn \g_@@_fallback_unknown_lang_prop +\cs_new_protected:Npn \@@_opt_tl_cset_fallback:nn #1#2 + { + \tl_const:cn + { \@@_opt_varname_fallback:nn {#1} { tl } } {#2} + } +\keyval_parse:nnn + { } + { \@@_opt_tl_cset_fallback:nn } { tpairsep = {,~} , tlistsep = {,~} , @@ -1515,96 +2129,8 @@ listsep = {,~} , lastsep = {,~} , rangesep = {\textendash} , - preref = {} , - postref = {} , - } -% \end{macrocode} -% -% -% -% \subsubsection*{Get language options} -% -% \begin{macro}{\@@_get_lang_opt_type:nnnNF} -% Get type-specific language option of \meta{key} for \meta{type} and -% \meta{language}, and store it in \meta{tl variable} if found. If not -% found, leave the \meta{false code} on the stream, in which case the value -% of \meta{tl variable} should not be relied upon. -% \begin{syntax} -% \cs{@@_get_lang_opt_type:nnnNF} \Arg{language} \Arg{type} \Arg{key} -% ~~\meta{tl variable} \Arg{false code} -% \end{syntax} -% \begin{macrocode} -\prg_new_protected_conditional:Npnn - \@@_get_lang_opt_type:nnnN #1#2#3#4 { F } - { - \prop_get:NnNTF \g_@@_languages_prop {#1} - \l_@@_base_language_tl - { - \prop_get:cnNTF - { g_@@_lang_ \l_@@_base_language_tl _prop } - { type- #2 - #3 } #4 - { \prg_return_true: } - { \prg_return_false: } - } - { \prg_return_false: } } -\prg_generate_conditional_variant:Nnn - \@@_get_lang_opt_type:nnnN { xxxN , xxnN } { F } % \end{macrocode} -% \end{macro} -% -% -% \begin{macro}{\@@_get_lang_opt_default:nnNF} -% Get default language option of \meta{key} for \meta{language}, and store -% it in \meta{tl variable} if found. If not found, leave the \meta{false -% code} on the stream, in which case the value of \meta{tl variable} should -% not be relied upon. -% \begin{syntax} -% \cs{@@_get_lang_opt_default:nnNF} \Arg{language} \Arg{key} -% ~~\meta{tl variable} \Arg{false code} -% \end{syntax} -% \begin{macrocode} -\prg_new_protected_conditional:Npnn - \@@_get_lang_opt_default:nnN #1#2#3 { F } - { - \prop_get:NnNTF \g_@@_languages_prop {#1} - \l_@@_base_language_tl - { - \prop_get:cnNTF - { g_@@_lang_ \l_@@_base_language_tl _prop } - { default- #2 } #3 - { \prg_return_true: } - { \prg_return_false: } - } - { \prg_return_false: } - } -\prg_generate_conditional_variant:Nnn - \@@_get_lang_opt_default:nnN { xnN } { F } -% \end{macrocode} -% \end{macro} -% -% -% \begin{macro}{\@@_get_fallback_unknown_lang_opt:nNF} -% Get fallback language option of \meta{key}, and store it in \meta{tl -% variable} if found. If not found, leave the \meta{false code} on the -% stream, in which case the value of \meta{tl variable} should not be relied -% upon. -% \begin{syntax} -% \cs{@@_get_fallback_unknown_lang_opt:nNF} \Arg{key} -% ~~\meta{tl variable} \Arg{false code} -% \end{syntax} -% \begin{macrocode} -% {<key>}<tl var to set> -\prg_new_protected_conditional:Npnn - \@@_get_fallback_unknown_lang_opt:nN #1#2 { F } - { - \prop_get:NnNTF \g_@@_fallback_unknown_lang_prop - { #1 } #2 - { \prg_return_true: } - { \prg_return_false: } - } -% \end{macrocode} -% \end{macro} % % % @@ -1646,7 +2172,7 @@ % % \begin{macrocode} \tl_new:N \l_@@_ref_property_tl -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { ref .code:n = { @@ -1671,7 +2197,7 @@ % \begin{macrocode} \bool_new:N \l_@@_typeset_ref_bool \bool_new:N \l_@@_typeset_name_bool -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { typeset .choice: , typeset / both .code:n = @@ -1705,7 +2231,7 @@ % % \begin{macrocode} \bool_new:N \l_@@_typeset_sort_bool -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { sort .bool_set:N = \l_@@_typeset_sort_bool , sort .initial:n = true , @@ -1726,7 +2252,7 @@ % % \begin{macrocode} \seq_new:N \l_@@_typesort_seq -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { typesort .code:n = { @@ -1748,7 +2274,7 @@ % % \begin{macrocode} \bool_new:N \l_@@_typeset_compress_bool -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { comp .bool_set:N = \l_@@_typeset_compress_bool , comp .initial:n = true , @@ -1764,7 +2290,7 @@ % % \begin{macrocode} \bool_new:N \l_@@_typeset_range_bool -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { range .bool_set:N = \l_@@_typeset_range_bool , range .initial:n = false , @@ -1776,30 +2302,14 @@ % % \subsubsection*{\opt{cap} and \opt{capfirst} options} % +% The \opt{cap} option is currently being handled with other reference format +% option booleans at \cs{c_@@_rf_opts_bool_maybe_type_specific_seq}. +% % \begin{macrocode} -\bool_new:N \l_@@_capitalize_first_bool -\keys_define:nn { zref-clever / reference } +\bool_new:N \l_@@_capfirst_bool +\keys_define:nn { zref-clever/reference } { - cap .code:n = - { - \tl_if_empty:nTF {#1} - { \prop_remove:Nn \l_@@_ref_options_prop { cap } } - { - \bool_lazy_or:nnTF - { \str_if_eq_p:nn {#1} { true } } - { \str_if_eq_p:nn {#1} { false } } - { \prop_put:Nnn \l_@@_ref_options_prop { cap } {#1} } - { - \msg_warning:nnn { zref-clever } - { key-boolean-or-empty } {#1} - } - } - } , - cap .default:n = true , - nocap .meta:n = { cap = false } , - nocap .value_forbidden:n = true , - - capfirst .bool_set:N = \l_@@_capitalize_first_bool , + capfirst .bool_set:N = \l_@@_capfirst_bool , capfirst .initial:n = false , capfirst .default:n = true , } @@ -1808,29 +2318,13 @@ % % \subsubsection*{\opt{abbrev} and \opt{noabbrevfirst} options} % +% The \opt{abbrev} option is currently being handled with other reference +% format option booleans at \cs{c_@@_rf_opts_bool_maybe_type_specific_seq}. +% % \begin{macrocode} \bool_new:N \l_@@_noabbrev_first_bool -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { - abbrev .code:n = - { - \tl_if_empty:nTF {#1} - { \prop_remove:Nn \l_@@_ref_options_prop { abbrev } } - { - \bool_lazy_or:nnTF - { \str_if_eq_p:nn {#1} { true } } - { \str_if_eq_p:nn {#1} { false } } - { \prop_put:Nnn \l_@@_ref_options_prop { abbrev } {#1} } - { - \msg_warning:nnn { zref-clever } - { key-boolean-or-empty } {#1} - } - } - } , - abbrev .default:n = true , - noabbrev .meta:n = { abbrev = false }, - noabbrev .value_forbidden:n = true , - noabbrevfirst .bool_set:N = \l_@@_noabbrev_first_bool , noabbrevfirst .initial:n = false , noabbrevfirst .default:n = true , @@ -1842,11 +2336,11 @@ % \subsubsection*{\opt{S} option} % % \begin{macrocode} -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { S .meta:n = - { capfirst = true , noabbrevfirst = true }, - S .value_forbidden:n = true , + { capfirst = {#1} , noabbrevfirst = {#1} }, + S .default:n = true , } % \end{macrocode} % @@ -1854,28 +2348,38 @@ % \subsubsection*{\opt{hyperref} option} % % \begin{macrocode} -\bool_new:N \l_@@_use_hyperref_bool -\bool_new:N \l_@@_warn_hyperref_bool -\keys_define:nn { zref-clever / reference } +\bool_new:N \l_@@_hyperlink_bool +\bool_new:N \l_@@_hyperref_warn_bool +\keys_define:nn { zref-clever/reference } { hyperref .choice: , hyperref / auto .code:n = { - \bool_set_true:N \l_@@_use_hyperref_bool - \bool_set_false:N \l_@@_warn_hyperref_bool + \bool_set_true:N \l_@@_hyperlink_bool + \bool_set_false:N \l_@@_hyperref_warn_bool } , hyperref / true .code:n = { - \bool_set_true:N \l_@@_use_hyperref_bool - \bool_set_true:N \l_@@_warn_hyperref_bool + \bool_set_true:N \l_@@_hyperlink_bool + \bool_set_true:N \l_@@_hyperref_warn_bool } , hyperref / false .code:n = { - \bool_set_false:N \l_@@_use_hyperref_bool - \bool_set_false:N \l_@@_warn_hyperref_bool + \bool_set_false:N \l_@@_hyperlink_bool + \bool_set_false:N \l_@@_hyperref_warn_bool } , hyperref .initial:n = auto , - hyperref .default:n = auto + hyperref .default:n = true , +% \end{macrocode} +% \opt{nohyperref} is provided mainly as a means to inhibit hyperlinking +% locally in \pkg{zref-vario}'s commands without the need to be setting +% \pkg{zref-clever}'s internal variables directly. What limits setting +% \opt{hyperref} out of the preamble is that enabling hyperlinks requires +% loading packages. But \opt{nohyperref} can only disable them, so we can use +% it in the document body too. +% \begin{macrocode} + nohyperref .meta:n = { hyperref = false } , + nohyperref .value_forbidden:n = true , } % \end{macrocode} % @@ -1884,18 +2388,20 @@ { \@@_if_package_loaded:nTF { hyperref } { - \bool_if:NT \l_@@_use_hyperref_bool + \bool_if:NT \l_@@_hyperlink_bool { \RequirePackage { zref-hyperref } } } { - \bool_if:NT \l_@@_warn_hyperref_bool + \bool_if:NT \l_@@_hyperref_warn_bool { \msg_warning:nn { zref-clever } { missing-hyperref } } - \bool_set_false:N \l_@@_use_hyperref_bool + \bool_set_false:N \l_@@_hyperlink_bool } - \keys_define:nn { zref-clever / reference } + \keys_define:nn { zref-clever/reference } { hyperref .code:n = - { \msg_warning:nn { zref-clever } { hyperref-preamble-only } } + { \msg_warning:nn { zref-clever } { hyperref-preamble-only } } , + nohyperref .code:n = + { \bool_set_false:N \l_@@_hyperlink_bool } , } } % \end{macrocode} @@ -1906,7 +2412,7 @@ % % \begin{macrocode} \str_new:N \l_@@_nameinlink_str -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { nameinlink .choice: , nameinlink / true .code:n = @@ -1923,15 +2429,17 @@ % \end{macrocode} % % -% \subsubsection*{\opt{preposinlink} option} +% \subsubsection*{\opt{preposinlink} option (deprecated)} % % \begin{macrocode} -\bool_new:N \l_@@_preposinlink_bool -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { - preposinlink .bool_set:N = \l_@@_preposinlink_bool , - preposinlink .initial:n = false , - preposinlink .default:n = true , + preposinlink .code:n = + { + % NOTE Option deprecated in 2022-01-12 for v0.2.0-alpha. + \msg_warning:nnnn { zref-clever }{ option-deprecated } + { preposinlink } { refbounds } + } , } % \end{macrocode} % @@ -1996,22 +2504,18 @@ \tl_set:Nn \l_@@_main_language_tl { english } } } -% \end{macrocode} -% Provide default value for \cs{l_@@_ref_language_tl} corresponding to option -% \opt{current}, but do so outside of the \pkg{l3keys} machinery (that is, -% instead of using \texttt{.initial:n}), so that we are able to distinguish -% when the user actually gave the option, in which case the language file -% loading is done verbosely, from when we are setting the default value -% (here), in which case the language file loading is done silently. -% \begin{macrocode} - \tl_set:Nn \l_@@_ref_language_tl - { \l_@@_current_language_tl } } % \end{macrocode} % +% \begin{macro}{\l_zrefclever_ref_language_tl} +% A public version of \cs{l_@@_ref_language_tl} for use in \pkg{zref-vario}. +% \begin{macrocode} +\tl_set:Nn \l_zrefclever_ref_language_tl { \l_@@_ref_language_tl } +% \end{macrocode} +% \end{macro} % % \begin{macrocode} -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { lang .code:n = { @@ -2023,32 +2527,27 @@ { \tl_set:Nn \l_@@_ref_language_tl { \l_@@_current_language_tl } - \@@_provide_langfile_verbose:x - { \l_@@_ref_language_tl } } { main } { \tl_set:Nn \l_@@_ref_language_tl { \l_@@_main_language_tl } - \@@_provide_langfile_verbose:x - { \l_@@_ref_language_tl } } } { - \prop_if_in:NnTF \g_@@_languages_prop {#1} - { \tl_set:Nn \l_@@_ref_language_tl {#1} } + \tl_set:Nn \l_@@_ref_language_tl {#1} + \@@_language_if_declared:nF {#1} { \msg_warning:nnn { zref-clever } { unknown-language-opt } {#1} - \tl_set:Nn \l_@@_ref_language_tl - { \l_@@_current_language_tl } } - \@@_provide_langfile_verbose:x - { \l_@@_ref_language_tl } } + \@@_provide_langfile:x + { \l_@@_ref_language_tl } } } , + lang .initial:n = current , lang .value_required:n = true , } % \end{macrocode} @@ -2060,18 +2559,11 @@ \AddToHook { begindocument } { % \end{macrocode} -% If any \opt{lang} option has been given by the user, the corresponding -% language is already loaded, otherwise, ensure the default one -% (\texttt{current}) gets loaded early, but not verbosely. -% \begin{macrocode} - \@@_provide_langfile:x { \l_@@_ref_language_tl } -% \end{macrocode} % Redefinition of the \texttt{lang} key option for the document body. Also, -% drop the verbose language file loading in the document body, as it can -% become intrusive depending on the use case, and does not provide much -% ``juice'' anyway: in \cs{zcref} missing names warnings will already ensue. +% drop the language file loading in the document body, it is somewhat +% redundant, since \cs{@@_zcref:nnn} already ensures it. % \begin{macrocode} - \keys_define:nn { zref-clever / reference } + \keys_define:nn { zref-clever/reference } { lang .code:n = { @@ -2081,32 +2573,23 @@ { \tl_set:Nn \l_@@_ref_language_tl { \l_@@_current_language_tl } - \@@_provide_langfile:x - { \l_@@_ref_language_tl } } { main } { \tl_set:Nn \l_@@_ref_language_tl { \l_@@_main_language_tl } - \@@_provide_langfile:x - { \l_@@_ref_language_tl } } } { - \prop_if_in:NnTF \g_@@_languages_prop {#1} - { \tl_set:Nn \l_@@_ref_language_tl {#1} } + \tl_set:Nn \l_@@_ref_language_tl {#1} + \@@_language_if_declared:nF {#1} { \msg_warning:nnn { zref-clever } { unknown-language-opt } {#1} - \tl_set:Nn \l_@@_ref_language_tl - { \l_@@_current_language_tl } } - \@@_provide_langfile:x - { \l_@@_ref_language_tl } } } , - lang .value_required:n = true , } } } @@ -2128,18 +2611,18 @@ % % \begin{macrocode} \tl_new:N \l_@@_ref_decl_case_tl -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { d .code:n = { \msg_warning:nnn { zref-clever } { option-document-only } { d } } , } \AddToHook { begindocument } { - \keys_define:nn { zref-clever / reference } + \keys_define:nn { zref-clever/reference } { % \end{macrocode} % We just store the value at this point, which is validated by -% \cs{@@_process_language_options:} after \cs{keys_set:nn}. +% \cs{@@_process_language_settings:} after \cs{keys_set:nn}. % \begin{macrocode} d .tl_set:N = \l_@@_ref_decl_case_tl , d .value_required:n = true , @@ -2158,7 +2641,7 @@ \bool_new:N \l_@@_nudge_singular_bool \bool_new:N \l_@@_nudge_gender_bool \tl_new:N \l_@@_ref_gender_tl -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { nudge .choice: , nudge / true .code:n = @@ -2219,11 +2702,11 @@ } \AddToHook { begindocument } { - \keys_define:nn { zref-clever / reference } + \keys_define:nn { zref-clever/reference } { % \end{macrocode} % We just store the value at this point, which is validated by -% \cs{@@_process_language_options:} after \cs{keys_set:nn}. +% \cs{@@_process_language_settings:} after \cs{keys_set:nn}. % \begin{macrocode} g .tl_set:N = \l_@@_ref_gender_tl , g .value_required:n = true , @@ -2245,7 +2728,7 @@ % % \begin{macrocode} \tl_new:N \l_@@_ref_typeset_font_tl -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { font .tl_set:N = \l_@@_ref_typeset_font_tl } % \end{macrocode} % @@ -2254,14 +2737,14 @@ % \subsubsection*{\opt{titleref} option} % % \begin{macrocode} -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { titleref .code:n = { \RequirePackage { zref-titleref } } , titleref .value_forbidden:n = true , } \AddToHook { begindocument } { - \keys_define:nn { zref-clever / reference } + \keys_define:nn { zref-clever/reference } { titleref .code:n = { \msg_warning:nn { zref-clever } { titleref-preamble-only } } @@ -2274,7 +2757,7 @@ % % \begin{macrocode} \tl_new:N \l_@@_zcref_note_tl -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { note .tl_set:N = \l_@@_zcref_note_tl , note .value_required:n = true , @@ -2289,7 +2772,7 @@ % \begin{macrocode} \bool_new:N \l_@@_zrefcheck_available_bool \bool_new:N \l_@@_zcref_with_check_bool -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { check .code:n = { \RequirePackage { zref-check } } , check .value_forbidden:n = true , @@ -2299,7 +2782,7 @@ \@@_if_package_loaded:nTF { zref-check } { \bool_set_true:N \l_@@_zrefcheck_available_bool - \keys_define:nn { zref-clever / reference } + \keys_define:nn { zref-clever/reference } { check .code:n = { @@ -2311,7 +2794,7 @@ } { \bool_set_false:N \l_@@_zrefcheck_available_bool - \keys_define:nn { zref-clever / reference } + \keys_define:nn { zref-clever/reference } { check .value_forbidden:n = false , check .code:n = @@ -2332,7 +2815,7 @@ % % \begin{macrocode} \prop_new:N \l_@@_counter_type_prop -\keys_define:nn { zref-clever / label } +\keys_define:nn { zref-clever/label } { countertype .code:n = { @@ -2396,7 +2879,7 @@ % % \begin{macrocode} \seq_new:N \l_@@_counter_resetters_seq -\keys_define:nn { zref-clever / label } +\keys_define:nn { zref-clever/label } { counterresetters .code:n = { @@ -2435,7 +2918,7 @@ % % \begin{macrocode} \prop_new:N \l_@@_counter_resetby_prop -\keys_define:nn { zref-clever / label } +\keys_define:nn { zref-clever/label } { counterresetby .code:n = { @@ -2476,7 +2959,7 @@ % % \begin{macrocode} \tl_new:N \l_@@_current_counter_tl -\keys_define:nn { zref-clever / label } +\keys_define:nn { zref-clever/label } { currentcounter .tl_set:N = \l_@@_current_counter_tl , currentcounter .value_required:n = true , @@ -2491,7 +2974,7 @@ % \begin{macrocode} \bool_new:N \g_@@_nocompat_bool \seq_new:N \g_@@_nocompat_modules_seq -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { nocompat .code:n = { @@ -2511,7 +2994,7 @@ } \AddToHook { begindocument } { - \keys_define:nn { zref-clever / reference } + \keys_define:nn { zref-clever/reference } { nocompat .code:n = { @@ -2566,53 +3049,121 @@ % This is a set of options related to reference typesetting which receive % equal treatment and, hence, are handled in batch. Since we are dealing with % options to be passed to \cs{zcref} or to \cs{zcsetup} or at load time, only -% ``not necessarily type-specific'' options are pertinent here. However, they -% \emph{may} either be type-specific or language-specific, and thus must be -% stored in a property list, \cs{l_@@_ref_options_prop}, in order to be -% retrieved from the option \emph{name} by \cs{@@_get_ref_opt_typeset:nN} and -% \cs{@@_get_ref_opt_font:nN} according to context and precedence rules. +% ``not necessarily type-specific'' options are pertinent here. % -% The keys are set so that any value, including an empty one, is added to -% \cs{l_@@_ref_options_prop}, while a key with \emph{no value} removes the -% property from the list, so that these options can then fall back to lower -% precedence levels settings. For discussion about the used technique, see -% \zcref{sec:zcreftypesetup}. % % \begin{macrocode} -\prop_new:N \l_@@_ref_options_prop \seq_map_inline:Nn - \c_@@_ref_options_reference_seq + \c_@@_rf_opts_tl_reference_seq { - \keys_define:nn { zref-clever / reference } + \keys_define:nn { zref-clever/reference } { - #1 .default:V = \c_novalue_tl , + #1 .default:x = \c_novalue_tl , #1 .code:n = { \tl_if_novalue:nTF {##1} - { \prop_remove:Nn \l_@@_ref_options_prop {#1} } - { \prop_put:Nnn \l_@@_ref_options_prop {#1} {##1} } + { + \@@_opt_tl_unset:c + { \@@_opt_varname_general:nn {#1} { tl } } + } + { + \tl_set:cn + { \@@_opt_varname_general:nn {#1} { tl } } + {##1} + } } , } } -\keys_define:nn { zref-clever / reference } +\keys_define:nn { zref-clever/reference } { refpre .code:n = { % NOTE Option deprecated in 2022-01-10 for v0.1.2-alpha. \msg_warning:nnnn { zref-clever }{ option-deprecated } - { refpre } { preref } + { refpre } { refbounds } } , refpos .code:n = { % NOTE Option deprecated in 2022-01-10 for v0.1.2-alpha. \msg_warning:nnnn { zref-clever }{ option-deprecated } - { refpos } { postref } + { refpos } { refbounds } + } , + preref .code:n = + { + % NOTE Option deprecated in 2022-01-14 for v0.2.0-alpha. + \msg_warning:nnnn { zref-clever }{ option-deprecated } + { preref } { refbounds } + } , + postref .code:n = + { + % NOTE Option deprecated in 2022-01-14 for v0.2.0-alpha. + \msg_warning:nnnn { zref-clever }{ option-deprecated } + { postref } { refbounds } } , } +\seq_map_inline:Nn + \c_@@_rf_opts_seq_refbounds_seq + { + \keys_define:nn { zref-clever/reference } + { + #1 .default:x = \c_novalue_tl , + #1 .code:n = + { + \tl_if_novalue:nTF {##1} + { + \@@_opt_seq_unset:c + { \@@_opt_varname_general:nn {#1} { seq } } + } + { + \seq_clear:N \l_tmpa_seq + \@@_opt_seq_set_clist_split:Nn + \l_tmpa_seq {##1} + \bool_lazy_or:nnTF + { \tl_if_empty_p:n {##1} } + { \int_compare_p:nNn { \seq_count:N \l_tmpa_seq } = { 4 } } + { + \seq_set_eq:cN + { \@@_opt_varname_general:nn {#1} { seq } } + \l_tmpa_seq + } + { + \msg_warning:nnxx { zref-clever } + { refbounds-must-be-four } + {#1} { \seq_count:N \l_tmpa_seq } + } + } + } , + } + } +\seq_map_inline:Nn + \c_@@_rf_opts_bool_maybe_type_specific_seq + { + \keys_define:nn { zref-clever/reference } + { + #1 .choice: , + #1 / true .code:n = + { + \bool_set_true:c + { \@@_opt_varname_general:nn {#1} { bool } } + } , + #1 / false .code:n = + { + \bool_set_false:c + { \@@_opt_varname_general:nn {#1} { bool } } + } , + #1 / unset .code:n = + { + \@@_opt_bool_unset:c + { \@@_opt_varname_general:nn {#1} { bool } } + } , + #1 .default:n = true , + no #1 .meta:n = { #1 = false } , + no #1 .value_forbidden:n = true , + } + } % \end{macrocode} % % -% % \subsubsection*{Package options} % % The options have been separated in two different groups, so that we can @@ -2625,10 +3176,10 @@ % \begin{macrocode} \keys_define:nn { } { - zref-clever / zcsetup .inherit:n = + zref-clever/zcsetup .inherit:n = { - zref-clever / label , - zref-clever / reference , + zref-clever/label , + zref-clever/reference , } } % \end{macrocode} @@ -2637,7 +3188,7 @@ % Process load-time package options % (\url{https://tex.stackexchange.com/a/15840}). % \begin{macrocode} -\ProcessKeysOptions { zref-clever / zcsetup } +\ProcessKeysOptions { zref-clever/zcsetup } % \end{macrocode} % % @@ -2665,7 +3216,7 @@ % \end{syntax} % \begin{macrocode} \cs_new_protected:Npn \@@_zcsetup:n #1 - { \keys_set:nn { zref-clever / zcsetup } {#1} } + { \keys_set:nn { zref-clever/zcsetup } {#1} } \cs_generate_variant:Nn \@@_zcsetup:n { x } % \end{macrocode} % \end{macro} @@ -2691,114 +3242,19 @@ % \begin{macrocode} \NewDocumentCommand \zcRefTypeSetup { m m } { - \prop_if_exist:cF { l_@@_type_ #1 _options_prop } - { \prop_new:c { l_@@_type_ #1 _options_prop } } \tl_set:Nn \l_@@_setup_type_tl {#1} - \keys_set:nn { zref-clever / typesetup } {#2} + \keys_set:nn { zref-clever/typesetup } {#2} } % \end{macrocode} % \end{macro} % % -% Inside \cs{zcRefTypeSetup} any of the options \emph{can} receive empty -% values, and those values, if they exist in the property list, will override -% language-specific options, regardless of their emptiness. In principle, we -% could live with the situation of, once a setting has been made in -% \cs{l_@@_type_<type>_options_prop} or in \cs{l_@@_ref_options_prop} it stays -% there forever, and can only be overridden by a new value at the same -% precedence level or a higher one. But it would be nice if an user can -% ``unset'' an option at either of those scopes to go back to the lower -% precedence level of the language-specific options at any given point. So -% both in \cs{zcRefTypeSetup} and in setting reference options (see -% \zcref{sec:reference-options}), we leverage the distinction of an ``empty -% valued key'' (\texttt{key=} or \texttt{key=\{\}}) from a ``key with no -% value'' (\texttt{key}). This distinction is captured internally by the -% lower-level key parsing, but must be made explicit at \cs{keys_set:nn} by -% means of the \texttt{.default:V} property of the key in \cs{keys_define:nn}. -% For the technique, by \contributor{Jonathan P.\ Spratte}, aka `Skillmon', -% and some discussion about it, including further insights by -% \contributor{Phelype Oleinik}, see -% \url{https://tex.stackexchange.com/q/614690} and -% \url{https://github.com/latex3/latex3/pull/988}. -% -% -% \begin{macrocode} -\keys_define:nn { zref-clever / typesetup } - { - cap .code:n = - { - \tl_if_empty:nTF {#1} - { - \prop_remove:cn - { - l_@@_type_ - \l_@@_setup_type_tl _options_prop - } - { cap } - } - { - \bool_lazy_or:nnTF - { \str_if_eq_p:nn {#1} { true } } - { \str_if_eq_p:nn {#1} { false } } - { - \prop_put:cnn - { - l_@@_type_ - \l_@@_setup_type_tl _options_prop - } - { cap } {#1} - } - { - \msg_warning:nnn { zref-clever } - { key-boolean-or-empty } {#1} - } - } - } , - cap .default:n = true , - nocap .meta:n = { cap = false } , - nocap .value_forbidden:n = true , - - abbrev .code:n = - { - \tl_if_empty:nTF {#1} - { - \prop_remove:cn - { - l_@@_type_ - \l_@@_setup_type_tl _options_prop - } - { abbrev } - } - { - \bool_lazy_or:nnTF - { \str_if_eq_p:nn {#1} { true } } - { \str_if_eq_p:nn {#1} { false } } - { - \prop_put:cnn - { - l_@@_type_ - \l_@@_setup_type_tl _options_prop - } - { abbrev } {#1} - } - { - \msg_warning:nnn { zref-clever } - { key-boolean-or-empty } {#1} - } - } - } , - abbrev .default:n = true , - noabbrev .meta:n = { abbrev = false }, - noabbrev .value_forbidden:n = true , - } -% \end{macrocode} -% % % \begin{macrocode} \seq_map_inline:Nn - \c_@@_ref_options_necessarily_not_type_specific_seq + \c_@@_rf_opts_tl_not_type_specific_seq { - \keys_define:nn { zref-clever / typesetup } + \keys_define:nn { zref-clever/typesetup } { #1 .code:n = { @@ -2807,57 +3263,141 @@ } , } } -% \end{macrocode} -% -% -% \begin{macrocode} \seq_map_inline:Nn - \c_@@_ref_options_typesetup_seq + \c_@@_rf_opts_tl_typesetup_seq { - \keys_define:nn { zref-clever / typesetup } + \keys_define:nn { zref-clever/typesetup } { - #1 .default:V = \c_novalue_tl , + #1 .default:x = \c_novalue_tl , #1 .code:n = { \tl_if_novalue:nTF {##1} { - \prop_remove:cn + \@@_opt_tl_unset:c { - l_@@_type_ - \l_@@_setup_type_tl _options_prop + \@@_opt_varname_type:enn + { \l_@@_setup_type_tl } {#1} { tl } } - {#1} } { - \prop_put:cnn + \tl_set:cn { - l_@@_type_ - \l_@@_setup_type_tl _options_prop + \@@_opt_varname_type:enn + { \l_@@_setup_type_tl } {#1} { tl } } - {#1} {##1} + {##1} } } , } } -\keys_define:nn { zref-clever / typesetup } +\keys_define:nn { zref-clever/typesetup } { refpre .code:n = { % NOTE Option deprecated in 2022-01-10 for v0.1.2-alpha. \msg_warning:nnnn { zref-clever }{ option-deprecated } - { refpre } { preref } + { refpre } { refbounds } } , refpos .code:n = { % NOTE Option deprecated in 2022-01-10 for v0.1.2-alpha. \msg_warning:nnnn { zref-clever }{ option-deprecated } - { refpos } { postref } + { refpos } { refbounds } + } , + preref .code:n = + { + % NOTE Option deprecated in 2022-01-14 for v0.2.0-alpha. + \msg_warning:nnnn { zref-clever }{ option-deprecated } + { preref } { refbounds } + } , + postref .code:n = + { + % NOTE Option deprecated in 2022-01-14 for v0.2.0-alpha. + \msg_warning:nnnn { zref-clever }{ option-deprecated } + { postref } { refbounds } } , } +\seq_map_inline:Nn + \c_@@_rf_opts_seq_refbounds_seq + { + \keys_define:nn { zref-clever/typesetup } + { + #1 .default:x = \c_novalue_tl , + #1 .code:n = + { + \tl_if_novalue:nTF {##1} + { + \@@_opt_seq_unset:c + { + \@@_opt_varname_type:enn + { \l_@@_setup_type_tl } {#1} { seq } + } + } + { + \seq_clear:N \l_tmpa_seq + \@@_opt_seq_set_clist_split:Nn + \l_tmpa_seq {##1} + \bool_lazy_or:nnTF + { \tl_if_empty_p:n {##1} } + { \int_compare_p:nNn { \seq_count:N \l_tmpa_seq } = { 4 } } + { + \seq_set_eq:cN + { + \@@_opt_varname_type:enn + { \l_@@_setup_type_tl } {#1} { seq } + } + \l_tmpa_seq + } + { + \msg_warning:nnxx { zref-clever } + { refbounds-must-be-four } + {#1} { \seq_count:N \l_tmpa_seq } + } + } + } , + } + } +\seq_map_inline:Nn + \c_@@_rf_opts_bool_maybe_type_specific_seq + { + \keys_define:nn { zref-clever/typesetup } + { + #1 .choice: , + #1 / true .code:n = + { + \bool_set_true:c + { + \@@_opt_varname_type:enn + { \l_@@_setup_type_tl } + {#1} { bool } + } + } , + #1 / false .code:n = + { + \bool_set_false:c + { + \@@_opt_varname_type:enn + { \l_@@_setup_type_tl } + {#1} { bool } + } + } , + #1 / unset .code:n = + { + \@@_opt_bool_unset:c + { + \@@_opt_varname_type:enn + { \l_@@_setup_type_tl } + {#1} { bool } + } + } , + #1 .default:n = true , + no #1 .meta:n = { #1 = false } , + no #1 .value_forbidden:n = true , + } + } % \end{macrocode} % % -% % \subsection{\cs{zcLanguageSetup}} % % \cs{zcLanguageSetup} is the main user interface for ``language-specific'' @@ -2879,37 +3419,31 @@ \NewDocumentCommand \zcLanguageSetup { m m } { \group_begin: - \prop_get:NnNTF \g_@@_languages_prop {#1} - \l_@@_base_language_tl + \@@_language_if_declared:nTF {#1} { \tl_clear:N \l_@@_setup_type_tl - \exp_args:NNx \seq_set_from_clist:Nn - \l_@@_lang_declension_seq + \tl_set:Nn \l_@@_setup_language_tl {#1} + \@@_opt_seq_get:cNF { - \prop_item:cn - { - g_@@_lang_ - \l_@@_base_language_tl _prop - } - { declension } + \@@_opt_varname_language:nnn + {#1} { declension } { seq } } + \l_@@_lang_declension_seq + { \seq_clear:N \l_@@_lang_declension_seq } \seq_if_empty:NTF \l_@@_lang_declension_seq { \tl_clear:N \l_@@_lang_decl_case_tl } { \seq_get_left:NN \l_@@_lang_declension_seq \l_@@_lang_decl_case_tl } - \exp_args:NNx \seq_set_from_clist:Nn - \l_@@_lang_gender_seq + \@@_opt_seq_get:cNF { - \prop_item:cn - { - g_@@_lang_ - \l_@@_base_language_tl _prop - } - { gender } + \@@_opt_varname_language:nnn + {#1} { gender } { seq } } - \keys_set:nn { zref-clever / langsetup } {#2} + \l_@@_lang_gender_seq + { \seq_clear:N \l_@@_lang_gender_seq } + \keys_set:nn { zref-clever/langsetup } {#2} } { \msg_warning:nnn { zref-clever } { unknown-language-setup } {#1} } \group_end: @@ -2919,44 +3453,12 @@ % \end{macro} % % -% \begin{macro} -% { -% \@@_declare_lang_opt_type:nnnn , -% \@@_declare_lang_opt_default:nnn , -% } -% A couple of auxiliary functions for the of -% \texttt{{zref-clever/langsetup}} keys set in \cs{zcLanguageSetup}. They -% respectively declare (unconditionally set) ``type-specific'' and -% ``default'' language-specific options. -% \begin{syntax} -% \cs{@@_declare_lang_opt_type:nnnn} \Arg{language} \Arg{type} -% ~~\Arg{key} \Arg{value} -% \cs{@@_declare_lang_opt_default:nnn} \Arg{language} -% ~~\Arg{key} \Arg{value} -% \end{syntax} -% \begin{macrocode} -\cs_new_protected:Npn \@@_declare_lang_opt_type:nnnn #1#2#3#4 - { - \prop_gput:cnn { g_@@_lang_ #1 _prop } - { type- #2 - #3 } {#4} - } -\cs_generate_variant:Nn - \@@_declare_lang_opt_type:nnnn { VVnn , VVxn , VVnx , VVnV } -\cs_new_protected:Npn \@@_declare_lang_opt_default:nnn #1#2#3 - { - \prop_gput:cnn { g_@@_lang_ #1 _prop } - { default- #2 } {#3} - } -\cs_generate_variant:Nn \@@_declare_lang_opt_default:nnn { Vnn , VnV } -% \end{macrocode} -% \end{macro} -% % % The set of keys for \texttt{{zref-clever/langsetup}}, which is used to set % language-specific options in \cs{zcLanguageSetup}. % % \begin{macrocode} -\keys_define:nn { zref-clever / langsetup } +\keys_define:nn { zref-clever/langsetup } { type .code:n = { @@ -2970,14 +3472,14 @@ \seq_if_empty:NTF \l_@@_lang_declension_seq { \msg_warning:nnxx { zref-clever } { language-no-decl-setup } - { \l_@@_base_language_tl } {#1} + { \l_@@_setup_language_tl } {#1} } { \seq_if_in:NnTF \l_@@_lang_declension_seq {#1} { \tl_set:Nn \l_@@_lang_decl_case_tl {#1} } { \msg_warning:nnxx { zref-clever } { unknown-decl-case } - {#1} { \l_@@_base_language_tl } + {#1} { \l_@@_setup_language_tl } \seq_get_left:NN \l_@@_lang_declension_seq \l_@@_lang_decl_case_tl } @@ -2985,12 +3487,13 @@ } , case .value_required:n = true , + gender .default:x = \c_novalue_tl , gender .code:n = { \seq_if_empty:NTF \l_@@_lang_gender_seq { \msg_warning:nnxxx { zref-clever } { language-no-gender } - { \l_@@_base_language_tl } { gender } {#1} + { \l_@@_setup_language_tl } { gender } {#1} } { \tl_if_empty:NTF \l_@@_setup_type_tl @@ -2999,82 +3502,69 @@ { option-only-type-specific } { gender } } { - \clist_clear:N \l_tmpa_clist - \clist_map_inline:nn {#1} + \tl_if_novalue:nTF {#1} { - \seq_if_in:NnTF \l_@@_lang_gender_seq {##1} - { \clist_put_right:Nn \l_tmpa_clist {##1} } + \@@_opt_seq_gunset:c { - \msg_warning:nnxx { zref-clever } - { gender-not-declared } - { \l_@@_base_language_tl } {##1} + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + { gender } + { seq } } } - \clist_if_empty:NF \l_tmpa_clist { - \@@_declare_lang_opt_type:VVnx - \l_@@_base_language_tl - \l_@@_setup_type_tl - { gender } { \clist_use:Nn \l_tmpa_clist { , } } + \seq_clear:N \l_tmpa_seq + \clist_map_inline:nn {#1} + { + \seq_if_in:NnTF \l_@@_lang_gender_seq {##1} + { \seq_put_right:Nn \l_tmpa_seq {##1} } + { + \msg_warning:nnxx { zref-clever } + { gender-not-declared } + { \l_@@_setup_language_tl } {##1} + } + } + \seq_gset_eq:cN + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + { gender } + { seq } + } + \l_tmpa_seq } } } } , - gender .value_required:n = true , - - cap .choices:nn = - { true , false } - { - \tl_if_empty:NTF \l_@@_setup_type_tl - { - \@@_declare_lang_opt_default:VnV - \l_@@_base_language_tl - { cap } \l_keys_choice_tl - } - { - \@@_declare_lang_opt_type:VVnV - \l_@@_base_language_tl - \l_@@_setup_type_tl - { cap } \l_keys_choice_tl - } - } , - cap .default:n = true , - nocap .meta:n = { cap = false } , - nocap .value_forbidden:n = true , - - abbrev .choices:nn = - { true , false } - { - \tl_if_empty:NTF \l_@@_setup_type_tl - { - \@@_declare_lang_opt_default:VnV - \l_@@_base_language_tl - { abbrev } \l_keys_choice_tl - } - { - \@@_declare_lang_opt_type:VVnV - \l_@@_base_language_tl - \l_@@_setup_type_tl - { abbrev } \l_keys_choice_tl - } - } , - abbrev .default:n = true , - noabbrev .meta:n = { abbrev = false }, - noabbrev .value_forbidden:n = true , } \seq_map_inline:Nn - \c_@@_ref_options_necessarily_not_type_specific_seq + \c_@@_rf_opts_tl_not_type_specific_seq { - \keys_define:nn { zref-clever / langsetup } + \keys_define:nn { zref-clever/langsetup } { - #1 .value_required:n = true , + #1 .default:x = \c_novalue_tl , #1 .code:n = { \tl_if_empty:NTF \l_@@_setup_type_tl { - \@@_declare_lang_opt_default:Vnn - \l_@@_base_language_tl - {#1} {##1} + \tl_if_novalue:nTF {##1} + { + \@@_opt_tl_gunset:c + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } {#1} { tl } + } + } + { + \tl_gset:cn + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } {#1} { tl } + } + {##1} + } } { \msg_warning:nnn { zref-clever } @@ -3084,47 +3574,88 @@ } } \seq_map_inline:Nn - \c_@@_ref_options_possibly_type_specific_seq + \c_@@_rf_opts_tl_maybe_type_specific_seq { - \keys_define:nn { zref-clever / langsetup } + \keys_define:nn { zref-clever/langsetup } { #1 .value_required:n = true , #1 .code:n = { \tl_if_empty:NTF \l_@@_setup_type_tl { - \@@_declare_lang_opt_default:Vnn - \l_@@_base_language_tl - {#1} {##1} + \tl_if_novalue:nTF {##1} + { + \@@_opt_tl_gunset:c + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } {#1} { tl } + } + } + { + \tl_gset:cn + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } {#1} { tl } + } + {##1} + } } { - \@@_declare_lang_opt_type:VVnn - \l_@@_base_language_tl - \l_@@_setup_type_tl - {#1} {##1} + \tl_if_novalue:nTF {##1} + { + \@@_opt_tl_gunset:c + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { tl } + } + } + { + \tl_gset:cn + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { tl } + } + {##1} + } } } , } } -\keys_define:nn { zref-clever / langsetup } +\keys_define:nn { zref-clever/langsetup } { refpre .code:n = { % NOTE Option deprecated in 2022-01-10 for v0.1.2-alpha. \msg_warning:nnnn { zref-clever }{ option-deprecated } - { refpre } { preref } + { refpre } { refbounds } } , refpos .code:n = { % NOTE Option deprecated in 2022-01-10 for v0.1.2-alpha. \msg_warning:nnnn { zref-clever }{ option-deprecated } - { refpos } { postref } + { refpos } { refbounds } + } , + preref .code:n = + { + % NOTE Option deprecated in 2022-01-14 for v0.2.0-alpha. + \msg_warning:nnnn { zref-clever }{ option-deprecated } + { preref } { refbounds } + } , + postref .code:n = + { + % NOTE Option deprecated in 2022-01-14 for v0.2.0-alpha. + \msg_warning:nnnn { zref-clever }{ option-deprecated } + { postref } { refbounds } } , } \seq_map_inline:Nn - \c_@@_ref_options_type_names_seq + \c_@@_rf_opts_tl_type_names_seq { - \keys_define:nn { zref-clever / langsetup } + \keys_define:nn { zref-clever/langsetup } { #1 .value_required:n = true , #1 .code:n = @@ -3135,27 +3666,205 @@ { option-only-type-specific } {#1} } { - \tl_if_empty:NTF \l_@@_lang_decl_case_tl + \tl_if_novalue:nTF {##1} { - \@@_declare_lang_opt_type:VVnn - \l_@@_base_language_tl - \l_@@_setup_type_tl - {#1} {##1} + \@@_opt_tl_gunset:c + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { tl } + } } { - \@@_declare_lang_opt_type:VVxn - \l_@@_base_language_tl - \l_@@_setup_type_tl - { \l_@@_lang_decl_case_tl - #1 } {##1} + \tl_if_empty:NTF \l_@@_lang_decl_case_tl + { + \tl_gset:cn + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { tl } + } + {##1} + } + { + \tl_gset:cn + { + \@@_opt_varname_lang_type:eeen + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + { \l_@@_lang_decl_case_tl - #1 } + { tl } + } + {##1} + } } } } , } } +\seq_map_inline:Nn + \c_@@_rf_opts_seq_refbounds_seq + { + \keys_define:nn { zref-clever/langsetup } + { + #1 .default:x = \c_novalue_tl , + #1 .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \tl_if_novalue:nTF {##1} + { + \@@_opt_seq_gunset:c + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { seq } + } + } + { + \seq_gclear:N \g_tmpa_seq + \@@_opt_seq_gset_clist_split:Nn + \g_tmpa_seq {##1} + \bool_lazy_or:nnTF + { \tl_if_empty_p:n {##1} } + { + \int_compare_p:nNn + { \seq_count:N \g_tmpa_seq } = { 4 } + } + { + \seq_gset_eq:cN + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { seq } + } + \g_tmpa_seq + } + { + \msg_warning:nnxx { zref-clever } + { refbounds-must-be-four } + {#1} { \seq_count:N \g_tmpa_seq } + } + } + } + { + \tl_if_novalue:nTF {##1} + { + \@@_opt_seq_gunset:c + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } {#1} { seq } + } + } + { + \seq_gclear:N \g_tmpa_seq + \@@_opt_seq_gset_clist_split:Nn + \g_tmpa_seq {##1} + \bool_lazy_or:nnTF + { \tl_if_empty_p:n {##1} } + { + \int_compare_p:nNn + { \seq_count:N \g_tmpa_seq } = { 4 } + } + { + \seq_gset_eq:cN + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } {#1} { seq } + } + \g_tmpa_seq + } + { + \msg_warning:nnxx { zref-clever } + { refbounds-must-be-four } + {#1} { \seq_count:N \g_tmpa_seq } + } + } + } + } , + } + } +\seq_map_inline:Nn + \c_@@_rf_opts_bool_maybe_type_specific_seq + { + \keys_define:nn { zref-clever/langsetup } + { + #1 .choice: , + #1 / true .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \bool_gset_true:c + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { bool } + } + } + { + \bool_gset_true:c + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { bool } + } + } + } , + #1 / false .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \bool_gset_false:c + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { bool } + } + } + { + \bool_gset_false:c + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { bool } + } + } + } , + #1 / unset .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \@@_opt_bool_gunset:c + { + \@@_opt_varname_lang_default:enn + { \l_@@_setup_language_tl } + {#1} { bool } + } + } + { + \@@_opt_bool_gunset:c + { + \@@_opt_varname_lang_type:eenn + { \l_@@_setup_language_tl } + { \l_@@_setup_type_tl } + {#1} { bool } + } + } + } , + #1 .default:n = true , + no #1 .meta:n = { #1 = false } , + no #1 .value_forbidden:n = true , + } + } % \end{macrocode} % % -% % \section{User interface} % % \subsection{\cs{zcref}} @@ -3187,7 +3896,7 @@ % \end{macrocode} % Set options. % \begin{macrocode} - \keys_set:nn { zref-clever / reference } {#3} + \keys_set:nn { zref-clever/reference } {#3} % \end{macrocode} % Store arguments values. % \begin{macrocode} @@ -3202,9 +3911,9 @@ % \begin{macrocode} \@@_provide_langfile:x { \l_@@_ref_language_tl } % \end{macrocode} -% Process \cs{zcDeclareLanguage} options. +% Process language settings. % \begin{macrocode} - \@@_process_language_options: + \@@_process_language_settings: % \end{macrocode} % Integration with \pkg{zref-check}. % \begin{macrocode} @@ -3232,7 +3941,10 @@ % \begin{macrocode} \tl_if_empty:NF \l_@@_zcref_note_tl { - \@@_get_ref_opt_typeset:nN { notesep } \l_tmpa_tl + \@@_get_rf_opt_tl:nxxN { notesep } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_tmpa_tl \l_tmpa_tl \l_@@_zcref_note_tl } @@ -3280,9 +3992,11 @@ % \begin{macrocode} \NewDocumentCommand \zcpageref { s O { } m } { - \IfBooleanTF {#1} - { \zcref*[#2, ref = page] {#3} } - { \zcref [#2, ref = page] {#3} } + \group_begin: + \IfBooleanT {#1} + { \bool_set_false:N \l_@@_hyperlink_bool } + \zcref [#2, ref = page] {#3} + \group_end: } % \end{macrocode} % \end{macro} @@ -3370,7 +4084,7 @@ % Store label types sequence. % \begin{macrocode} \seq_clear:N \l_@@_label_types_seq - \tl_if_eq:NnF \l_@@_ref_property_tl { page } + \tl_if_eq:NnF \l_@@_ref_propserty_tl { page } { \seq_map_function:NN \l_@@_zcref_labels_seq \@@_label_type_put_new_right:n @@ -3432,7 +4146,7 @@ \cs_new_protected:Npn \@@_label_type_put_new_right:n #1 { \@@_extract_default:Nnnn - \l_@@_label_type_a_tl {#1} { zc@type } { \c_empty_tl } + \l_@@_label_type_a_tl {#1} { zc@type } { } \seq_if_in:NVF \l_@@_label_types_seq \l_@@_label_type_a_tl { @@ -3480,15 +4194,15 @@ \cs_new_protected:Npn \@@_sort_default_same_type:nn #1#2 { \@@_extract_default:Nnnn \l_@@_label_enclval_a_tl - {#1} { zc@enclval } { \c_empty_tl } + {#1} { zc@enclval } { } \tl_reverse:N \l_@@_label_enclval_a_tl \@@_extract_default:Nnnn \l_@@_label_enclval_b_tl - {#2} { zc@enclval } { \c_empty_tl } + {#2} { zc@enclval } { } \tl_reverse:N \l_@@_label_enclval_b_tl \@@_extract_default:Nnnn \l_@@_label_extdoc_a_tl - {#1} { externaldocument } { \c_empty_tl } + {#1} { externaldocument } { } \@@_extract_default:Nnnn \l_@@_label_extdoc_b_tl - {#2} { externaldocument } { \c_empty_tl } + {#2} { externaldocument } { } \bool_set_false:N \l_@@_sort_decided_bool @@ -3819,11 +4533,13 @@ % { % \l_@@_type_count_int , % \l_@@_label_count_int , +% \l_@@_ref_count_int , % } % Auxiliary variables for \cs{@@_typeset_refs:} main counters. % \begin{macrocode} \int_new:N \l_@@_type_count_int \int_new:N \l_@@_label_count_int +\int_new:N \l_@@_ref_count_int % \end{macrocode} % \end{macro} % @@ -3852,17 +4568,19 @@ % { % \l_@@_type_name_tl , % \l_@@_name_in_link_bool , +% \l_@@_type_name_missing_bool , % \l_@@_name_format_tl , % \l_@@_name_format_fallback_tl , -% \l_@@_type_name_gender_tl , +% \l_@@_type_name_gender_seq , % } % Auxiliary variables for \cs{@@_typeset_refs:} type name handling. % \begin{macrocode} \tl_new:N \l_@@_type_name_tl \bool_new:N \l_@@_name_in_link_bool +\bool_new:N \l_@@_type_name_missing_bool \tl_new:N \l_@@_name_format_tl \tl_new:N \l_@@_name_format_fallback_tl -\tl_new:N \l_@@_type_name_gender_tl +\seq_new:N \l_@@_type_name_gender_seq % \end{macrocode} % \end{macro} % @@ -3894,15 +4612,13 @@ % \l_@@_listsep_tl , % \l_@@_lastsep_tl , % \l_@@_rangesep_tl , -% \l_@@_preref_tl , -% \l_@@_postref_tl , % \l_@@_namefont_tl , % \l_@@_reffont_tl , -% \l_@@_capitalize_bool , +% \l_@@_cap_bool , % \l_@@_abbrev_bool , % } -% Auxiliary variables for \cs{@@_typeset_refs:} separators, pre-/postref and -% font and other options. +% Auxiliary variables for \cs{@@_typeset_refs:} separators, and font and +% other options. % \begin{macrocode} \tl_new:N \l_@@_tpairsep_tl \tl_new:N \l_@@_tlistsep_tl @@ -3912,15 +4628,45 @@ \tl_new:N \l_@@_listsep_tl \tl_new:N \l_@@_lastsep_tl \tl_new:N \l_@@_rangesep_tl -\tl_new:N \l_@@_preref_tl -\tl_new:N \l_@@_postref_tl \tl_new:N \l_@@_namefont_tl \tl_new:N \l_@@_reffont_tl -\bool_new:N \l_@@_capitalize_bool +\bool_new:N \l_@@_cap_bool \bool_new:N \l_@@_abbrev_bool % \end{macrocode} % \end{macro} % +% \begin{macro} +% { +% \l_@@_refbounds_first_seq , +% \l_@@_refbounds_first_sg_seq , +% \l_@@_refbounds_first_pb_seq , +% \l_@@_refbounds_first_rb_seq , +% \l_@@_refbounds_mid_seq , +% \l_@@_refbounds_mid_rb_seq , +% \l_@@_refbounds_mid_re_seq , +% \l_@@_refbounds_last_seq , +% \l_@@_refbounds_last_pe_seq , +% \l_@@_refbounds_last_re_seq , +% \l_@@_type_first_refbounds_seq , +% \l_@@_type_first_refbounds_set_bool , +% } +% Auxiliary variables for \cs{@@_typeset_refs:}: advanced reference format +% options. +% \begin{macrocode} +\seq_new:N \l_@@_refbounds_first_seq +\seq_new:N \l_@@_refbounds_first_sg_seq +\seq_new:N \l_@@_refbounds_first_pb_seq +\seq_new:N \l_@@_refbounds_first_rb_seq +\seq_new:N \l_@@_refbounds_mid_seq +\seq_new:N \l_@@_refbounds_mid_rb_seq +\seq_new:N \l_@@_refbounds_mid_re_seq +\seq_new:N \l_@@_refbounds_last_seq +\seq_new:N \l_@@_refbounds_last_pe_seq +\seq_new:N \l_@@_refbounds_last_re_seq +\seq_new:N \l_@@_type_first_refbounds_seq +\bool_new:N \l_@@_type_first_refbounds_set_bool +% \end{macrocode} +% \end{macro} % % \begin{macro}{\l_@@_verbose_testing_bool} % Internal variable which enables extra log messaging at points of interest @@ -3948,15 +4694,23 @@ \tl_clear:N \l_@@_range_beg_label_tl \int_zero:N \l_@@_label_count_int \int_zero:N \l_@@_type_count_int + \int_zero:N \l_@@_ref_count_int \int_zero:N \l_@@_range_count_int \int_zero:N \l_@@_range_same_count_int + \bool_set_false:N \l_@@_type_first_refbounds_set_bool % Get type block options (not type-specific). - \@@_get_ref_opt_typeset:nN { tpairsep } + \@@_get_rf_opt_tl:nxxN { tpairsep } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } \l_@@_tpairsep_tl - \@@_get_ref_opt_typeset:nN { tlistsep } + \@@_get_rf_opt_tl:nxxN { tlistsep } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } \l_@@_tlistsep_tl - \@@_get_ref_opt_typeset:nN { tlastsep } + \@@_get_rf_opt_tl:nxxN { tlastsep } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } \l_@@_tlastsep_tl % Process label stack. @@ -4039,32 +4793,86 @@ } } - % Get type-specific separators, pre-/postref font and other options, - % once per type. + % Get possibly type-specific separators, refbounds, font and other + % options, once per type. \int_compare:nNnT { \l_@@_label_count_int } = { 0 } { - \@@_get_ref_opt_typeset:nN { namesep } + \@@_get_rf_opt_tl:nxxN { namesep } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } \l_@@_namesep_tl - \@@_get_ref_opt_typeset:nN { pairsep } + \@@_get_rf_opt_tl:nxxN { pairsep } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } \l_@@_pairsep_tl - \@@_get_ref_opt_typeset:nN { listsep } + \@@_get_rf_opt_tl:nxxN { listsep } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } \l_@@_listsep_tl - \@@_get_ref_opt_typeset:nN { lastsep } + \@@_get_rf_opt_tl:nxxN { lastsep } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } \l_@@_lastsep_tl - \@@_get_ref_opt_typeset:nN { rangesep } + \@@_get_rf_opt_tl:nxxN { rangesep } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } \l_@@_rangesep_tl - \@@_get_ref_opt_typeset:nN { preref } - \l_@@_preref_tl - \@@_get_ref_opt_typeset:nN { postref } - \l_@@_postref_tl - \@@_get_ref_opt_font:nN { namefont } + \@@_get_rf_opt_tl:nxxN { namefont } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } \l_@@_namefont_tl - \@@_get_ref_opt_font:nN { reffont } + \@@_get_rf_opt_tl:nxxN { reffont } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } \l_@@_reffont_tl - \@@_get_ref_opt_bool:nnN { cap } { false } - \l_@@_capitalize_bool - \@@_get_ref_opt_bool:nnN { abbrev } { false } + \@@_get_rf_opt_bool:nnxxN { cap } { false } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_@@_cap_bool + \@@_get_rf_opt_bool:nnxxN { abbrev } { false } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } \l_@@_abbrev_bool + \@@_get_rf_opt_seq:nxxN { refbounds-first } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_@@_refbounds_first_seq + \@@_get_rf_opt_seq:nxxN { refbounds-first-sg } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_@@_refbounds_first_sg_seq + \@@_get_rf_opt_seq:nxxN { refbounds-first-pb } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_@@_refbounds_first_pb_seq + \@@_get_rf_opt_seq:nxxN { refbounds-first-rb } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_@@_refbounds_first_rb_seq + \@@_get_rf_opt_seq:nxxN { refbounds-mid } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_@@_refbounds_mid_seq + \@@_get_rf_opt_seq:nxxN { refbounds-mid-rb } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_@@_refbounds_mid_rb_seq + \@@_get_rf_opt_seq:nxxN { refbounds-mid-re } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_@@_refbounds_mid_re_seq + \@@_get_rf_opt_seq:nxxN { refbounds-last } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_@@_refbounds_last_seq + \@@_get_rf_opt_seq:nxxN { refbounds-last-pe } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_@@_refbounds_last_pe_seq + \@@_get_rf_opt_seq:nxxN { refbounds-last-re } + { \l_@@_label_type_a_tl } + { \l_@@_ref_language_tl } + \l_@@_refbounds_last_re_seq } % Here we send this to a couple of auxiliary functions. @@ -4109,19 +4917,31 @@ \l_@@_label_a_tl \tl_set:NV \l_@@_type_first_label_type_tl \l_@@_label_type_a_tl + \seq_set_eq:NN \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_sg_seq + \bool_set_true:N \l_@@_type_first_refbounds_set_bool } % The last is the second: we have a pair (if not repeated). % Test: 'zc-typeset01.lvt': "Last of type: pair" { 1 } { - \int_compare:nNnF { \l_@@_range_same_count_int } = { 1 } + \int_compare:nNnTF { \l_@@_range_same_count_int } = { 1 } + { + \seq_set_eq:NN \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_sg_seq + \bool_set_true:N \l_@@_type_first_refbounds_set_bool + } { \tl_put_right:Nx \l_@@_typeset_queue_curr_tl { \exp_not:V \l_@@_pairsep_tl - \@@_get_ref:V \l_@@_label_a_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_last_pe_seq } + \seq_set_eq:NN \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_pb_seq + \bool_set_true:N \l_@@_type_first_refbounds_set_bool } } } @@ -4134,28 +4954,56 @@ % Test: 'zc-typeset01.lvt': "Last of type: not range" { 0 } { - \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + \int_compare:nNnTF { \l_@@_ref_count_int } < { 2 } { - \exp_not:V \l_@@_lastsep_tl - \@@_get_ref:V \l_@@_label_a_tl + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_pairsep_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_last_pe_seq + } + } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_lastsep_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_last_seq + } } } % Last in the range is also the second in it. % Test: 'zc-typeset01.lvt': "Last of type: pair in sequence" { 1 } { - \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + \int_compare:nNnTF + { \l_@@_range_same_count_int } = { 1 } { % We know `range_beg_label' is not empty, since this is the % second element in the range, but the third or more in the % type list. - \exp_not:V \l_@@_listsep_tl - \@@_get_ref:V \l_@@_range_beg_label_tl - \int_compare:nNnF - { \l_@@_range_same_count_int } = { 1 } + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_pairsep_tl + \@@_get_ref:VN + \l_@@_range_beg_label_tl + \l_@@_refbounds_last_pe_seq + } + \seq_set_eq:NN \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_pb_seq + \bool_set_true:N + \l_@@_type_first_refbounds_set_bool + } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl { + \exp_not:V \l_@@_listsep_tl + \@@_get_ref:VN + \l_@@_range_beg_label_tl + \l_@@_refbounds_mid_seq \exp_not:V \l_@@_lastsep_tl - \@@_get_ref:V \l_@@_label_a_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_last_seq } } } @@ -4173,49 +5021,117 @@ { 0 } { % If `range_beg_label' is empty, it means it was also the - % first of the type, and hence was already handled. - \tl_if_empty:VF \l_@@_range_beg_label_tl + % first of the type, and hence its typesetting was already + % handled, and we just have to set refbounds. + \tl_if_empty:VTF \l_@@_range_beg_label_tl { - \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + \seq_set_eq:NN \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_sg_seq + \bool_set_true:N + \l_@@_type_first_refbounds_set_bool + } + { + \int_compare:nNnTF + { \l_@@_ref_count_int } < { 2 } { - \exp_not:V \l_@@_lastsep_tl - \@@_get_ref:V - \l_@@_range_beg_label_tl + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_pairsep_tl + \@@_get_ref:VN + \l_@@_range_beg_label_tl + \l_@@_refbounds_last_pe_seq + } + } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_lastsep_tl + \@@_get_ref:VN + \l_@@_range_beg_label_tl + \l_@@_refbounds_last_seq + } } } } - % A `range', but with no skipped value, treat as list. + % A `range', but with no skipped value, treat as pair if range + % started with first of type, otherwise as list. % Test: 'zc-typeset01.lvt': "Last of type: range to pair" { 1 } { - \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + % Ditto. + \tl_if_empty:VTF \l_@@_range_beg_label_tl { - % Ditto. - \tl_if_empty:VF \l_@@_range_beg_label_tl + \seq_set_eq:NN \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_pb_seq + \bool_set_true:N + \l_@@_type_first_refbounds_set_bool + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_pairsep_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_last_pe_seq + } + } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl { \exp_not:V \l_@@_listsep_tl - \@@_get_ref:V + \@@_get_ref:VN \l_@@_range_beg_label_tl + \l_@@_refbounds_mid_seq + } + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_lastsep_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_last_seq } - \exp_not:V \l_@@_lastsep_tl - \@@_get_ref:V \l_@@_label_a_tl } } } { % An actual range. % Test: 'zc-typeset01.lvt': "Last of type: range" - \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + % Ditto. + \tl_if_empty:VTF \l_@@_range_beg_label_tl { - % Ditto. - \tl_if_empty:VF \l_@@_range_beg_label_tl + \seq_set_eq:NN \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_rb_seq + \bool_set_true:N + \l_@@_type_first_refbounds_set_bool + } + { + \int_compare:nNnTF + { \l_@@_ref_count_int } < { 2 } { - \exp_not:V \l_@@_lastsep_tl - \@@_get_ref:V - \l_@@_range_beg_label_tl + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_pairsep_tl + \@@_get_ref:VN + \l_@@_range_beg_label_tl + \l_@@_refbounds_mid_rb_seq + } + \seq_set_eq:NN + \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_pb_seq + \bool_set_true:N + \l_@@_type_first_refbounds_set_bool } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_lastsep_tl + \@@_get_ref:VN + \l_@@_range_beg_label_tl + \l_@@_refbounds_mid_rb_seq + } + } + } + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { \exp_not:V \l_@@_rangesep_tl - \@@_get_ref:V \l_@@_label_a_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_last_re_seq } } } @@ -4247,16 +5163,40 @@ } % Test: 'zc-typeset01.lvt': "Last of type: option range" % Test: 'zc-typeset01.lvt': "Last of type: option range to pair" - \tl_set:Nx \l_@@_typeset_queue_curr_tl + \bool_if:NTF \l_@@_next_maybe_range_bool + { + \tl_set:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_pairsep_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_last_pe_seq + } + \seq_set_eq:NN \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_pb_seq + \bool_set_true:N \l_@@_type_first_refbounds_set_bool + } { - \bool_if:NTF \l_@@_next_maybe_range_bool - { \exp_not:V \l_@@_pairsep_tl } - { \exp_not:V \l_@@_rangesep_tl } - \@@_get_ref:V \l_@@_label_a_tl + \tl_set:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_rangesep_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_last_re_seq + } + \seq_set_eq:NN \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_rb_seq + \bool_set_true:N \l_@@_type_first_refbounds_set_bool } } } + % If none of the special cases for the first of type refbounds have been + % set, do it. + \bool_if:NF \l_@@_type_first_refbounds_set_bool + { + \seq_set_eq:NN \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_seq + } + % Now that the type block is finished, we can add the name and the first % ref to the queue. Also, if "typeset" option is not "both", handle it % here as well. @@ -4272,7 +5212,10 @@ { % Test: 'zc-typeset01.lvt': "Last of type: option typeset ref" \tl_put_left:Nx \l_@@_typeset_queue_curr_tl - { \@@_get_ref:V \l_@@_type_first_label_tl } + { + \@@_get_ref:VN \l_@@_type_first_label_tl + \l_@@_type_first_refbounds_seq + } } { \bool_if:NTF \l_@@_typeset_name_bool @@ -4372,9 +5315,11 @@ \tl_clear:N \l_@@_type_first_label_type_tl \tl_clear:N \l_@@_range_beg_label_tl \int_zero:N \l_@@_label_count_int + \int_zero:N \l_@@_ref_count_int \int_incr:N \l_@@_type_count_int \int_zero:N \l_@@_range_count_int \int_zero:N \l_@@_range_same_count_int + \bool_set_false:N \l_@@_type_first_refbounds_set_bool } } % \end{macrocode} @@ -4409,6 +5354,7 @@ \l_@@_label_a_tl \tl_set:NV \l_@@_type_first_label_type_tl \l_@@_label_type_a_tl + \int_incr:N \l_@@_ref_count_int % If the next label may be part of a range, we set `range_beg_label' % to "empty" (we deal with it as the "first", and must do it there, to @@ -4453,10 +5399,12 @@ % Test: 'zc-typeset01.lvt': "Not last of type: no range" { 0 } { + \int_incr:N \l_@@_ref_count_int \tl_put_right:Nx \l_@@_typeset_queue_curr_tl { \exp_not:V \l_@@_listsep_tl - \@@_get_ref:V \l_@@_label_a_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_mid_seq } } % Last is second in the range: if `range_same_count' is also @@ -4466,20 +5414,33 @@ % Test: 'zc-typeset01.lvt': "Not last of type: range pair" { 1 } { - \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + \tl_if_empty:VTF \l_@@_range_beg_label_tl { - \tl_if_empty:VF \l_@@_range_beg_label_tl + \seq_set_eq:NN \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_seq + \bool_set_true:N + \l_@@_type_first_refbounds_set_bool + } + { + \int_incr:N \l_@@_ref_count_int + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl { \exp_not:V \l_@@_listsep_tl - \@@_get_ref:V + \@@_get_ref:VN \l_@@_range_beg_label_tl + \l_@@_refbounds_mid_seq } - \int_compare:nNnF - { \l_@@_range_same_count_int } = { 1 } + } + \int_compare:nNnF + { \l_@@_range_same_count_int } = { 1 } + { + \int_incr:N \l_@@_ref_count_int + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl { \exp_not:V \l_@@_listsep_tl - \@@_get_ref:V + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_mid_seq } } } @@ -4498,44 +5459,85 @@ % Test: 'zc-typeset01.lvt': "Not last of type: range to one" { 0 } { - \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + \tl_if_empty:VTF \l_@@_range_beg_label_tl { - \tl_if_empty:VF \l_@@_range_beg_label_tl + \seq_set_eq:NN + \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_seq + \bool_set_true:N + \l_@@_type_first_refbounds_set_bool + } + { + \int_incr:N \l_@@_ref_count_int + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl { \exp_not:V \l_@@_listsep_tl - \@@_get_ref:V + \@@_get_ref:VN \l_@@_range_beg_label_tl + \l_@@_refbounds_mid_seq } } } % Test: 'zc-typeset01.lvt': "Not last of type: range to pair" { 1 } { - \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + \tl_if_empty:VTF \l_@@_range_beg_label_tl + { + \seq_set_eq:NN + \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_seq + \bool_set_true:N + \l_@@_type_first_refbounds_set_bool + } { - \tl_if_empty:VF \l_@@_range_beg_label_tl + \int_incr:N \l_@@_ref_count_int + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl { \exp_not:V \l_@@_listsep_tl - \@@_get_ref:V + \@@_get_ref:VN \l_@@_range_beg_label_tl + \l_@@_refbounds_mid_seq } + } + \int_incr:N \l_@@_ref_count_int + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { \exp_not:V \l_@@_listsep_tl - \@@_get_ref:V \l_@@_label_a_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_mid_seq } } } { % Test: 'zc-typeset01.lvt': "Not last of type: range" - \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + \tl_if_empty:VTF \l_@@_range_beg_label_tl { - \tl_if_empty:VF \l_@@_range_beg_label_tl + \seq_set_eq:NN + \l_@@_type_first_refbounds_seq + \l_@@_refbounds_first_rb_seq + \bool_set_true:N + \l_@@_type_first_refbounds_set_bool + } + { + \int_incr:N \l_@@_ref_count_int + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl { \exp_not:V \l_@@_listsep_tl - \@@_get_ref:V + \@@_get_ref:VN \l_@@_range_beg_label_tl + \l_@@_refbounds_mid_rb_seq } + } + % For the purposes of the serial comma, and thus for the + % distinction of 'lastsep' and 'pairsep', a "range" counts + % as one. Since 'range_beg' has already been counted + % (here or with the first of type), we refrain from + % incrementing 'ref_count_int'. + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { \exp_not:V \l_@@_rangesep_tl - \@@_get_ref:V \l_@@_label_a_tl + \@@_get_ref:VN \l_@@_label_a_tl + \l_@@_refbounds_mid_re_seq } } } @@ -4554,8 +5556,8 @@ % % \subsection*{Auxiliary functions} % -% \cs{@@_get_ref:n} and \cs{@@_get_ref_first:} are the two functions which -% actually build the reference blocks for typesetting. \cs{@@_get_ref:n} +% \cs{@@_get_ref:nN} and \cs{@@_get_ref_first:} are the two functions which +% actually build the reference blocks for typesetting. \cs{@@_get_ref:nN} % handles all references but the first of its type, and \cs{@@_get_ref_first:} % deals with the first reference of a type. Saying they do ``typesetting'' is % imprecise though, they actually prepare material to be accumulated in @@ -4566,10 +5568,10 @@ % the queue, we are using a number of variables which are transient to the % current label, the label properties among them, but not only. Hence, these % variables \emph{must} be expanded to their current values to be stored in -% the queue. Indeed, \cs{@@_get_ref:n} and \cs{@@_get_ref_first:} get called, -% as they must, in the context of \texttt{x} type expansions. But we don't -% want to expand the values of the variables themselves, so we need to get -% current values, but stop expansion after that. In particular, reference +% the queue. Indeed, \cs{@@_get_ref:nN} and \cs{@@_get_ref_first:} get +% called, as they must, in the context of \texttt{x} type expansions. But we +% don't want to expand the values of the variables themselves, so we need to +% get current values, but stop expansion after that. In particular, reference % options given by the user should reach the stream for its final typesetting % (when the queue itself gets typeset) \emph{unmodified} (``no manipulation'', % to use the \texttt{n} signature jargon). We also need to prevent premature @@ -4594,58 +5596,55 @@ % \end{macro} % % -% \begin{macro}{\@@_get_ref:n} +% \begin{macro}{\@@_get_ref:nN} % Handles a complete reference block to be accumulated in the ``queue'', -% including ``pre'' and ``pos'' elements, and hyperlinking. For use with -% all labels, except the first of its type, which is done by -% \cs{@@_get_ref_first:}. +% including refbounds, and hyperlinking. For use with all labels, except +% the first of its type, which is done by \cs{@@_get_ref_first:}. % \begin{syntax} -% \cs{@@_get_ref:n} \Arg{label} +% \cs{@@_get_ref:nN} \Arg{label} \Arg{refbounds} % \end{syntax} % \begin{macrocode} -\cs_new:Npn \@@_get_ref:n #1 +\cs_new:Npn \@@_get_ref:nN #1#2 { \zref@ifrefcontainsprop {#1} { \l_@@_ref_property_tl } { \bool_if:nTF { - \l_@@_use_hyperref_bool && + \l_@@_hyperlink_bool && ! \l_@@_link_star_bool } { - \bool_if:NF \l_@@_preposinlink_bool - { \exp_not:V \l_@@_preref_tl } + \exp_not:N \group_begin: + \exp_not:V \l_@@_reffont_tl + \seq_item:Nn #2 { 1 } % It's two `@s', but escaped for DocStrip. \exp_not:N \hyper@@@@link { \@@_extract_url_unexp:n {#1} } { \@@_extract_unexp:nnn {#1} { anchor } { } } { - \bool_if:NT \l_@@_preposinlink_bool - { \exp_not:V \l_@@_preref_tl } - \exp_not:N \group_begin: - \exp_not:V \l_@@_reffont_tl + \seq_item:Nn #2 { 2 } \@@_extract_unexp:nvn {#1} { l_@@_ref_property_tl } { } - \exp_not:N \group_end: - \bool_if:NT \l_@@_preposinlink_bool - { \exp_not:V \l_@@_postref_tl } + \seq_item:Nn #2 { 3 } } - \bool_if:NF \l_@@_preposinlink_bool - { \exp_not:V \l_@@_postref_tl } + \seq_item:Nn #2 { 4 } + \exp_not:N \group_end: } { - \exp_not:V \l_@@_preref_tl \exp_not:N \group_begin: \exp_not:V \l_@@_reffont_tl + \seq_item:Nn #2 { 1 } + \seq_item:Nn #2 { 2 } \@@_extract_unexp:nvn {#1} { l_@@_ref_property_tl } { } + \seq_item:Nn #2 { 3 } + \seq_item:Nn #2 { 4 } \exp_not:N \group_end: - \exp_not:V \l_@@_postref_tl } } { \@@_ref_default: } } -\cs_generate_variant:Nn \@@_get_ref:n { V } +\cs_generate_variant:Nn \@@_get_ref:nN { VN } % \end{macrocode} % \end{macro} % @@ -4671,6 +5670,7 @@ { \l_@@_type_first_label_tl } { \l_@@_ref_property_tl } { + \exp_not:N \group_begin: % It's two `@s', but escaped for DocStrip. \exp_not:N \hyper@@@@link { @@ -4687,18 +5687,19 @@ \exp_not:V \l_@@_type_name_tl \exp_not:N \group_end: \exp_not:V \l_@@_namesep_tl - \exp_not:V \l_@@_preref_tl \exp_not:N \group_begin: \exp_not:V \l_@@_reffont_tl + \seq_item:Nn \l_@@_type_first_refbounds_seq { 1 } + \seq_item:Nn \l_@@_type_first_refbounds_seq { 2 } \@@_extract_unexp:Vvn \l_@@_type_first_label_tl { l_@@_ref_property_tl } { } + \seq_item:Nn \l_@@_type_first_refbounds_seq { 3 } \exp_not:N \group_end: - \bool_if:NT \l_@@_preposinlink_bool - { \exp_not:V \l_@@_postref_tl } } - \bool_if:NF \l_@@_preposinlink_bool - { \exp_not:V \l_@@_postref_tl } + \exp_not:V \l_@@_reffont_tl + \seq_item:Nn \l_@@_type_first_refbounds_seq { 4 } + \exp_not:N \group_end: } { \exp_not:N \group_begin: @@ -4710,7 +5711,7 @@ } } { - \tl_if_empty:NTF \l_@@_type_name_tl + \bool_if:nTF \l_@@_type_name_missing_bool { \@@_name_default: \exp_not:V \l_@@_namesep_tl @@ -4720,7 +5721,8 @@ \exp_not:V \l_@@_namefont_tl \exp_not:V \l_@@_type_name_tl \exp_not:N \group_end: - \exp_not:V \l_@@_namesep_tl + \tl_if_empty:NF \l_@@_type_name_tl + { \exp_not:V \l_@@_namesep_tl } } \zref@ifrefcontainsprop { \l_@@_type_first_label_tl } @@ -4728,12 +5730,14 @@ { \bool_if:nTF { - \l_@@_use_hyperref_bool && + \l_@@_hyperlink_bool && ! \l_@@_link_star_bool } { - \bool_if:NF \l_@@_preposinlink_bool - { \exp_not:V \l_@@_preref_tl } + \exp_not:N \group_begin: + \exp_not:V \l_@@_reffont_tl + \seq_item:Nn + \l_@@_type_first_refbounds_seq { 1 } % It's two '@s', but escaped for DocStrip. \exp_not:N \hyper@@@@link { @@ -4745,29 +5749,29 @@ \l_@@_type_first_label_tl { anchor } { } } { - \bool_if:NT \l_@@_preposinlink_bool - { \exp_not:V \l_@@_preref_tl } - \exp_not:N \group_begin: - \exp_not:V \l_@@_reffont_tl + \seq_item:Nn + \l_@@_type_first_refbounds_seq { 2 } \@@_extract_unexp:Vvn \l_@@_type_first_label_tl { l_@@_ref_property_tl } { } - \exp_not:N \group_end: - \bool_if:NT \l_@@_preposinlink_bool - { \exp_not:V \l_@@_postref_tl } + \seq_item:Nn + \l_@@_type_first_refbounds_seq { 3 } } - \bool_if:NF \l_@@_preposinlink_bool - { \exp_not:V \l_@@_postref_tl } + \seq_item:Nn + \l_@@_type_first_refbounds_seq { 4 } + \exp_not:N \group_end: } { - \exp_not:V \l_@@_preref_tl \exp_not:N \group_begin: \exp_not:V \l_@@_reffont_tl + \seq_item:Nn \l_@@_type_first_refbounds_seq { 1 } + \seq_item:Nn \l_@@_type_first_refbounds_seq { 2 } \@@_extract_unexp:Vvn \l_@@_type_first_label_tl { l_@@_ref_property_tl } { } + \seq_item:Nn \l_@@_type_first_refbounds_seq { 3 } + \seq_item:Nn \l_@@_type_first_refbounds_seq { 4 } \exp_not:N \group_end: - \exp_not:V \l_@@_postref_tl } } { \@@_ref_default: } @@ -4794,18 +5798,24 @@ \cs_new_protected:Npn \@@_type_name_setup: { \zref@ifrefundefined { \l_@@_type_first_label_tl } - { \tl_clear:N \l_@@_type_name_tl } + { + \tl_clear:N \l_@@_type_name_tl + \bool_set_true:N \l_@@_type_name_missing_bool + } { \tl_if_eq:NnTF \l_@@_type_first_label_type_tl { zc@missingtype } - { \tl_clear:N \l_@@_type_name_tl } + { + \tl_clear:N \l_@@_type_name_tl + \bool_set_true:N \l_@@_type_name_missing_bool + } { % Determine whether we should use capitalization, abbreviation, % and plural. \bool_lazy_or:nnTF - { \l_@@_capitalize_bool } + { \l_@@_cap_bool } { - \l_@@_capitalize_first_bool && + \l_@@_capfirst_bool && \int_compare_p:nNn { \l_@@_type_count_int } = { 0 } } { \tl_set:Nn \l_@@_name_format_tl {Name} } @@ -4860,19 +5870,15 @@ { \l_@@_nudge_gender_bool } { ! \tl_if_empty_p:N \l_@@_ref_gender_tl } { - \@@_get_lang_opt_type:xxnNF - { \l_@@_ref_language_tl } + \@@_get_rf_opt_seq:nxxN { gender } { \l_@@_type_first_label_type_tl } - { gender } - \l_@@_type_name_gender_tl - { \tl_clear:N \l_@@_type_name_gender_tl } - \clist_set:NV \l_tmpa_clist - \l_@@_type_name_gender_tl - \clist_if_in:NVF - \l_tmpa_clist + { \l_@@_ref_language_tl } + \l_@@_type_name_gender_seq + \seq_if_in:NVF + \l_@@_type_name_gender_seq \l_@@_ref_gender_tl { - \tl_if_empty:NTF \l_@@_type_name_gender_tl + \seq_if_empty:NTF \l_@@_type_name_gender_seq { \msg_warning:nnxxx { zref-clever } { nudge-gender-not-declared-for-type } @@ -4885,7 +5891,10 @@ { nudge-gender-mismatch } { \l_@@_type_first_label_type_tl } { \l_@@_ref_gender_tl } - { \l_@@_type_name_gender_tl } + { + \seq_use:Nn + \l_@@_type_name_gender_seq { ,~ } + } { \l_@@_ref_language_tl } } } @@ -4894,12 +5903,13 @@ \tl_if_empty:NTF \l_@@_name_format_fallback_tl { - \prop_get:cVNF + \@@_opt_tl_get:cNF { - l_@@_type_ - \l_@@_type_first_label_type_tl _options_prop + \@@_opt_varname_type:een + { \l_@@_type_first_label_type_tl } + { \l_@@_name_format_tl } + { tl } } - \l_@@_name_format_tl \l_@@_type_name_tl { \tl_if_empty:NF \l_@@_ref_decl_case_tl @@ -4908,13 +5918,18 @@ \tl_put_left:NV \l_@@_name_format_tl \l_@@_ref_decl_case_tl } - \@@_get_lang_opt_type:xxxNF - { \l_@@_ref_language_tl } - { \l_@@_type_first_label_type_tl } - { \l_@@_name_format_tl } + \@@_opt_tl_get:cNF + { + \@@_opt_varname_lang_type:eeen + { \l_@@_ref_language_tl } + { \l_@@_type_first_label_type_tl } + { \l_@@_name_format_tl } + { tl } + } \l_@@_type_name_tl { \tl_clear:N \l_@@_type_name_tl + \bool_set_true:N \l_@@_type_name_missing_bool \msg_warning:nnxx { zref-clever } { missing-name } { \l_@@_name_format_tl } { \l_@@_type_first_label_type_tl } @@ -4922,20 +5937,22 @@ } } { - \prop_get:cVNF + \@@_opt_tl_get:cNF { - l_@@_type_ - \l_@@_type_first_label_type_tl _options_prop + \@@_opt_varname_type:een + { \l_@@_type_first_label_type_tl } + { \l_@@_name_format_tl } + { tl } } - \l_@@_name_format_tl \l_@@_type_name_tl { - \prop_get:cVNF + \@@_opt_tl_get:cNF { - l_@@_type_ - \l_@@_type_first_label_type_tl _options_prop + \@@_opt_varname_type:een + { \l_@@_type_first_label_type_tl } + { \l_@@_name_format_fallback_tl } + { tl } } - \l_@@_name_format_fallback_tl \l_@@_type_name_tl { \tl_if_empty:NF \l_@@_ref_decl_case_tl @@ -4950,19 +5967,29 @@ \l_@@_name_format_fallback_tl \l_@@_ref_decl_case_tl } - \@@_get_lang_opt_type:xxxNF - { \l_@@_ref_language_tl } - { \l_@@_type_first_label_type_tl } - { \l_@@_name_format_tl } - \l_@@_type_name_tl + \@@_opt_tl_get:cNF { - \@@_get_lang_opt_type:xxxNF + \@@_opt_varname_lang_type:eeen { \l_@@_ref_language_tl } { \l_@@_type_first_label_type_tl } - { \l_@@_name_format_fallback_tl } + { \l_@@_name_format_tl } + { tl } + } + \l_@@_type_name_tl + { + \@@_opt_tl_get:cNF + { + \@@_opt_varname_lang_type:eeen + { \l_@@_ref_language_tl } + { \l_@@_type_first_label_type_tl } + { \l_@@_name_format_fallback_tl } + { tl } + } \l_@@_type_name_tl { \tl_clear:N \l_@@_type_name_tl + \bool_set_true:N + \l_@@_type_name_missing_bool \msg_warning:nnxx { zref-clever } { missing-name } { \l_@@_name_format_tl } @@ -4978,7 +6005,7 @@ % Signal whether the type name is to be included in the hyperlink or not. \bool_lazy_any:nTF { - { ! \l_@@_use_hyperref_bool } + { ! \l_@@_hyperlink_bool } { \l_@@_link_star_bool } { \tl_if_empty_p:N \l_@@_type_name_tl } { \str_if_eq_p:Vn \l_@@_nameinlink_str { false } } @@ -5017,11 +6044,11 @@ \cs_new:Npn \@@_extract_url_unexp:n #1 { \zref@ifpropundefined { urluse } - { \@@_extract_unexp:nnn {#1} { url } { \c_empty_tl } } + { \@@_extract_unexp:nnn {#1} { url } { } } { \zref@ifrefcontainsprop {#1} { urluse } - { \@@_extract_unexp:nnn {#1} { urluse } { \c_empty_tl } } - { \@@_extract_unexp:nnn {#1} { url } { \c_empty_tl } } + { \@@_extract_unexp:nnn {#1} { urluse } { } } + { \@@_extract_unexp:nnn {#1} { url } { } } } } \cs_generate_variant:Nn \@@_extract_url_unexp:n { V } @@ -5045,9 +6072,9 @@ \cs_new_protected:Npn \@@_labels_in_sequence:nn #1#2 { \@@_extract_default:Nnnn \l_@@_label_extdoc_a_tl - {#1} { externaldocument } { \c_empty_tl } + {#1} { externaldocument } { } \@@_extract_default:Nnnn \l_@@_label_extdoc_b_tl - {#2} { externaldocument } { \c_empty_tl } + {#2} { externaldocument } { } \tl_if_eq:NNT \l_@@_label_extdoc_a_tl @@ -5124,187 +6151,142 @@ % % % Finally, some functions for retrieving reference options values, according -% to the relevant precedence rules. They both receive an \meta{option} as -% argument, and store the retrieved value in an appropriate. Though these are -% mostly general functions (for a change\dots{}), they are not completely so, -% they rely on the current state of \cs{l_@@_label_type_a_tl}, as set during -% the processing of the label stack. This could be easily generalized, of -% course, but I don't think it is worth it, \cs{l_@@_label_type_a_tl} is -% indeed what we want in all practical cases. The difference between each of -% these functions is the kind of option each should be used for. -% \cs{@@_get_ref_opt_typeset:nN} is meant for the general options, and -% attempts to find values for them in all precedence levels (four plus -% ``fallback''). \cs{@@_get_ref_opt_font:nN} is intended for ``font'' -% options, which cannot be ``language-specific'', thus for these we just -% search general options and type options. \cs{@@_get_ref_opt_bool:nN} is -% intended for boolean options. -% -% \begin{macro}{\@@_get_ref_opt_typeset:nN} +% to the relevant precedence rules. They receive an \meta{option} as +% argument, and store the retrieved value in an appropriate \meta{variable}. +% The difference between each of these functions is the data type of the +% option each should be used for. +% +% +% \begin{macro}{\@@_get_rf_opt_tl:nnnN} % \begin{syntax} -% \cs{@@_get_ref_opt_typeset:nN} \Arg{option} \Arg{tl variable} +% \cs{@@_get_rf_opt_tl:nnnN} \Arg{option} +% ~~\Arg{ref type} \Arg{language} \Arg{tl variable} % \end{syntax} % \begin{macrocode} -\cs_new_protected:Npn \@@_get_ref_opt_typeset:nN #1#2 +\cs_new_protected:Npn \@@_get_rf_opt_tl:nnnN #1#2#3#4 { % First attempt: general options. - \prop_get:NnNF \l_@@_ref_options_prop {#1} #2 + \@@_opt_tl_get:cNF + { \@@_opt_varname_general:nn {#1} { tl } } + #4 { % If not found, try type specific options. - \bool_lazy_and:nnTF - { - \prop_if_exist_p:c - { - l_@@_type_ - \l_@@_label_type_a_tl _options_prop - } - } - { - \prop_if_in_p:cn - { - l_@@_type_ - \l_@@_label_type_a_tl _options_prop - } - {#1} - } - { - \prop_get:cnN - { - l_@@_type_ - \l_@@_label_type_a_tl _options_prop - } - {#1} #2 - } + \@@_opt_tl_get:cNF + { \@@_opt_varname_type:nnn {#2} {#1} { tl } } + #4 { % If not found, try type- and language-specific. - \@@_get_lang_opt_type:xxnNF - { \l_@@_ref_language_tl } - { \l_@@_label_type_a_tl } - {#1} #2 + \@@_opt_tl_get:cNF + { \@@_opt_varname_lang_type:nnnn {#3} {#2} {#1} { tl } } + #4 { % If not found, try language-specific default. - \@@_get_lang_opt_default:xnNF - { \l_@@_ref_language_tl } - {#1} #2 + \@@_opt_tl_get:cNF + { \@@_opt_varname_lang_default:nnn {#3} {#1} { tl } } + #4 { % If not found, try fallback. - \@@_get_fallback_unknown_lang_opt:nNF {#1} #2 - { - \tl_clear:N #2 - \msg_warning:nnn { zref-clever } - { missing-string } {#1} - } + \@@_opt_tl_get:cNF + { \@@_opt_varname_fallback:nn {#1} { tl } } + #4 + { \tl_clear:N #4 } } } } } } +\cs_generate_variant:Nn \@@_get_rf_opt_tl:nnnN { nxxN } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_get_ref_opt_font:nN} +% +% \begin{macro}{\@@_get_rf_opt_seq:nnnN} % \begin{syntax} -% \cs{@@_get_ref_opt_font:nN} \Arg{option} \Arg{tl variable} +% \cs{@@_get_rf_opt_seq:nnnN} \Arg{option} +% ~~\Arg{ref type} \Arg{language} \Arg{seq variable} % \end{syntax} % \begin{macrocode} -\cs_new_protected:Npn \@@_get_ref_opt_font:nN #1#2 +\cs_new_protected:Npn \@@_get_rf_opt_seq:nnnN #1#2#3#4 { % First attempt: general options. - \prop_get:NnNF \l_@@_ref_options_prop {#1} #2 + \@@_opt_seq_get:cNF + { \@@_opt_varname_general:nn {#1} { seq } } + #4 { % If not found, try type specific options. - \bool_if:nTF - { - \prop_if_exist_p:c - { - l_@@_type_ - \l_@@_label_type_a_tl _options_prop - } - } + \@@_opt_seq_get:cNF + { \@@_opt_varname_type:nnn {#2} {#1} { seq } } + #4 { - \prop_get:cnNF + % If not found, try type- and language-specific. + \@@_opt_seq_get:cNF + { \@@_opt_varname_lang_type:nnnn {#3} {#2} {#1} { seq } } + #4 { - l_@@_type_ - \l_@@_label_type_a_tl _options_prop + % If not found, try language-specific default. + \@@_opt_seq_get:cNF + { \@@_opt_varname_lang_default:nnn {#3} {#1} { seq } } + #4 + { + % If not found, try fallback. + \@@_opt_seq_get:cNF + { \@@_opt_varname_fallback:nn {#1} { seq } } + #4 + { \seq_clear:N #4 } + } } - {#1} #2 - { \tl_clear:N #2 } } - { \tl_clear:N #2 } } } +\cs_generate_variant:Nn \@@_get_rf_opt_seq:nnnN { nxxN } % \end{macrocode} % \end{macro} % % -% \begin{macro}{\@@_get_ref_opt_bool:nnN} +% \begin{macro}{\@@_get_rf_opt_bool:nnnnN} % \begin{syntax} -% \cs{@@_get_ref_opt_bool:nN} \Arg{option} -% ~~\Arg{default} \Arg{bool variable} +% \cs{@@_get_rf_opt_bool:nN} \Arg{option} \Arg{default} +% ~~\Arg{ref type} \Arg{language} \Arg{bool variable} % \end{syntax} % \begin{macrocode} -\cs_new_protected:Npn \@@_get_ref_opt_bool:nnN #1#2#3 +\cs_new_protected:Npn \@@_get_rf_opt_bool:nnnnN #1#2#3#4#5 { % First attempt: general options. - \prop_get:NnNF \l_@@_ref_options_prop {#1} \l_tmpa_tl + \@@_opt_bool_get:cNF + { \@@_opt_varname_general:nn {#1} { bool } } + #5 { % If not found, try type specific options. - \bool_lazy_and:nnTF - { - \prop_if_exist_p:c - { - l_@@_type_ - \l_@@_label_type_a_tl _options_prop - } - } - { - \prop_if_in_p:cn - { - l_@@_type_ - \l_@@_label_type_a_tl _options_prop - } - {#1} - } - { - \prop_get:cnN - { - l_@@_type_ - \l_@@_label_type_a_tl _options_prop - } - {#1} \l_tmpa_tl - } + \@@_opt_bool_get:cNF + { \@@_opt_varname_type:nnn {#3} {#1} { bool } } + #5 { % If not found, try type- and language-specific. - \@@_get_lang_opt_type:xxnNF - { \l_@@_ref_language_tl } - { \l_@@_label_type_a_tl } - {#1} \l_tmpa_tl + \@@_opt_bool_get:cNF + { \@@_opt_varname_lang_type:nnnn {#4} {#3} {#1} { bool } } + #5 { % If not found, try language-specific default. - \@@_get_lang_opt_default:xnNF - { \l_@@_ref_language_tl } - {#1} \l_tmpa_tl + \@@_opt_bool_get:cNF + { \@@_opt_varname_lang_default:nnn {#4} {#1} { bool } } + #5 { - % If not found, use default argument. - \bool_lazy_or:nnTF - { \str_if_eq_p:nn {#2} { true } } - { \str_if_eq_p:nn {#2} { false } } - { \tl_set:Nn \l_tmpa_tl {#2} } - { - % And, if even that fails, presume false. - \tl_set:Nn \l_tmpa_tl { false } - } + % If not found, try fallback. + \@@_opt_bool_get:cNF + { \@@_opt_varname_fallback:nn {#1} { bool } } + #5 + { \use:c { bool_set_ #2 :N } #5 } } } } } - % Having retrieved the option value, set the boolean. At this point, we - % *know* '\l_tmpa_tl' is either 'true' or 'false'. - \use:c { bool_set_ \l_tmpa_tl :N } #3 } +\cs_generate_variant:Nn \@@_get_rf_opt_bool:nnnnN { nnxxN } % \end{macrocode} % \end{macro} % % +% % \section{Compatibility} % % This section is meant to aggregate any ``special handling'' needed for @@ -5796,11 +6778,7 @@ % references \cs{textup}. % \begin{macrocode} \zcRefTypeSetup { equation } - { - reffont = \upshape , - preref = {\textup{(}} , - postref = {\textup{)}} , - } + { reffont = \upshape } \msg_info:nnn { zref-clever } { compat-package } { amsmath } } } @@ -6091,7 +7069,7 @@ % % \section{Language files} % -% Initial values for the English, German, French, Portuguese, and Spanish, +% Initial values for the English, German, French, Portuguese, and Spanish % language files have been provided by the author. Translations available for % document elements' names in other packages have been an useful reference for % the purpose, namely: \pkg{babel}, \pkg{cleveref}, \pkg{translator}, and @@ -6232,8 +7210,8 @@ type = equation , name-sg-ab = eq. , Name-pl-ab = Eqs. , name-pl-ab = eqs. , - preref = {(} , - postref = {)} , + refbounds-first-sg = {,(,),} , + refbounds = {(,,,)} , type = theorem , Name-sg = Theorem , @@ -6586,8 +7564,8 @@ type = equation , case = G , Name-sg = Gleichung , Name-pl = Gleichungen , - preref = {(} , - postref = {)} , + refbounds-first-sg = {,(,),} , + refbounds = {(,,,)} , type = theorem , gender = n , @@ -6931,8 +7909,8 @@ type = equation , name-sg = équation , Name-pl = Équations , name-pl = équations , - preref = {(} , - postref = {)} , + refbounds-first-sg = {,(,),} , + refbounds = {(,,,)} , type = theorem , gender = m , @@ -7180,8 +8158,8 @@ type = equation , name-sg-ab = eq. , Name-pl-ab = Eqs. , name-pl-ab = eqs. , - preref = {(} , - postref = {)} , + refbounds-first-sg = {,(,),} , + refbounds = {(,,,)} , type = theorem , gender = m , @@ -7411,8 +8389,8 @@ type = equation , name-sg = ecuación , Name-pl = Ecuaciones , name-pl = ecuaciones , - preref = {(} , - postref = {)} , + refbounds-first-sg = {,(,),} , + refbounds = {(,,,)} , type = theorem , gender = m , @@ -7648,8 +8626,8 @@ type = equation , name-sg-ab = vgl. , Name-pl-ab = Vgl.'s , name-pl-ab = vgl.'s , - preref = {(} , - postref = {)} , + refbounds-first-sg = {,(,),} , + refbounds = {(,,,)} , type = theorem , gender = f , @@ -7657,12 +8635,11 @@ type = theorem , name-sg = stelling , Name-pl = Stellingen , name-pl = stellingen , + % \end{macrocode} -% % 2022-01-09, \texttt{niluxv}: An alternative plural is ``lemmata''. That is % also a correct English plural for lemma, but the English language file % chooses ``lemmas''. For consistency we therefore choose ``lemma's''. -% % \begin{macrocode} type = lemma , gender = n , @@ -7726,11 +8703,10 @@ type = algorithm , name-sg = algoritme , Name-pl = Algoritmes , name-pl = algoritmes , + % \end{macrocode} -% % 2022-01-09, \texttt{niluxv}: EN-NL Van Dale translates listing as (3) % ``uitdraai van computerprogramma'', ``listing''. -% % \begin{macrocode} type = listing , gender = m , |