% -------------------------------------------------------------------------- % % the CHEMMACROS package -- module: `base' % % -------------------------------------------------------------------------- % Clemens Niederberger % -------------------------------------------------------------------------- % https://github.org/cgnieder/chemmacros/ % contact@mychemistry.eu % -------------------------------------------------------------------------- % If you have any ideas, questions, suggestions or bugs to report, please % feel free to contact me. % -------------------------------------------------------------------------- % Copyright 2011--2020 Clemens Niederberger % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % 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.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Clemens Niederberger. % -------------------------------------------------------------------------- \ChemModule{base}{2020/02/02 basic chemmacros module} % for the document hooks \ChemCompatibilityFrom{5.1} \RequirePackage {etoolbox} \EndChemCompatibility % -------------------------------------------------------------------------- \msg_new:nnn {chemmacros} {command-deprecated} { The~ command~ \token_to_str:N #1 \c_space_tl is~ deprecated.~ Use~ \token_to_str:N #2 \c_space_tl instead. } % define a deprecated command with hints to the corresponding new one: \cs_new_protected:Npn \chemmacros_define_deprecated:NN #1#2 { \cs_set_protected:Npn #1 { \msg_warning:nnnn {chemmacros} {command-deprecated} {#1} {#2} #2 } } \NewDocumentCommand \DeclareChemDeprecated {mm} { \chemmacros_define_deprecated:NN #1 #2 } % -------------------------------------------------------------------------- % define a macro set: % \NewChem... \RenewChem... \DeclareChem... \ProvideChem... % #1: macro names % #2: arg spec % #3: internal command call \cs_new_protected:Npn \chemmacros_new_macroset:nnn #1#2#3 { \exp_args:Nc \NewDocumentCommand { NewChem \str_uppercase:f { \tl_head:n {#1} } \tl_tail:n {#1} } {#2} { \cs_if_free:NTF ##1 { #3 } { \msg_error:nnn {chemmacros} {new-#1} {##1} } } \exp_args:Nc \NewDocumentCommand { RenewChem \str_uppercase:f { \tl_head:n {#1} } \tl_tail:n {#1} } {#2} { \cs_if_free:NTF ##1 { \msg_error:nnn {chemmacros} {renew-#1} {##1} } { #3 } } \exp_args:Nc \NewDocumentCommand { DeclareChem \str_uppercase:f { \tl_head:n {#1} } \tl_tail:n {#1} } {#2} {#3} \exp_args:Nc \NewDocumentCommand { ProvideChem \str_uppercase:f { \tl_head:n {#1} } \tl_tail:n {#1} } {#2} { \cs_if_free:NT ##1 { #3 } } \msg_new:nnn {chemmacros} {new-#1} { You've~ tried~ to~ define~ a~ #1~ with~ \token_to_str:N \NewChem #1 ,~ but~ the~ command~ sequence~ \token_to_str:N ##1 \c_space_tl already~ exists.~ Please~ choose~ another~ name. } \msg_new:nnn {chemmacros} {renew-#1} { You've~ tried~ to~ renew~ the~ #1~ \token_to_str:N ##1 ,~ but~ it~ doesn't~ exist. } } \cs_new_protected:Npn \chemmacros_new_environment_macroset:nnn #1#2#3 { \exp_args:Nc \NewDocumentCommand {NewChem#1} {#2} { \bool_lazy_and:nnTF { \cs_if_free_p:c {##1} } { \cs_if_free_p:c {end##1} } {#3} { \msg_error:nnn {chemmacros} {new-#1} {##1} } } \exp_args:Nc \NewDocumentCommand {RenewChem#1} {#2} { \bool_lazy_or:nnTF { \cs_if_free_p:c {##1} } { \cs_if_free_p:c {end##1} } { \msg_error:nnn {chemmacros} {renew-#1} {##1} } {#3} } \exp_args:Nc \NewDocumentCommand {DeclareChem#1} {#2} {#3} \exp_args:Nc \NewDocumentCommand {ProvideChem#1} {#2} { \bool_lazy_and:nT { \cs_if_free_p:c {##1} } { \cs_if_free_p:c {end##1} } {#3} } \msg_new:nnn {chemmacros} {new-#1} { You've~ tried~ to~ define~ a~ #1~ with~ \token_to_str:N \NewChem #1 ,~ but~ the~ command~ sequence~ \exp_not:c {##1} \c_space_tl already~ exists.~ Please~ choose~ another~ name. } \msg_new:nnn {chemmacros} {renew-#1} { You've~ tried~ to~ renew~ the~ #1~ ##1,~ but~ it~ doesn't~ exist. } } \NewDocumentCommand \NewChemMacroset {smmm} { \IfBooleanTF {#1} { \chemmacros_new_environment_macroset:nnn {#2} {#3} {#4} } { \chemmacros_new_macroset:nnn {#2} {#3} {#4} } } % -------------------------------------------------------------------------- \cs_new_protected:Npn \chemmacros_define_keys:nn #1#2 { \keys_define:nn {chemmacros/#1} {#2} } \cs_generate_variant:Nn \chemmacros_define_keys:nn {x} \cs_new_protected:Npn \chemmacros_set_keys:nn #1#2 { \keys_set:nn {chemmacros/#1} {#2} } \cs_generate_variant:Nn \chemmacros_set_keys:nn {x,nx} \cs_new_protected:Npn \chemmacros_set_keys_groups:nnn #1#2#3 { \keys_set_groups:nnn {chemmacros/#1} {#2} {#3} } \cs_new_protected:Npn \chemmacros_set_keys_filter:nnn #1#2#3 { \keys_set_filter:nnn {chemmacros/#1} {#2} {#3} } \cs_new_protected:Npn \chemmacros_define_global_keys:n #1 { \keys_define:nn {chemmacros} {#1} } \cs_new_protected:Npn \chemmacros_set_global_keys:n #1 { \keys_set:nn {chemmacros} {#1} } % -------------------------------------------------------------------------- % basic tools: \cs_new:Npn \chemmacros_remove_backslash:N #1 { \exp_after:wN \use_none:n \token_to_str:N #1 } \cs_new_eq:NN \chemmacros_ignore_spaces: \tex_ignorespaces:D \cs_new_protected:Npn \chemmacros_nobreak: { \tex_penalty:D 10000 \scan_stop: } \cs_new_protected:Npn \chemmacros_allow_break: { \tex_penalty:D \c_zero_int } \cs_new_protected:Npn \chemmacros_skip_nobreak:N #1 { \chemmacros_nobreak: \skip_horizontal:N #1 \chemmacros_nobreak: } % this is used at least in the `isotope' module \prg_new_conditional:Npnn \chemmacros_if_is_int:n #1 {p,T,F,TF} { \if_charcode:w ! \if_int_compare:w 9 < 1#1 ! \else: _ \fi: \prg_return_true: \else: \prg_return_false: \fi: } \prg_new_conditional:Npnn \chemmacros_if_loaded:nn #1#2 {p,T,F,TF} { \use:c {chemmacros_if_#1_loaded:nTF} {#2} { \prg_return_true: } { \prg_return_false: } } \prg_new_conditional:Npnn \chemmacros_if_package_loaded:n #1 {p,T,F,TF} { \cs_if_exist:cTF {ver@#1.sty} { \prg_return_true: } { \prg_return_false: } } \prg_new_conditional:Npnn \chemmacros_if_class_loaded:n #1 {p,T,F,TF} { \cs_if_exist:cTF {ver@#1.cls} { \prg_return_true: } { \prg_return_false: } } \ChemCompatibilityFrom{5.2} % this is still true \AtBeginDocument: \prg_new_conditional:Npnn \chemmacros_if_preamble: {p,T,F,TF} { \cs_if_eq:NNTF \@onlypreamble \@notprerr { \prg_return_false: } { \prg_return_true: } } % this is still false \AtBeginDocument: \prg_new_conditional:Npnn \chemmacros_if_document: {p,T,F,TF} { \bool_if:NTF \l__chemmacros_in_document_bool { \prg_return_true: } { \prg_return_false: } } \EndChemCompatibility \ChemCompatibilityFrom{5.6} \cs_new_protected:Npn \chemmacros_cs_if_free_new:Npn #1 { \cs_if_exist:NF #1 { \cs_new:Npn #1 } } \cs_generate_variant:Nn \chemmacros_cs_if_free_new:Npn {c} \cs_new_protected:Npn \chemmacros_cs_if_free_new_protected:Npn #1 { \cs_if_exist:NF #1 { \cs_new_protected:Npn #1 } } \cs_generate_variant:Nn \chemmacros_cs_if_free_new_protected:Npn {c} \RequirePackage{scrlfile} % #1: counter % #2: singular % #3: plural % #4: Singular % #5: Plural \cs_new_protected:Npn \chemmacros_add_cleveref_support:nnnnn #1#2#3#4#5 { \AfterPackage* {cleveref} { \cs_if_exist:cF {cref@#1@name} { \legacy_if:nTF {@cref@capitalise} { \crefname {#1} {#4} {#5} } { \crefname {#1} {#2} {#3} } \Crefname {#1} {#4} {#5} } } } \cs_generate_variant:Nn \chemmacros_add_cleveref_support:nnnnn {nnnx , nnnxx , nnnnx } % #1: counter % #2: singular % #3: Singular (optional) % #4: plural % #5: Plural (optional) \NewDocumentCommand \ChemCleverefSupport {mmomo} { \IfNoValueTF {#3} { \IfNoValueTF {#5} { \chemmacros_add_cleveref_support:nnnnn {#1} {#2} {#4} { \tl_mixed_case:n {#2} } { \tl_mixed_case:n {#4} } } { \chemmacros_add_cleveref_support:nnnnn {#1} {#2} {#4} { \tl_mixed_case:n {#2} } {#5} } } { \IfNoValueTF {#5} { \chemmacros_add_cleveref_support:nnnnn {#1} {#2} {#4} {#3} { \tl_mixed_case:n {#4} } } { \chemmacros_add_cleveref_support:nnnnn {#1} {#2} {#4} {#3} {#5} } } } \@onlypreamble\ChemCleverefSupport % #1: id % #2: mid sentence % #3: begin sentence \cs_new_protected:Npn \chemmacros_add_fancyref_support:nnn #1#2#3 { \AfterPackage* {fancyref} { \chemmacros_cs_if_free_new:cpn {fancyref#1labelprefix} {#1} \chemmacros_cs_if_free_new:cpn {fref#1name} {#2} \chemmacros_cs_if_free_new:cpn {Fref#1name} {#3} \exp_args:Nnx \frefformat {vario} { \exp_not:c {fancyref#1labelprefix} } { \use:c {fref#1name} \fancyrefdefaultspacing ##1##3 } \exp_args:Nnx \Frefformat {vario} { \exp_not:c {fancyref#1labelprefix} } { \use:c {Fref#1name} \fancyrefdefaultspacing ##1##3 } \exp_args:Nnx \frefformat {plain} { \exp_not:c {fancyref#1labelprefix} } { \use:c {fref#1name} \fancyrefdefaultspacing ##1 } \exp_args:Nnx \Frefformat {plain} { \exp_not:c {fancyref#1labelprefix} } { \use:c {Fref#1name} \fancyrefdefaultspacing ##1 } } } \cs_generate_variant:Nn \chemmacros_add_fancyref_support:nnn {nnx} % #1: id % #2: mid sentence % #3: begin sentence (optional) \NewDocumentCommand \ChemFancyrefSupport {mmo} { \IfNoValueTF {#3} { \chemmacros_add_fancyref_support:nnn {#1} {#2} { \tl_mixed_case:n {#3} } } { \chemmacros_add_fancyref_support:nnn {#1} {#2} {#3} } } \@onlypreamble\ChemFancyrefSupport \EndChemCompatibility % -------------------------------------------------------------------------- % some checks at begin document: \bool_new:N \l__chemmacros_in_document_bool \bool_new:N \l__chemmacros_chemstyle_bool \chemmacros_if_compatibility:nnTF {>=} {5.2} { \AfterEndPreamble } { \AtBeginDocument } { \bool_set_true:N \l__chemmacros_in_document_bool } \AtBeginDocument { \@ifpackageloaded { chemstyle } { \bool_set_true:N \l__chemmacros_chemstyle_bool } { \bool_set_false:N \l__chemmacros_chemstyle_bool } } % -------------------------------------------------------------------------- % detection and handling of bold face: \RequirePackage{bm} \prg_new_protected_conditional:Npnn \chemmacros_if_bold: {T,F,TF} { \seq_if_in:NVTF \l__chemmacros_if_bf_seq \f@series { \prg_return_true: } { \prg_return_false: } } \seq_new:N \l__chemmacros_if_bf_seq \seq_set_split:Nnn \l__chemmacros_if_bf_seq { , } { b , bc , bm , bx , bux , eb , ebc , ebx , mb , sb , sbc , sbx , ub , ubc , ubx } \cs_new_protected:Npn \chemmacros_bold:n #1 { \chemmacros_if_bold:TF { \mode_if_math:TF { \bm {#1} } { \textbf {#1} } } {#1} } \cs_new_protected:Npn \chemmacros_detect_bold:n { \error \chemmacros_bold:n } % -------------------------------------------------------------------------- \RequirePackage{amstext} \cs_new_protected:Npn \chemmacros_text:n #1 { \mode_if_math:TF { \text {#1} } {#1} } \cs_generate_variant:Nn \chemmacros_text:n { V } \cs_new_protected:Npn \chemmacros_math:n #1 { \chemmacros_text:n { \c_math_toggle_token #1 \c_math_toggle_token } } \cs_generate_variant:Nn \chemmacros_math:n { V } % -------------------------------------------------------------------------- % a setup command: \NewDocumentCommand \chemsetup {om} { \IfNoValueTF {#1} { \keys_set:nn {chemmacros} {#2} } { \keys_set:nn {chemmacros/#1} {#2} } } \chemmacros_define_global_keys:n { modules .code:n = \chemmacros_load_modules:n {#1} } % -------------------------------------------------------------------------- % load package #1 and add its options to chemmacros % this requires that package #1 defines its options with l3keys using its % name as module \cs_new_protected:Npn \chemmacros_integrate_package:nnn #1#2#3 { \tl_if_blank:nTF {#3} { \tl_if_blank:nTF {#1} { \RequirePackage {#2} } { \RequirePackage [#1] {#2} } } { \tl_if_blank:nTF {#1} { \RequirePackage {#2} [#3] } { \RequirePackage [#1] {#2} [#3] } } \chemmacros_define_global_keys:n { #2 .choice: , #2 / unknown .code:n = \keys_set:no {#2} { \l_keys_key_tl = ##1 } } } % -------------------------------------------------------------------------- \chemmacros_if_compatibility:nnT {>=} {5.2} { \chemmacros_load_module:n {errorcheck} } % -------------------------------------------------------------------------- \bool_new:N \l__chemmacros_hyperref_bool \AtEndPreamble { \chemmacros_if_package_loaded:nT {hyperref} { \bool_set_true:N \l__chemmacros_hyperref_bool } } \file_input_stop: 2015/09/23 - new conditionals \chemmacros_if_preamble:TF and \chemmacros_if_document:TF 2015/10/14 - load `errorcheck' module 2016/02/09 - starred version of \NewChemMacroset 2016/03/07 - \chemmacros_define_keys:nn and friends 2016/04/25 - macros for cleveref and fancyref support, \ChemCleverefSupport \ChemFancyrefSupport 2016/05/04 - fix \ChemCleverefSupport 2017/08/28 - add missing hyperref check 2020/01/16 - adapt to renaming of string case changing functions 2020/02/02 - lazy boolean evaluation