% -------------------------------------------------------------------------- % the CHEMNUM package % % a comprehensive approach for the numbering of chemical compounds % % -------------------------------------------------------------------------- % Clemens Niederberger % -------------------------------------------------------------------------- % https://github.org/cgnieder/chemnum/ % contact@mychemistry.eu % -------------------------------------------------------------------------- % If you have any ideas, questions, suggestions or bugs to report, please % feel free to contact me. % -------------------------------------------------------------------------- % Copyright 2011--2021 Clemens Niederberger % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2008/05/04 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Clemens Niederberger. % -------------------------------------------------------------------------- \RequirePackage{expl3,xparse,l3keys2e} \ExplSyntaxOn \tl_const:Nn \c_chemnum_date_tl {2021/01/21} \tl_const:Nn \c_chemnum_version_number_tl {1.3} \tl_const:Nn \c_chemnum_version_suffix_tl {a} \tl_const:Nx \c_chemnum_version_tl { \c_chemnum_version_number_tl \c_chemnum_version_suffix_tl } \tl_const:Nn \c_chemnum_info_tl {a~ comprehensive~ approach~ for~ the~ numbering~ of~ chemical~ compounds} % ---------------------------------------------------------------------------- % provide the package: \ProvidesExplPackage {chemnum} {\c_chemnum_date_tl} {\c_chemnum_version_tl} {\c_chemnum_info_tl \c_space_tl (CN)} % ---------------------------------------------------------------------------- % required packages: % language support: \RequirePackage{translations} % greek alphabet for the labels matching to chemmacros' selection: \RequirePackage{chemgreek} \RequirePackage{psfrag} % ---------------------------------------------------------------------------- % messages: \msg_new:nnn {chemnum} {missing-label} { The~ key~ `#1' \tl_if_blank:nF {#2} {~ of~`#2'} ~ has~ no~ label~ associated~ \msg_line_context: } \msg_new:nnn {chemnum} {erroneous-argument-combination} { Apparently~ you've~ used~ both~ the~ `*'~ and~ the~ `+'~ argument.~ This~ does~ not~ make~ sense.~ I'm~ doing~ nothing~ \msg_line_context: } \msg_new:nnn {chemnum} {unknown-counter-format} { I~ do~ not~ know~ the~ counter~ format~ `#1'.~ I'll~ use~ `arabic'~ instead~ \msg_line_context: } \msg_new:nnn {chemnum} {compound-not-initiated} { The~ compound~ `#1'~ has~ not~ been~ initiated~ \msg_line_context: } \msg_new:nnn {chemnum} {subcompound-not-initiated} { The~ compound~ `#1\l_chemnum_compound_separator_tl #2'~ has~ not~ been~ initiated~ \msg_line_context: } \msg_new:nnn {chemnum} {log-compound-silent} { ................................................. \\ . ~ \msg_info_text:n {chemnum}: ~ defined~ new~ compound~ `#1'~with~output~ `\chemnum_expandable_get_compound_property:nn {#1} {counter-representation}' . \\ ................................................. } \msg_new:nnn {chemnum} {log-compound-verbose} { ................................................. \\ . ~ \msg_info_text:n {chemnum}: ~ defined~ new~ compound: \\ . \c_space_tl \c_space_tl \c_space_tl ID ~=~ #1 \\ . \c_space_tl \c_space_tl \c_space_tl internal~ number ~=~ \chemnum_expandable_get_compound_property:nn {#1} {number} \\ . \c_space_tl \c_space_tl \c_space_tl label ~=~ \chemnum_expandable_get_compound_property:nn {#1} {counter-representation} \\ . \c_space_tl \c_space_tl \c_space_tl pre~ label~ code ~=~ \chemnum_expandable_get_compound_property:nn {#1} {pre-label-code} \\ . \c_space_tl \c_space_tl \c_space_tl post~ label~ code ~=~ \chemnum_expandable_get_compound_property:nn {#1} {post-label-code} \\ . \c_space_tl \c_space_tl \c_space_tl pre~ main~ label~ code ~=~ \chemnum_expandable_get_compound_property:nn {#1} {pre-main-label-code} \\ . \c_space_tl \c_space_tl \c_space_tl post~ main~ label~ code ~=~ \chemnum_expandable_get_compound_property:nn {#1} {post-main-label-code} \\ . \c_space_tl \c_space_tl \c_space_tl format ~=~ \chemnum_expandable_get_compound_property:nn {#1} {label-format} \\ ................................................. } \msg_new:nnn {chemnum} {log-subcompound-silent} { ................................................. \\ . ~ \msg_info_text:n {chemnum}: ~ defined~ new~ subcompound~ `#2'~ with~ output~ \chemnum_expandable_get_subcompound_property:nnn {#1} {#2} {counter-representation} \\ . ~ belonging~ to~ the~ main~ compound~ `#1'. \\ ................................................. } \msg_new:nnn {chemnum} {log-subcompound-verbose} { ................................................. \\ . ~ \msg_info_text:n {chemnum}: ~ defined~ new~ subcompound: \\ . \c_space_tl \c_space_tl \c_space_tl ID ~=~ #2 \\ . \c_space_tl \c_space_tl \c_space_tl main~ compound~ ID ~=~ \chemnum_expandable_get_subcompound_property:nnn {#1} {#2} {main-compound} \\ . \c_space_tl \c_space_tl \c_space_tl internal~ number ~=~ \chemnum_expandable_get_subcompound_property:nnn {#1} {#2} {number} \\ . \c_space_tl \c_space_tl \c_space_tl label ~=~ \chemnum_expandable_get_subcompound_property:nnn {#1} {#2} {counter-representation} \\ ................................................. } \msg_new:nnn {chemnum} {deprecated-command} { The~ command~ `\token_to_str:N #1'~ \msg_line_context: \c_space_tl is~ deprecated.~ Use~ `\token_to_str:N #2'~ instead.~ `\token_to_str:N #1'~ may~ be~ removed~ in~ future~ versions. } \msg_new:nnn {chemnum} {property-undefined} { The~ property~ `#2'~ for~ compound~ `#1'~ is~ undefined~ and~ thus~ cannot~ be~ set~ \msg_line_context: } % ---------------------------------------------------------------------------- % deprecated command names: % #1: old name % #2: new name \cs_new_protected:Npn \chemnum_deprecated_command:NN #1#2 { \cs_new_protected:Npn #1 { \msg_warning:nnnn {chemnum} {deprecated-command} {#1} {#2} #2 } } \chemnum_deprecated_command:NN \cmpdsetup \setchemnum \chemnum_deprecated_command:NN \cmpdinit \initcmpd \chemnum_deprecated_command:NN \cmpdref \replacecmpd \chemnum_deprecated_command:NN \cmpdreset \resetcmpd % ---------------------------------------------------------------------------- % variants of kernel functions: \cs_generate_variant:Nn \prop_gput:Nnn {Nnx,cnx,cnV} \cs_generate_variant:Nn \prop_put:Nnn {NV,NVV,NVx} \cs_generate_variant:Nn \prop_if_in:NnTF {NV} \cs_generate_variant:Nn \quark_if_no_value:nTF {V} \cs_generate_variant:Nn \quark_if_no_value:nF {V} \cs_generate_variant:Nn \seq_set_split:Nnn {NV,NVV} \cs_generate_variant:Nn \seq_use:Nnnn {NVVV} \cs_generate_variant:Nn \tl_if_eq:nnF {Vx} \cs_generate_variant:Nn \tl_if_in:nnTF {VV} % ---------------------------------------------------------------------------- % temporary variables: \tl_new:N \l__chemnum_tmpa_tl \tl_new:N \l__chemnum_tmpb_tl \seq_new:N \l__chemnum_tmpa_seq \seq_new:N \l__chemnum_tmpb_seq \seq_new:N \l__chemnum_tmpc_seq \seq_new:N \l__chemnum_tmpd_seq \seq_new:N \l__chemnum_tmpe_seq \int_new:N \l__chemnum_tmpa_int \int_new:N \l__chemnum_tmpb_int \int_new:N \l__chemnum_tmpc_int \str_new:N \l__chemnum_tmpa_str % ---------------------------------------------------------------------------- % variables: \prop_new:N \l__chemnum_label_formats_prop % the main label counter: % not very expl3 like but allows `cmpdmain' to be added to the \cl@ % list, i.e., it can e.g. be reset for every chapter: \newcounter{cmpdmain} % counter for internal reference if needed. Will be a unique number in order % of declaration: \int_new:N \g__chemnum_main_int \int_new:N \l__chemnum_compound_replace_int \seq_new:N \g_chemnum_initiated_compounds_seq \seq_new:N \g__chemnum_defined_compounds_seq \seq_new:N \g__chemnum_compound_defined_subcompounds_seq \tl_const:Nn \c_chemnum_nothing_here_tl {??} \tl_new:N \l__chemnum_label_format_tl \tl_set:Nn \l__chemnum_label_format_tl {\bfseries} \tl_new:N \l__chemnum_local_label_format_tl \tl_set_eq:NN \l__chemnum_local_label_format_tl \l__chemnum_label_format_tl \tl_new:N \l__chemnum_default_counter_representation_tl \tl_set:Nn \l__chemnum_default_counter_representation_tl {arabic} \tl_new:N \l__chemnum_default_subcounter_representation_tl \tl_set:Nn \l__chemnum_default_subcounter_representation_tl {alph} \tl_new:N \l__chemnum_pre_counter_default_tl \tl_new:N \l__chemnum_post_counter_default_tl \tl_new:N \l__chemnum_pre_label_default_tl \tl_new:N \l__chemnum_post_label_default_tl \tl_new:N \l__chemnum_pre_main_label_default_tl \tl_new:N \l__chemnum_post_main_label_default_tl \tl_new:N \l__chemnum_main_separator_tl \tl_set:Nn \l__chemnum_main_separator_tl {,} \tl_new:N \l__chemnum_sub_separator_tl \tl_set:Nn \l__chemnum_sub_separator_tl {,} \tl_new:N \l_chemnum_compound_separator_tl \tl_set:Nn \l_chemnum_compound_separator_tl {.} \tl_new:N \l__chemnum_sep_list_two_tl \tl_set:Nn \l__chemnum_sep_list_two_tl { \GetTranslation {chemnum-sep-two} } \tl_new:N \l__chemnum_sep_list_more_tl \tl_set:Nn \l__chemnum_sep_list_more_tl {,~} \tl_new:N \l__chemnum_sep_list_last_two_tl \tl_set:Nn \l__chemnum_sep_list_last_two_tl { \GetTranslation {chemnum-sep-last-two} } \tl_new:N \l__chemnum_sep_sublist_two_tl \tl_set:Nn \l__chemnum_sep_sublist_two_tl {,} \tl_new:N \l__chemnum_sep_sublist_more_tl \tl_set:Nn \l__chemnum_sep_sublist_more_tl {,} \tl_new:N \l__chemnum_sep_sublist_last_two_tl \tl_set:Nn \l__chemnum_sep_sublist_last_two_tl {,} \tl_new:N \l__chemnum_sep_sublist_range_tl \tl_set:Nn \l__chemnum_sep_sublist_range_tl {--} \tl_new:N \l__chemnum_compound_replace_tl \tl_new:N \l__chemnum_compound_replace_format_tl \tl_new:N \l__chemnum_compound_replace_local_format_tl \tl_set:Nn \l__chemnum_compound_replace_format_tl {\sffamily} \tl_new:N \l__chemnum_compound_replace_tag_tl \tl_set:Nn \l__chemnum_compound_replace_tag_tl {TMP} \tl_new:N \l__chemnum_psfrag_texpos_tl \tl_new:N \l__chemnum_psfrag_local_texpos_tl \tl_set:Nn \l__chemnum_psfrag_texpos_tl {b} \tl_new:N \l__chemnum_psfrag_pspos_tl \tl_new:N \l__chemnum_psfrag_local_pspos_tl \tl_set:Nn \l__chemnum_psfrag_pspos_tl {b} \bool_new:N \l__chemnum_compound_local_bool \bool_new:N \g__chemnum_initiate_bool \bool_new:N \g__chemnum_initiate_strict_bool \bool_new:N \g__chemnum_initiate_sub_bool \bool_new:N \l__chemnum_log_bool \bool_set_true:N \l__chemnum_log_bool \bool_new:N \l__chemnum_log_verbose_bool \bool_new:N \l__chemnum_compress_subcompounds_bool \bool_set_true:N \l__chemnum_compress_subcompounds_bool \bool_new:N \l__chemnum_merge_list_bool \bool_new:N \l__chemnum_sub_only_bool \bool_new:N \l__chemnum_sub_all_bool \bool_new:N \l__chemnum_show_def_bool \bool_new:N \l__chemnum_show_ref_bool \bool_new:N \l__chemnum_compound_replace_auto_bool \bool_set_true:N \l__chemnum_compound_replace_auto_bool \bool_new:N \l__chemnum_compound_replace_auto_this_bool \bool_set_true:N \l__chemnum_compound_replace_auto_this_bool \bool_new:N \l__chemnum_replace_local_bool \bool_new:N \l__chemnum_hyperlinks_bool % ---------------------------------------------------------------------------- % label formats: % #1: name % #2: function with 1 n-type argument that takes an integer \cs_new_protected:Npn \chemnum_add_label_format:nn #1#2 { \cs_if_exist:cTF { __chemnum_#1_label_format:n } { \cs_set:cpn { __chemnum_#1_label_format:n } ##1 { #2 {##1} } } { \cs_new:cpn { __chemnum_#1_label_format:n } ##1 { #2 {##1} } } \prop_put:Nnx \l__chemnum_label_formats_prop {#1} { \exp_not:c { __chemnum_#1_label_format:n } } } % a user level command to add new formats \NewDocumentCommand \newcmpdcounterformat {mm} { \chemnum_add_label_format:nn {#1} {#2} } \newcmpdcounterformat {arabic} { \int_to_arabic:n } \newcmpdcounterformat {alph} { \int_to_alph:n } \newcmpdcounterformat {Alph} { \int_to_Alph:n } \newcmpdcounterformat {roman} { \int_to_roman:n } \newcmpdcounterformat {Roman} { \int_to_Roman:n } \newcmpdcounterformat {greek} { \chemgreek_int_to_greek:n } \newcmpdcounterformat {Greek} { \chemgreek_int_to_Greek:n } % ---------------------------------------------------------------------------- %%% options % options assigned to group `compound' are only setable with the \cmpd command % except they're _also_ asigned to the `general' group; likewise options that % are assigned to the group `general' can only be set with \setchemnum except % they're also assigned to the `compound' group. \keys_define:nn {chemnum} { local .bool_set:N = \l__chemnum_compound_local_bool , local .groups:n = {compound} , % counter: counter-within .code:n = \@addtoreset{cmpdmain}{#1} , counter-within .groups:n = {general} , counter-format .code:n = \prop_if_in:NnTF \l__chemnum_label_formats_prop {#1} { \tl_set:Nn \l__chemnum_default_counter_representation_tl {#1} } { \msg_warning:nnn {chemnum} {unknown-counter-format} {#1} \tl_set:Nn \l__chemnum_default_counter_representation_tl {arabic} } , counter-format .groups:n = {compound,general} , sub-counter-format .code:n = \prop_if_in:NnTF \l__chemnum_label_formats_prop {#1} { \tl_set:Nn \l__chemnum_default_subcounter_representation_tl {#1} } { \msg_warning:nnn {chemnum} {unknown-counter-format} {#1} \tl_set:Nn \l__chemnum_default_subcounter_representation_tl {arabic} } , sub-counter-format .groups:n = {compound,general} , % label: pre-label-code .tl_set:N = \l__chemnum_pre_label_default_tl , pre-label-code .groups:n = {compound,general} , post-label-code .tl_set:N = \l__chemnum_post_label_default_tl , post-label-code .groups:n = {compound,general} , pre-main-label-code .tl_set:N = \l__chemnum_pre_main_label_default_tl , pre-main-label-code .groups:n = {compound,general} , post-main-label-code .tl_set:N = \l__chemnum_post_main_label_default_tl , post-main-label-code .groups:n = {compound,general} , main-sub-sep .tl_set:N = \l_chemnum_compound_separator_tl , main-sub-sep .groups:n = {general,list} , list-label-sep .tl_set:N = \l__chemnum_main_separator_tl , list-label-sep .groups:n = {general,list} , sub-list-label-sep .tl_set:N = \l__chemnum_sub_separator_tl , sub-list-label-sep .groups:n = {general,list} , format .code:n = \tl_set:Nn \l__chemnum_local_label_format_tl {#1} \bool_if:NF \l__chemnum_compound_local_bool { \tl_set:Nn \l__chemnum_label_format_tl {#1} } , format .groups:n = {compound,general} , sub-only .bool_set:N = \l__chemnum_sub_only_bool , sub-only .groups:n = {compound,sub-only} , sub-all .bool_set:N = \l__chemnum_sub_all_bool , sub-all .groups:n = {compound} , compress .bool_set:N = \l__chemnum_compress_subcompounds_bool , compress .groups:n = {compound,general} , merge .bool_set:N = \l__chemnum_merge_list_bool , merge .groups:n = {general,list} , % initiation: init .choice: , init / true .code:n = \bool_set_true:N \g__chemnum_initiate_bool \bool_set_true:N \g__chemnum_initiate_sub_bool \bool_set_false:N \g__chemnum_initiate_strict_bool , init / main .code:n = \bool_set_true:N \g__chemnum_initiate_bool \bool_set_false:N \g__chemnum_initiate_sub_bool \bool_set_false:N \g__chemnum_initiate_strict_bool , init / false .code:n = \bool_set_false:N \g__chemnum_initiate_bool \bool_set_false:N \g__chemnum_initiate_sub_bool \bool_set_false:N \g__chemnum_initiate_strict_bool , init / strict .code:n = \bool_set_true:N \g__chemnum_initiate_bool \bool_set_true:N \g__chemnum_initiate_sub_bool \bool_set_true:N \g__chemnum_initiate_strict_bool , init / main-strict .code:n = \bool_set_true:N \g__chemnum_initiate_bool \bool_set_false:N \g__chemnum_initiate_sub_bool \bool_set_true:N \g__chemnum_initiate_strict_bool , init .default:n = true , init .groups:n = {general} , % list processing: list-sep-two .tl_set:N = \l__chemnum_sep_list_two_tl , list-sep-two .groups:n = {general,list} , list-sep-more .tl_set:N = \l__chemnum_sep_list_more_tl , list-sep-more .groups:n = {general,list} , list-sep-last-two .tl_set:N = \l__chemnum_sep_list_last_two_tl , list-sep-last-two .groups:n = {general,list} , sub-list-sep-two .tl_set:N = \l__chemnum_sep_sublist_two_tl , sub-list-sep-two .groups:n = {compound,general} , sub-list-sep-more .tl_set:N = \l__chemnum_sep_sublist_more_tl , sub-list-sep-more .groups:n = {compound,general} , sub-list-sep-last-two .tl_set:N = \l__chemnum_sep_sublist_last_two_tl , sub-list-sep-last-two .groups:n = {compound,general} , sub-list-sep-range .tl_set:N = \l__chemnum_sep_sublist_range_tl , sub-list-sep-range .groups:n = {compound,general} , % logging and other information: log .choice: , log / true .code:n = \bool_set_true:N \l__chemnum_log_bool \bool_set_false:N \l__chemnum_log_verbose_bool , log / silent .code:n = \bool_set_true:N \l__chemnum_log_bool \bool_set_false:N \l__chemnum_log_verbose_bool , log / false .code:n = \bool_set_false:N \l__chemnum_log_bool \bool_set_false:N \l__chemnum_log_verbose_bool , log / verbose .code:n = \bool_set_true:N \l__chemnum_log_bool \bool_set_true:N \l__chemnum_log_verbose_bool , log .default:n = true , log .groups:n = {general} , show-keys .choice: , show-keys / true .code:n = \bool_set_true:N \l__chemnum_show_def_bool \bool_set_true:N \l__chemnum_show_ref_bool , show-keys / false .code:n = \bool_set_false:N \l__chemnum_show_def_bool \bool_set_false:N \l__chemnum_show_ref_bool , show-keys / def .code:n = \bool_set_true:N \l__chemnum_show_def_bool \bool_set_false:N \l__chemnum_show_ref_bool , show-keys / ref .code:n = \bool_set_false:N \l__chemnum_show_def_bool \bool_set_true:N \l__chemnum_show_ref_bool , show-keys .default:n = true , show-keys .groups:n = {general} , replace .bool_set:N = \l__chemnum_replace_local_bool , replace .groups:n = {replace} , replace-auto .bool_set:N = \l__chemnum_compound_replace_auto_bool , replace-tag .tl_set:N = \l__chemnum_compound_replace_tag_tl , replace-tag .groups:n = {general} , tag .code:n = \tl_set:Nn \l__chemnum_compound_replace_tag_tl {#1} \bool_set_false:N \l__chemnum_compound_replace_auto_this_bool , tag .groups:n = {replace} , replace-tag-nr .code:n = \int_set:Nn \l__chemnum_compound_replace_int { (#1) - 1 } , replace-tag-nr .groups:n = {general} , replace-tag-nr .initial:n = {1} , replace-style .tl_set:N = \l__chemnum_compound_replace_format_tl , replace-style .groups:n = {general} , style .code:n = \tl_set:Nn \l__chemnum_compound_replace_local_format_tl {#1} \bool_set_true:N \l__chemnum_replace_local_bool , style .groups:n = {replace} , replace-pos .code:n = \__chemnum_set_psfrag_pos:nn #1 , replace-pos .groups:n = {general} , pos .code:n = \bool_set_true:N \l__chemnum_replace_local_bool \__chemnum_set_psfrag_local_pos:nn #1 , pos .groups:n = {replace} , hyperlinks .bool_set:N = \l__chemnum_hyperlinks_bool , hyperlinks .groups:n = {general} , } % ---------------------------------------------------------------------------- % #1: int variable that holds the value % #2: the chosen format % this command is expandable \cs_new:Npn \__chemnum_label_format:Nn #1#2 { \prop_if_in:NnTF \l__chemnum_label_formats_prop {#2} { \use:c { __chemnum_#2_label_format:n } {#1} } { \__chemnum_arabic_label_format:n {#1} } } \cs_generate_variant:Nn \__chemnum_label_format:Nn {NV,cV} % ---------------------------------------------------------------------------- % auxiliary file -- we'll use the .aux file % first let's add dummy definitions so we can hopefully avoid error messages % if the `chemnum' package is removed from the preamble \hook_gput_code:nnn {begindocument} {chemnum} { \legacy_if:nT {@filesw} { \iow_now:Nn \@auxout { \providecommand\chemnum@cmpd[8]{} ^^J \providecommand\chemnum@subcmpd[4]{} ^^J \providecommand\chemnum@check{} } } } % we use this one to trigger a LaTeX rerun warning -- to be precise the % ``Label(s) may have changed'' warning: \cs_new_protected:Npn \__chemnum_rerun: { \hook_gput_code:nnn {enddocument} {code} { \def \chemnum@check { \@tempswatrue } } } % add the rerun check at the end: \hook_gput_code:nnn {enddocument} {code} { \legacy_if:nT {@filesw} { \iow_now:Nn \@auxout { \chemnum@check } } } % ---------------------------------------------------------------------------- % initiating new compounds % - property list that holds % - ID % - counter value % - counter represetation % - pre-counter-code % - post-counter-code % - pre-label-code % - post-label-code % - formatting code % - add to list of initiated compounds \cs_new_protected:Npn \chemnum_initiate_compound:n #1 { \chemnum_compound_if_initiated:nF {#1} { \seq_gput_right:Nn \g_chemnum_initiated_compounds_seq {#1} } } % #1: ID \cs_new_protected:Npn \chemnum_define_compound:n #1 { \chemnum_initialize_compound:n {#1} \chemnum_compound_declare_properties:nn {#1} { ID , number , counter-representation , pre-label-code , post-label-code , pre-main-label-code , post-main-label-code , label-format } \chemnum_compound_set_property:nnn {#1} {ID} {#1} \chemnum_compound_set_property:nnx {#1} {number} { \int_use:N \c@cmpdmain } \chemnum_compound_set_property:nnx {#1} {counter-representation} { \exp_not:V \l__chemnum_pre_counter_default_tl \__chemnum_label_format:NV \c@cmpdmain % \g__chemnum_main_int \l__chemnum_default_counter_representation_tl \exp_not:V \l__chemnum_post_counter_default_tl } \chemnum_compound_set_property:nnV {#1} {pre-label-code} \l__chemnum_pre_label_default_tl \chemnum_compound_set_property:nnV {#1} {post-label-code} \l__chemnum_post_label_default_tl \chemnum_compound_set_property:nnV {#1} {pre-main-label-code} \l__chemnum_pre_main_label_default_tl \chemnum_compound_set_property:nnV {#1} {post-main-label-code} \l__chemnum_post_main_label_default_tl \chemnum_compound_set_property:nnV {#1} {label-format} \l__chemnum_label_format_tl } \cs_new_protected:Npn \chemnum_finalize_compound:n #1 { \chemnum_compound_update_properties:n {#1} \chemnum_save_compound_to_auxfile:n {#1} \chemnum_log_main:n {#1} } % TODO: keep? and if: what should it set? \cs_new_protected:Npn \chemnum_set_compound:n #1 { % those should be done: however, they overwrite existing options in any % case... this would overwrite options that really should stay set. % \chemnum_compound_set_property:nnV {#1} {pre-label-code} % \l__chemnum_pre_label_default_tl % \chemnum_compound_set_property:nnV {#1} {post-label-code} % \l__chemnum_post_label_default_tl % \chemnum_compound_set_property:nnV {#1} {post-main-label-code} % \l__chemnum_post_main_label_default_tl % \chemnum_compound_set_property:nnV {#1} {label-format} % \l__chemnum_label_format_tl % \chemnum_save_compound_to_auxfile:n {#1} % \chemnum_compound_update_properties:n {#1} } % we can use this command as a hook through redefinition: \cs_new_protected:Npn \chemnum_initialize_compound:n #1 { \chemnum_init_raw_compound:n {#1} } \cs_new_protected:Npn \chemnum_init_raw_compound:n #1 { \seq_if_in:NnF \g__chemnum_defined_compounds_seq {#1} { \seq_gput_right:Nn \g__chemnum_defined_compounds_seq {#1} \int_gincr:N \g__chemnum_main_int \stepcounter{cmpdmain} } \seq_if_exist:cF {g__chemnum_#1_initiated_subcompounds_seq} { \seq_new:c {g__chemnum_#1_initiated_subcompounds_seq} } } % #1: main ID % #2: sub ID \cs_new_protected:Npn \chemnum_define_subcompound:nn #1#2 { \chemnum_initialize_subcompound:nn {#1} {#2} \chemnum_subcompound_declare_properties:nnn {#1} {#2} { ID , main-compound , number , counter-representation } \chemnum_subcompound_set_property:nnnn {#1} {#2} {ID} {#2} \chemnum_subcompound_set_property:nnnn {#1} {#2} {main-compound} {#1} \chemnum_subcompound_set_property:nnnx {#1} {#2} {number} { \int_use:c {g__chemnum_compound_#1_subcompound_int} } \chemnum_subcompound_set_property:nnnx {#1} {#2} {counter-representation} { \__chemnum_label_format:cV {g__chemnum_compound_#1_subcompound_int} \l__chemnum_default_subcounter_representation_tl } } \cs_new_protected:Npn \chemnum_finalize_subcompound:nn #1#2 { \chemnum_save_subcompound_to_auxfile:nn {#1} {#2} \chemnum_subcompound_update_properties:nn {#1} {#2} \chemnum_log_sub:nn {#1} {#2} } \cs_new_protected:Npn \chemnum_initialize_subcompound:nn #1#2 { \int_if_exist:cF {g__chemnum_compound_#1_subcompound_int} { \int_new:c {g__chemnum_compound_#1_subcompound_int} } \int_gincr:c {g__chemnum_compound_#1_subcompound_int} \seq_if_exist:cF {g__chemnum_compound_#1_subcompounds_seq} { \seq_new:c {g__chemnum_compound_#1_subcompounds_seq} } \prop_if_exist:cF {g__chemnum_compound_#1_subcompounds_prop} { \prop_new:c {g__chemnum_compound_#1_subcompounds_prop} } \seq_if_in:cnF {g__chemnum_compound_#1_subcompounds_seq} {#2} { \seq_gput_right:cn {g__chemnum_compound_#1_subcompounds_seq} {#2} } \seq_gput_right:Nn \g__chemnum_compound_defined_subcompounds_seq {#1#2} \prop_gput:cnx {g__chemnum_compound_#1_subcompounds_prop} {#2} { \int_use:c {g__chemnum_compound_#1_subcompound_int} : \__chemnum_label_format:cV {g__chemnum_compound_#1_subcompound_int} \l__chemnum_default_subcounter_representation_tl } } % #1: main ID \prg_new_conditional:Npnn \chemnum_if_subcompounds:n #1 {T,F,TF} { \seq_if_exist:cTF {g__chemnum_compound_#1_subcompounds_seq} { \prg_return_true: } { \prg_return_false: } } % #1: main ID \cs_new:Npn \chemnum_count_subcompounds:n #1 { \int_use:c {g__chemnum_compound_#1_subcompound_int} } % #1: main ID % #2: index \cs_new:Npn \chemnum_get_subcompound:nn #1#2 { \seq_item:cn {g__chemnum_compound_#1_subcompounds_seq} {#2} } % ---------------------------------------------------------------------------- \cs_new:Npn \__chemnum_nothing_here:n #1 { \c_chemnum_nothing_here_tl \msg_warning:nnn {chemnum} {missing-label} {#1} } \cs_new:Npn \__chemnum_nothing_here:nn #1#2 { \c_chemnum_nothing_here_tl \msg_warning:nnnn {chemnum} {missing-label} {#1} {#2} } \cs_generate_variant:Nn \__chemnum_nothing_here:nn {x} % ---------------------------------------------------------------------------- \cs_new_protected:Npn \chemnum_log_main:n #1 { \bool_if:NT \l__chemnum_log_bool { \bool_if:NTF \l__chemnum_log_verbose_bool { \msg_log:nnn {chemnum} {log-compound-verbose} {#1} } { \msg_log:nnn {chemnum} {log-compound-silent} {#1} } } } \cs_new_protected:Npn \chemnum_log_sub:nn #1#2 { \bool_if:NT \l__chemnum_log_bool { \bool_if:NTF \l__chemnum_log_verbose_bool { \msg_log:nnnn {chemnum} {log-subcompound-verbose} {#1} {#2} } { \msg_log:nnnn {chemnum} {log-subcompound-silent} {#1} {#2} } } } % ---------------------------------------------------------------------------- % #1: ID \prg_new_protected_conditional:Npnn \chemnum_compound_if_initiated:n #1 { T,F,TF } { \seq_if_in:NnTF \g_chemnum_initiated_compounds_seq {#1} { \prg_return_true: } { \prg_return_false: } } % #1: main ID % #2: sub ID \prg_new_protected_conditional:Npnn \chemnum_subcompound_if_initiated:nn #1#2 { T,F,TF } { \seq_if_in:cnTF {g__chemnum_#1_initiated_subcompounds_seq} {#2} { \prg_return_true: } { \prg_return_false: } } % #1: ID \prg_new_protected_conditional:Npnn \chemnum_compound_if_defined:n #1 { T,F,TF } { \seq_if_in:NnTF \g__chemnum_defined_compounds_seq {#1} { \prg_return_true: } { \prg_return_false: } } % #1: main ID % #2: sub ID \prg_new_protected_conditional:Npnn \chemnum_subcompound_if_defined:nn #1#2 { T,F,TF } { \seq_if_in:NnTF \g__chemnum_compound_defined_subcompounds_seq {#1#2} { \prg_return_true: } { \prg_return_false: } } % ---------------------------------------------------------------------------- % #1: ID % #2: property to be defined \cs_new_protected:Npn \chemnum_compound_declare_property:nn #1#2 { \seq_if_exist:cF {g__chemnum_compound_#1_properties_seq } { \seq_new:c {g__chemnum_compound_#1_properties_seq} } \prop_if_exist:cF {g__chemnum_compound_#1_prop} { \prop_new:c {g__chemnum_compound_#1_prop} } \seq_if_in:cnF {g__chemnum_compound_#1_properties_seq} {#2} { \seq_gput_right:cn {g__chemnum_compound_#1_properties_seq} {#2} } } % #1: ID % #2: properties to be defined \cs_new_protected:Npn \chemnum_compound_declare_properties:nn #1#2 { \clist_map_inline:nn {#2} { \chemnum_compound_declare_property:nn {#1} {##1} } } % #1: ID % #2: property to be set % #3: value of property \cs_new_protected:Npn \chemnum_compound_set_property:nnn #1#2#3 { \seq_if_in:cnTF {g__chemnum_compound_#1_properties_seq} {#2} { \prop_gput:cnn {g__chemnum_compound_#1_prop} {#2} {#3} } { \msg_error:nnn {chemnum} {property-undefined} {#1} {#2} } } \cs_generate_variant:Nn \chemnum_compound_set_property:nnn {nnV,nnx} % #1: ID % #2: property to be updated \cs_new_protected:Npn \chemnum_compound_update_property:nn #1#2 { \seq_if_in:cnTF {g__chemnum_compound_#1_properties_seq} {#2} { \prop_get:cnN {g__chemnum_compound_#1_prop} {previous-#2} \l__chemnum_tmpa_tl \prop_get:cnN {g__chemnum_compound_#1_prop} {#2} \l__chemnum_tmpb_tl \tl_if_eq:NNF \l__chemnum_tmpb_tl \l__chemnum_tmpa_tl { \prop_gput:cnV {g__chemnum_compound_#1_prop} {previous-#2} \l__chemnum_tmpb_tl } } { \msg_error:nnn {chemnum} {property-undefined} {#1} {#2} } } % #1: ID \cs_new_protected:Npn \chemnum_compound_update_properties:n #1 { \seq_map_inline:cn {g__chemnum_compound_#1_properties_seq} { \chemnum_compound_update_property:nn {#1} {##1} } } % #1: main ID % #2. sub ID % #3: property to be defined \cs_new_protected:Npn \chemnum_subcompound_declare_property:nnn #1#2#3 { \seq_if_in:cnF {g__chemnum_compound_#1_#2_properties_seq} {#3} { \seq_gput_right:cn {g__chemnum_compound_#1_#2_properties_seq} {#3} } } % #1: main ID % #2. sub ID % #3: properties to be defined \cs_new_protected:Npn \chemnum_subcompound_declare_properties:nnn #1#2#3 { \seq_if_exist:cF {g__chemnum_compound_#1_#2_properties_seq} { \seq_new:c {g__chemnum_compound_#1_#2_properties_seq} } \prop_if_exist:cF {g__chemnum_compound_#1_#2_properties_prop} { \prop_new:c {g__chemnum_compound_#1_#2_properties_prop} } \clist_map_inline:nn {#3} { \chemnum_subcompound_declare_property:nnn {#1} {#2} {##1} } } % #1: main ID % #2: sub ID % #3: property to be set % #4: value of property \cs_new_protected:Npn \chemnum_subcompound_set_property:nnnn #1#2#3#4 { \seq_if_in:cnTF {g__chemnum_compound_#1_#2_properties_seq} {#3} { \prop_gput:cnn {g__chemnum_compound_#1_#2_properties_prop} {#3} {#4} } { \msg_error:nnn {chemnum} {property-undefined} {#1.#2} {#3} } } \cs_generate_variant:Nn \chemnum_subcompound_set_property:nnnn {nnnV,nnnx} % #1: main ID % #2. sub ID % #3: property to be updated \cs_new_protected:Npn \chemnum_subcompound_update_property:nnn #1#2#3 { \seq_if_in:cnTF {g__chemnum_compound_#1_#2_properties_seq} { \prop_get:cnN {g__chemnum_compound_#1_#2_properties_prop} {previous-#3} \l__chemnum_tmpa_tl \prop_get:cnN {g__chemnum_compound_#1_#2_properties_prop} {#3} \l__chemnum_tmpb_tl \tl_if_eq:NNF \l__chemnum_tmpb_tl \l__chemnum_tmpa_tl { \prop_gput:cnV {g__chemnum_compound_#1_#2_properties_prop} {previous-#3} \l__chemnum_tmpb_tl } } { \msg_error:nnn {chemnum} {property-undefined} {#1.#2} {#3} } } % #1: main ID % #2: sub ID \cs_new_protected:Npn \chemnum_subcompound_update_properties:nn #1#2 { \seq_map_inline:cn {g__chemnum_compound_#1_#2_properties_seq} { \chemnum_subcompound_update_property:nnn {#1} {#2} {##1} } } % #1: ID % #2: property \cs_new_protected:Npn \chemnum_get_compound_property:nn #1#2 { \chemnum_get_compound_property_or:nnn {#1} {#2} { } } \cs_new_protected:Npn \chemnum_get_compound_property_or:nnn #1#2#3 { \prop_get:cnNTF {g__chemnum_compound_#1_prop} {#2} \l__chemnum_tmpa_tl { \tl_use:N \l__chemnum_tmpa_tl } {#3} } \cs_new:Npn \chemnum_expandable_get_compound_property:nn #1#2 { \prop_item:cn {g__chemnum_compound_#1_prop} {#2} } \cs_generate_variant:Nn \chemnum_expandable_get_compound_property:nn {V} % #1: main ID % #2: sub ID % #3: property \cs_new_protected:Npn \chemnum_get_subcompound_property:nnn #1#2#3 { \chemnum_get_subcompound_property_or:nnnn {#1} {#2} {#3} { } } \cs_new_protected:Npn \chemnum_get_subcompound_property_or:nnnn #1#2#3#4 { \prop_get:cnNTF {g__chemnum_compound_#1_#2_properties_prop} {#3} \l__chemnum_tmpa_tl { \tl_use:N \l__chemnum_tmpa_tl } {#4} } \cs_new:Npn \chemnum_expandable_get_subcompound_property:nnn #1#2#3 { \prop_item:cn {g__chemnum_compound_#1_#2_properties_prop} {#3} } % ---------------------------------------------------------------------------- \DeclareExpandableDocumentCommand \cmpdproperty { mm } { \chemnum_expandable_get_compound_property:nn {#1} {#2} } \DeclareExpandableDocumentCommand \subcmpdproperty { mmm } { \chemnum_expandable_get_subcompound_property:nnn {#1} {#2} {#3} } % #1: property % #2: ID % #3: value \NewDocumentCommand \setcmpdproperty {mmm} { \chemnum_compound_set_property:nnn {#2} {#1} {#3} \chemnum_finalize_compound:n {#1} } \NewDocumentCommand \setcmpdlabel {mm} { \setcmpdproperty {counter-representation} {#1} {#2} } % ---------------------------------------------------------------------------- % initiating subcompounds: % #1: main ID % #2: sub ID \cs_new_protected:Npn \chemnum_initiate_subcompound:nn #1#2 { \chemnum_subcompound_if_initiated:nnF {#1} {#2} { \seq_gput_right:cn {g__chemnum_#1_initiated_subcompounds_seq} {#2} } } % ---------------------------------------------------------------------------- % saving compounds to the auxilliary file: % #1: ID % #2: counter value % #3: counter representation % #4: pre label % #5: post label % #6: pre main label % #7: post main label % #8: label format \cs_new_protected:Npn \__chemnum_write_compound_to_auxfile_x:nnnnnnnn #1#2#3#4#5#6#7#8 { \hook_gput_code:nnn {begindocument} {chemnum} { \legacy_if:nT {@filesw} { \iow_now:Nx \@auxout { \exp_not:N \chemnum@cmpd {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8} } } } } \cs_generate_variant:Nn \__chemnum_write_compound_to_auxfile_x:nnnnnnnn {nnnVVVVV} \cs_new_protected:Npn \chemnum_save_compound_to_auxfile:n #1 { \__chemnum_write_compound_to_auxfile_x:nnnnnnnn {#1} { \chemnum_expandable_get_compound_property:nn {#1} {number} } { \chemnum_expandable_get_compound_property:nn {#1} {counter-representation} } { \chemnum_expandable_get_compound_property:nn {#1} {pre-label-code} } { \chemnum_expandable_get_compound_property:nn {#1} {post-label-code} } { \chemnum_expandable_get_compound_property:nn {#1} {pre-main-label-code} } { \chemnum_expandable_get_compound_property:nn {#1} {post-main-label-code} } { \chemnum_expandable_get_compound_property:nn {#1} {label-format} } } % #1: main ID % #2: sub ID % #2: counter value % #3: counter representation \cs_new_protected:Npn \__chemnum_write_subcompound_to_auxfile_x:nnnn #1#2#3#4 { \legacy_if:nT {@filesw} { \iow_now:Nx \@auxout { \exp_not:N \chemnum@subcmpd {#1}{#2}{#3}{#4} } } } \cs_new_protected:Npn \chemnum_save_subcompound_to_auxfile:nn #1#2 { \__chemnum_write_subcompound_to_auxfile_x:nnnn {#1} {#2} { \chemnum_expandable_get_subcompound_property:nnn {#1} {#2} {number} } { \chemnum_expandable_get_subcompound_property:nnn {#1} {#2} {counter-representation} } } % ---------------------------------------------------------------------------- % #1: ID % #2: counter value % #3: counter representation % #4: pre label % #5: post label % #6: pre main label % #7: post main label % #8: label format \cs_new_protected:Npn \chemnum@cmpd #1#2#3#4#5#6#7#8 { % \chemnum_initialize_compound:n {#1} \prop_if_exist:cF {g__chemnum_compound_#1_prop} { \prop_new:c {g__chemnum_compound_#1_prop} } \prop_gput:cnn {g__chemnum_compound_#1_prop} {previous-number} {#2} \prop_gput:cnn {g__chemnum_compound_#1_prop} {previous-counter-representation} {#3} \prop_gput:cnn {g__chemnum_compound_#1_prop} {previous-pre-label-code} {#4} \prop_gput:cnn {g__chemnum_compound_#1_prop} {previous-post-label-code} {#5} \prop_gput:cnn {g__chemnum_compound_#1_prop} {previous-pre-main-label-code} {#6} \prop_gput:cnn {g__chemnum_compound_#1_prop} {previous-post-main-label-code} {#7} \prop_gput:cnn {g__chemnum_compound_#1_prop} {previous-label-format} {#8} } % #1: main ID % #2: sub ID % #3: counter value % #4: counter representation \cs_new_protected:Npn \chemnum@subcmpd #1#2#3#4 { \prop_if_exist:cF {g__chemnum_compound_#1_#2_properties_prop} { \prop_new:c {g__chemnum_compound_#1_#2_properties_prop} } \seq_if_exist:cF {g__chemnum_compound_#1_subcompounds_seq} { \seq_new:c {g__chemnum_compound_#1_subcompounds_seq} } \seq_if_in:cnF {g__chemnum_compound_#1_subcompounds_seq} {#2} { \seq_gput_right:cn {g__chemnum_compound_#1_subcompounds_seq} {#2} } \prop_gput:cnn {g__chemnum_compound_#1_#2_properties_prop} {previous-number} {#3} \prop_gput:cnn {g__chemnum_compound_#1_#2_properties_prop} {previous-counter-representation} {#4} } % ---------------------------------------------------------------------------- % declaring and writing compounds: % #1: options % #2: ID \cs_new_protected:Npn \chemnum_declare_compound:nn #1#2 { \tl_if_blank:nF {#1} { \keys_set_groups:nnn {chemnum} {compound} { local=true , #1 } } \chemnum_compound_if_initiated:nF {#2} { \bool_if:NT \g__chemnum_initiate_bool { \bool_if:NTF \g__chemnum_initiate_strict_bool { \msg_error:nnn {chemnum} {compound-not-initiated} {#2} } { \msg_warning:nnn {chemnum} {compound-not-initiated} {#2} } } \bool_if:NT \l__chemnum_show_def_bool { \cmpdshowdef {#2} } \bool_set_false:N \l__chemnum_show_ref_bool \chemnum_initiate_compound:n {#2} } \chemnum_compound_if_defined:nTF {#2} { \chemnum_set_compound:n {#2} } { \chemnum_define_compound:n {#2} \chemnum_finalize_compound:n {#2} } } % #1: options % #2: main ID % #3: sub ID \cs_new_protected:Npn \chemnum_declare_subcompound:nnn #1#2#3 { \chemnum_subcompound_if_initiated:nnF {#2} {#3} { \bool_if:NT \g__chemnum_initiate_sub_bool { \bool_if:NTF \g__chemnum_initiate_strict_bool { \msg_error:nnnn {chemnum} {subcompound-not-initiated} {#2} {#3} } { \msg_warning:nnnn {chemnum} {subcompound-not-initiated} {#2} {#3} } } \bool_if:NT \l__chemnum_show_def_bool { \subcmpdshowdef {#2} {#3} } \bool_set_false:N \l__chemnum_show_ref_bool \chemnum_initiate_subcompound:nn {#2} {#3} } \chemnum_subcompound_if_defined:nnF {#2} {#3} { \chemnum_define_subcompound:nn {#2} {#3} \chemnum_finalize_subcompound:nn {#2} {#3} } } \cs_new_protected:Npn \chemnum_compound_start:n #1 { \bool_if:NF \l__chemnum_sub_only_bool { \chemnum_get_compound_property:nn {#1} {pre-label-code} } } \cs_new:Npn \chemnum_expandable_compound_start:n #1 { \bool_if:NF \l__chemnum_sub_only_bool { \chemnum_expandable_get_compound_property:nn {#1} {previous-pre-label-code} } } \cs_new_protected:Npn \chemnum_compound_finish:n #1 { \bool_if:NF \l__chemnum_sub_only_bool { \chemnum_get_compound_property:nn {#1} {post-label-code} } } \cs_new:Npn \chemnum_expandable_compound_finish:n #1 { \bool_if:NF \l__chemnum_sub_only_bool { \chemnum_expandable_get_compound_property:nn {#1} {previous-post-label-code} } } % actively write a compound: % #1: ID \cs_new_protected:Npn \chemnum_compound_write:n #1 { \chemnum_get_compound_property:nn {#1} {pre-main-label-code} \group_begin: \bool_if:NTF \l__chemnum_compound_local_bool { \l__chemnum_local_label_format_tl } { \chemnum_get_compound_property:nn {#1} {label-format} } { \chemnum_get_compound_property:nn {#1} {counter-representation} } \group_end: \chemnum_get_compound_property:nn {#1} {post-main-label-code} } % actively write a subcompound: % #1: main ID % #2: sub ID \cs_new_protected:Npn \chemnum_subcompound_write:nn #1#2 { \group_begin: \bool_if:NTF \l__chemnum_compound_local_bool { \l__chemnum_local_label_format_tl } { \chemnum_get_compound_property:nn {#1} {label-format} } { \chemnum_get_subcompound_property:nnn {#1} {#2} {counter-representation} } \group_end: } % this is only provided for use in PDF strings: \cs_new:Npn \chemnum_expandable_compound_write:n #1 { \chemnum_expandable_get_compound_property:nn {#1} {pre-main-label-code} \chemnum_expandable_get_compound_property:nn {#1} {counter-representation} \chemnum_expandable_get_compound_property:nn {#1} {post-main-label-code} } \cs_new:Npn \chemnum_expandable_subcompound_write:nn #1#2 { \chemnum_expandable_get_subcompound_property:nnn {#1} {#2} {counter-representation} } % read and write saved values: % #1: ID \cs_new_protected:Npn \chemnum_compound_read:n #1 { \chemnum_get_compound_property:nn {#1} {previous-pre-main-label-code} \group_begin: \chemnum_get_compound_property:nn {#1} {previous-label-format} { \chemnum_get_compound_property_or:nnn {#1} {previous-counter-representation} { \__chemnum_nothing_here:n {#1} \__chemnum_rerun: } } \group_end: \chemnum_get_compound_property:nn {#1} {previous-post-main-label-code} } % #1: main ID % #2: sub ID \cs_new_protected:Npn \chemnum_subcompound_read:nn #1#2 { \group_begin: \bool_if:NTF \l__chemnum_compound_local_bool { \l__chemnum_local_label_format_tl } { \chemnum_get_compound_property:nn {#1} {previous-label-format} } { \chemnum_get_subcompound_property_or:nnnn {#1} {#2} {previous-counter-representation} { \__chemnum_nothing_here:nn {#2} {#1} \__chemnum_rerun: } } \group_end: } % this is only provided for use in PDF strings: \cs_new:Npn \chemnum_expandable_compound_read:n #1 { \chemnum_expandable_get_compound_property:nn {#1} {previous-pre-main-label-code} \chemnum_expandable_get_compound_property:nn {#1} {previous-counter-representation} \chemnum_expandable_get_compound_property:nn {#1} {previous-post-main-label-code} } \cs_new:Npn \chemnum_expandable_subcompound_read:nn #1#2 { \chemnum_expandable_get_subcompound_property:nnn {#1} {#2} {previous-counter-representation} } % #1: boolean: if true register compound but don't write the label % #2: boolean: if true only read compound % #3: write == true and read == false % #4: write == true and read == true \cs_new:Npn \chemnum_if_write_and_or_read:NNTF #1#2 { \bool_if:NTF #1 { \use_none:nn } { \bool_if:NTF #2 { \use_ii:nn } { \use_i:nn } } } % write a label from the entries of \cmpd: % #1: boolean: if true register compound but don't write the label % #2: boolean: if true only read compound % #3: options % #4: label specifications \cs_new_protected:Npn \chemnum_single_compound:NNnn #1#2#3#4 { \bool_if:NT #1 { \@bsphack } \group_begin: \chemnum_split_sub_from_main:VNNnn \l_chemnum_compound_separator_tl #1 #2 {#3} {#4} \group_end: \bool_if:NT {#1} { \@esphack } } % #1: label separator % #2: boolean: if true register compound but don't write the label % #3: boolean: if true only read compound % #4: options % #5: label spec \cs_new_protected:Npn \chemnum_split_sub_from_main:nNNnn #1#2#3#4#5 { \cs_set:Npn \__chemnum_split_sub_from_main_aux:nnnw ##1##2##3##4#1##5#1##6 \q_stop { \bool_if:NF ##2 { \chemnum_declare_compound:nn {##3} {##4} } \keys_set_groups:nnn {chemnum} {sub-only} {#4} \chemnum_if_write_and_or_read:NNTF #2 #3 { \chemnum_compound_start:n {##4} } { \chemnum_expandable_compound_start:n {##4} } \chemnum_write_main:nnnn {##1} {##2} {##3} {##4} \bool_lazy_and:nnT { !\l__chemnum_sub_all_bool } { !\tl_if_blank_p:n {##5} } { \chemnum_write_sublist:NNnnn ##1 ##2 {##3} {##4} {##5} } \bool_if:NT \l__chemnum_sub_all_bool { \tl_clear:N \l__chemnum_tmpa_tl \tl_set:Nx \l__chemnum_tmpa_tl { \seq_use:cn {g__chemnum_compound_##4_subcompounds_seq} {,} } \tl_if_blank:VF \l__chemnum_tmpa_tl { \chemnum_write_sublist:NNnnV ##1 ##2 {##3} {##4} \l__chemnum_tmpa_tl } } \chemnum_if_write_and_or_read:NNTF #2 #3 { \chemnum_compound_finish:n {##4} } { \chemnum_expandable_compound_finish:n {##4} } } \__chemnum_split_sub_from_main_aux:nnnw {#2} {#3} {#4} #5#1#1 \q_stop } \cs_generate_variant:Nn \chemnum_split_sub_from_main:nNNnn {V} \cs_new:Npn \__chemnum_split_sub_from_main_aux:nnnw #1#2#3#4.#5.#6 \q_stop {} % \chemnum_write_main:nnnn will write the main label, either with saved % values (+ variant, boolean #2=true), or only register it (* variant, boolean % #1=true) % % #1: boolean: if true register compound but don't write the label % #2: boolean: if true only read compound % #3: options % #4: label spec \cs_new_protected:Npn \chemnum_write_main:nnnn #1#2#3#4 { \bool_if:NTF #2 { \bool_if:NF \l__chemnum_sub_only_bool { \chemnum_hyper_link:nn {#4} { \chemnum_compound_read:n {#4} } } \bool_if:NT #1 { \msg_error:nn {chemnum} {erroneous-argument-combination} } } { \bool_if:NT \l__chemnum_show_ref_bool { \cmpdshowref {#4} } \bool_lazy_or:nnF { \l__chemnum_sub_only_bool } {#1} { \chemnum_if_compound_used:nTF {#4} { \chemnum_hyper_link:nn {#4} } { \chemnum_use_compound:n {#4} \chemnum_hyper_target:nn {#4} } { \chemnum_compound_write:n {#4} } } } } % ---------------------------------------------------------------------------- % use this for determining wether we need a hyperlink or hypertarget: \seq_new:N \g__chemnum_used_compounds_seq \prg_new_conditional:Npnn \chemnum_if_compound_used:n #1 {p,T,F,TF} { \seq_if_in:NnTF \g__chemnum_used_compounds_seq {#1} { \prg_return_true: } { \prg_return_false: } } \cs_new_protected:Npn \chemnum_use_compound:n #1 { \seq_gput_right:Nn \g__chemnum_used_compounds_seq {#1} } % ---------------------------------------------------------------------------- % hyperlinks: \cs_new_eq:NN \chemnum_hyper_target:nn \use_ii:nn \cs_new_eq:NN \chemnum_hyper_link:nn \use_ii:nn \AtBeginDocument { % TODO: add boolean which allows en- and disabling the mechanism; disable % it per default \@ifpackageloaded {hyperref} { \bool_if:NT \l__chemnum_hyperlinks_bool { \cs_set_eq:NN \chemnum_hyper_link:nn \hyperlink \cs_set:Npn \chemnum_hyper_target:nn #1#2 { \raisebox {3ex} [0pt] { \hypertarget {#1} {} } #2 } } } {} } % ---------------------------------------------------------------------------- \cs_new_protected:Npn \chemnum_print_label_id:n #1 { \group_begin: \str_set:Nn \l__chemnum_tmpa_str {#1} \str_use:N \l__chemnum_tmpa_str \group_end: } \cs_new_protected:Npn \chemnum_show_label_margin:n #1 { \marginpar { \fbox {#1} } } \cs_new_protected:Npn \chemnum_show_label_inline:n #1 { \group_begin: \hbox_unpack:N \c_empty_box % this is \leavevmode \vbox_to_zero:n { \tex_vss:D \hbox_overlap_right:n { \tex_vrule:D \tex_raise:D .75em \hbox:n { \underbar {#1} } } } \group_end: } \NewDocumentCommand \cmpdprintlabelid {m} { \chemnum_print_label_id:n {#1} } \NewDocumentCommand \cmpdshowlabelmargin {m} { \chemnum_show_label_margin:n {#1} } \NewDocumentCommand \cmpdshowlabelinline {m} { \chemnum_show_label_inline:n {#1} } \NewDocumentCommand \chemnumshowdef {m} { \cmpdshowlabelmargin { \normalfont \ttfamily \cmpdprintlabelid {#1} } } \NewDocumentCommand \chemnumshowref {m} { \cmpdshowlabelinline { \normalfont \ttfamily \footnotesize \cmpdprintlabelid {#1} } } \NewDocumentCommand \cmpdshowdef {m} { \chemnumshowdef {#1} } \NewDocumentCommand \cmpdshowref {m} { \chemnumshowref {#1} } \NewDocumentCommand \subcmpdshowdef {mm} { \chemnumshowdef {#2~(#1)} } \NewDocumentCommand \subcmpdshowref {mm} { \chemnumshowref {#2} } % ---------------------------------------------------------------------------- % #1: boolean: if true register compound but don't write the label % #2: boolean: if true only read compound % #3: options % #4: main label id % #5: sublabel list \cs_new_protected:Npn \chemnum_write_sublist:NNnnn #1#2#3#4#5 { \seq_set_split:NVn \l__chemnum_tmpc_seq \l__chemnum_sub_separator_tl {#5} \seq_remove_duplicates:N \l__chemnum_tmpc_seq \seq_map_inline:Nn \l__chemnum_tmpc_seq { \bool_if:NF #2 { \chemnum_declare_subcompound:nnn {#3} {#4} {##1} } } \seq_clear:N \l__chemnum_tmpd_seq % puts the subcompounds ready to be printed in \l__chemnum_tmpd_seq : \chemnum_sort_subcompounds:NNNnnNN #1#2 \l__chemnum_tmpc_seq {#3} {#4} \l__chemnum_tmpd_seq % to write the uncompressed list \l__chemnum_tmpe_seq % for compressing the list, holds the numbers \bool_lazy_and:nnTF { \l__chemnum_compress_subcompounds_bool } { \int_compare_p:n { \seq_count:N \l__chemnum_tmpe_seq > 2 } } { % needs a seq with the associated /numbers/! \chemnum_compress_subcompounds:NNN \l__chemnum_tmpd_seq % holds the IDs \l__chemnum_tmpe_seq % holds the numbers \l__chemnum_tmpc_seq % the new sequence \seq_use:Nn \l__chemnum_tmpc_seq {} } { \seq_use:NVVV \l__chemnum_tmpd_seq \l__chemnum_sep_sublist_two_tl \l__chemnum_sep_sublist_more_tl \l__chemnum_sep_sublist_last_two_tl } } \cs_generate_variant:Nn \chemnum_write_sublist:NNnnn {NNnnV} % #1: boolean: if true register compound but don't write the label % #2: boolean: if true only read compound % #3: options % #4: main ID % #5: sub ID \cs_new_protected:Npn \chemnum_write_subcompound:NNnnn #1#2#3#4#5 { \bool_if:NTF #2 { \chemnum_subcompound_read:nn {#4} {#5} } { \chemnum_declare_subcompound:nnn {#3} {#4} {#5} \bool_if:NT \l__chemnum_show_ref_bool { \subcmpdshowref {#4} {#5} } \bool_if:NF #1 { \chemnum_subcompound_write:nn {#4} {#5} } } } \cs_generate_variant:Nn \chemnum_write_subcompound:NNnnn {NNnnV} %%% The following command sorts the sequence according to the order in which %%% they've been declared % #1: boolean: if true register compound but don't write the label % #2: boolean: if true only read compound % #3: sub ID sequence % #4: options % #5: main ID % #6: seq variable % #7: seq variable \cs_new_protected:Npn \chemnum_sort_subcompounds:NNNnnNN #1#2#3#4#5#6#7 { \seq_clear:N #6 \seq_clear:N #7 \bool_if:NF #1 { \seq_if_exist:cTF {g__chemnum_compound_#5_subcompounds_seq} { \seq_map_inline:Nn #3 { \seq_if_in:cnTF {g__chemnum_compound_#5_subcompounds_seq} {##1} { \seq_put_right:Nn #6 { \chemnum_write_subcompound:NNnnn #1 #2 {#4} {#5} {##1} } \bool_if:NTF #2 { \seq_put_right:Nx #7 { \chemnum_expandable_get_subcompound_property:nnn {#5} {##1} {previous-number} } } { \seq_put_right:Nx #7 { \chemnum_expandable_get_subcompound_property:nnn {#5} {##1} {number} } } } { \__chemnum_nothing_here:nn {##1} {#5} } } } { \__chemnum_nothing_here:xn { \seq_use:Nnnn #3 {,~} {,~} {,~} } {#5} } } \seq_remove_all:Nn #7 {} } % #1: sub ID sequence % #2: sub ID sequence that holds the numbers rather than the IDs % #3: seq variable \cs_new_protected:Npn \chemnum_compress_subcompounds:NNN #1#2#3 { \int_zero:N \l__chemnum_tmpa_int \int_zero:N \l__chemnum_tmpb_int \seq_clear:N \l__chemnum_tmpa_seq \seq_clear:N #3 \seq_map_inline:Nn #2 { \int_incr:N \l__chemnum_tmpa_int \int_compare:nTF { \l__chemnum_tmpa_int = 1 } { \seq_put_right:Nn \l__chemnum_tmpa_seq {1} } { \seq_put_right:Nx \l__chemnum_tmpa_seq { \int_eval:n { ##1 - \l__chemnum_tmpb_int } } } \int_set:Nn \l__chemnum_tmpb_int {##1} } \int_zero:N \l__chemnum_tmpa_int \int_set:Nn \l__chemnum_tmpb_int { \seq_count:N #2 } \int_zero:N \l__chemnum_tmpc_int \seq_map_inline:Nn \l__chemnum_tmpa_seq { \int_incr:N \l__chemnum_tmpa_int \int_compare:nTF { \l__chemnum_tmpa_int = 1 } { \int_add:Nn \l__chemnum_tmpc_int {##1} \seq_put_right:Nx #3 { \seq_item:Nn #1 {1} } } { \int_compare:nTF { ##1 = 1 } { \int_add:Nn \l__chemnum_tmpc_int {##1} } { \int_compare:nTF { \l__chemnum_tmpc_int > 2 } { \seq_put_right:NV #3 \l__chemnum_sep_sublist_range_tl \seq_put_right:Nx #3 { \seq_item:Nn #1 { \l__chemnum_tmpa_int - 1 } } \seq_put_right:NV #3 \l__chemnum_sep_sublist_two_tl \seq_put_right:Nx #3 { \seq_item:Nn #1 { \l__chemnum_tmpa_int } } } { \seq_get_right:NN #3 \l__chemnum_tmpa_tl \tl_if_eq:VxF \l__chemnum_tmpa_tl { \seq_item:Nn #1 { \l__chemnum_tmpa_int - 1 } } { \seq_put_right:NV #3 \l__chemnum_sep_sublist_two_tl \seq_put_right:Nx #3 { \seq_item:Nn #1 { \l__chemnum_tmpa_int - 1 } } } \seq_put_right:NV #3 \l__chemnum_sep_sublist_two_tl \seq_put_right:Nx #3 { \seq_item:Nn #1 { \l__chemnum_tmpa_int } } } \int_set:Nn \l__chemnum_tmpc_int { 1 } } \int_compare:nT { \l__chemnum_tmpa_int = \l__chemnum_tmpb_int } { \seq_get_right:NN #3 \l__chemnum_tmpa_tl \tl_if_eq:VxF \l__chemnum_tmpa_tl { \seq_item:Nn #1 { \l__chemnum_tmpa_int } } { \int_compare:nTF { \l__chemnum_tmpc_int > 2 } { \seq_put_right:NV #3 \l__chemnum_sep_sublist_range_tl } { \seq_put_right:NV #3 \l__chemnum_sep_sublist_last_two_tl } \seq_put_right:Nx #3 { \seq_item:Nn #1 { \l__chemnum_tmpa_int } } } } } } } % ---------------------------------------------------------------------------- % the code level version of the main command: % #1: boolean: if true register compound but don't write the label % #2: boolean: if true only read compound % #3: options % #4: list of IDs \cs_new_protected:Npn \chemnum_cmpd:nnnn #1#2#3#4 { \group_begin: \keys_set_groups:nnn {chemnum} {list} {#3} \seq_set_split:NVn \l__chemnum_tmpa_seq \l__chemnum_main_separator_tl {#4} \seq_remove_duplicates:N \l__chemnum_tmpa_seq \chemnum_sort_main_labels:N \l__chemnum_tmpa_seq \seq_clear:N \l__chemnum_tmpb_seq \seq_map_inline:Nn \l__chemnum_tmpa_seq { \seq_put_right:Nn \l__chemnum_tmpb_seq { \chemnum_single_compound:NNnn #1 #2 {#3} {##1} } } \bool_if:NTF #1 % starred call of \cmpd { \seq_use:Nn \l__chemnum_tmpb_seq {} } { \seq_use:NVVV \l__chemnum_tmpb_seq \l__chemnum_sep_list_two_tl \l__chemnum_sep_list_more_tl \l__chemnum_sep_list_last_two_tl } \group_end: } % #1: first variable % #2: second variable % #3: main/sub separator % #4: complete label \cs_new_protected:Npn \chemnum_separate_main_sub:NNnn #1#2#3#4 { \cs_set:Npn \__chemnum_remove_sub:w ##1#3##2 \q_stop { \exp_not:n {##1} } \cs_set:Npn \__chemnum_get_sub:w ##1#3##2#3##3 \q_stop { \tl_if_blank:nF {##2} { \exp_not:n {##2} } } \tl_set:Nx #1 { \__chemnum_remove_sub:w #4#3 \q_stop } \tl_set:Nx #2 { \__chemnum_get_sub:w #4#3#3 \q_stop } } \cs_generate_variant:Nn \chemnum_separate_main_sub:NNnn {NNV} % sorting and merging of the main label list: % #1: seq that holds the label list \cs_new_protected:Npn \chemnum_sort_main_labels:N #1 { \prop_clear:N \l__chemnum_tmpa_prop \seq_clear:N \l__chemnum_tmpb_seq \seq_clear:N \l__chemnum_tmpc_seq % build property list that holds entries of #1: \seq_map_inline:Nn #1 { \chemnum_separate_main_sub:NNVn \l__chemnum_tmpa_tl % main part \l__chemnum_tmpb_tl % sub part \l_chemnum_compound_separator_tl {##1} \bool_if:NTF \l__chemnum_merge_list_bool { \prop_get:NVNTF \l__chemnum_tmpa_prop \l__chemnum_tmpa_tl \l__chemnum_tmpc_tl { \prop_put:NVx \l__chemnum_tmpa_prop \l__chemnum_tmpa_tl { \exp_not:V \l__chemnum_tmpc_tl \exp_not:V \l__chemnum_sub_separator_tl \exp_not:V \l__chemnum_tmpb_tl } } { \prop_put:NVV \l__chemnum_tmpa_prop \l__chemnum_tmpa_tl \l__chemnum_tmpb_tl } } { \prop_get:NVNTF \l__chemnum_tmpa_prop \l__chemnum_tmpa_tl \l__chemnum_tmpc_tl { \prop_put:NVx \l__chemnum_tmpa_prop \l__chemnum_tmpa_tl { \exp_not:V \l__chemnum_tmpc_tl \exp_not:V \l__chemnum_main_separator_tl \exp_not:n {##1} } } { \prop_put:NVn \l__chemnum_tmpa_prop \l__chemnum_tmpa_tl {##1} } } } % merge = true: % \l__chemnum_tmpa_prop now holds all main labels with possible sublabel % lists % merge = false % \l__chemnum_tmpa_prop now holds all main labels with all occurences of % the respective main label as property % % build sequence that holds entries of #1 in order of already defined % labels: \seq_map_inline:Nn \g__chemnum_defined_compounds_seq { \bool_if:NTF \l__chemnum_merge_list_bool { \prop_get:NnNT \l__chemnum_tmpa_prop {##1} \l__chemnum_tmpa_tl { \tl_if_in:VVTF \l__chemnum_tmpa_tl \l__chemnum_sub_separator_tl { \seq_put_right:Nx \l__chemnum_tmpb_seq { \exp_not:n {##1} \tl_if_blank:VF \l__chemnum_tmpa_tl { \exp_not:V \l_chemnum_compound_separator_tl { \exp_not:V \l__chemnum_tmpa_tl } } } } { \seq_put_right:Nx \l__chemnum_tmpb_seq { \exp_not:n {##1} \tl_if_blank:VF \l__chemnum_tmpa_tl { \exp_not:V \l_chemnum_compound_separator_tl \exp_not:V \l__chemnum_tmpa_tl } } } \seq_if_in:NnF \l__chemnum_tmpc_seq {##1} { \seq_put_right:Nn \l__chemnum_tmpc_seq {##1} } } } { \prop_get:NnNT \l__chemnum_tmpa_prop {##1} \l__chemnum_tmpa_tl { \tl_if_in:VVTF \l__chemnum_tmpa_tl \l__chemnum_main_separator_tl { \seq_set_split:NVV \l__chemnum_tmpc_seq \l__chemnum_main_separator_tl \l__chemnum_tmpa_tl \seq_map_inline:Nn \l__chemnum_tmpc_seq { \seq_put_right:Nn \l__chemnum_tmpb_seq {####1} } } { \seq_put_right:NV \l__chemnum_tmpb_seq \l__chemnum_tmpa_tl } } } } % \l__chemnum_tmpb_seq now holds all labels that are already defined % merge = true : % the same \l__chemnum_tmpc_seq which only holds the /main/ labels \bool_if:NTF \l__chemnum_merge_list_bool { \seq_map_inline:Nn #1 { \chemnum_separate_main_sub:NNVn \l__chemnum_tmpa_tl % main part \l__chemnum_tmpb_tl % sub part \l_chemnum_compound_separator_tl {##1} % check if existing main label is present, otherwise add entry \seq_if_in:NVF \l__chemnum_tmpc_seq \l__chemnum_tmpa_tl { \prop_get:NVNT \l__chemnum_tmpa_prop \l__chemnum_tmpa_tl \l__chemnum_tmpc_tl { \seq_put_right:Nx \l__chemnum_tmpb_seq { \exp_not:V \l__chemnum_tmpa_tl \tl_if_blank:VF \l__chemnum_tmpc_tl { \exp_not:V \l_chemnum_compound_separator_tl \exp_not:V \l__chemnum_tmpc_tl } } \seq_put_right:NV \l__chemnum_tmpc_seq \l__chemnum_tmpa_tl } } } } { \seq_map_inline:Nn #1 { \seq_if_in:NnF \l__chemnum_tmpb_seq {##1} { \seq_put_right:Nn \l__chemnum_tmpb_seq {##1} } } } \seq_set_eq:NN #1 \l__chemnum_tmpb_seq } % %-----------------------------------------------------------------------------% % % REPLACE TAG IN EPS PICTURE WITH LABEL % % works similar to \schemeref command of the chemscheme package % % \cmpdref-[][]{