% -------------------------------------------------------------------------- % the CHEMFORMULA package % % typeset chemical compounds and reactions % % -------------------------------------------------------------------------- % Clemens Niederberger % -------------------------------------------------------------------------- % https://github.com/cgnieder/chemformula/ % contact@mychemistry.eu % -------------------------------------------------------------------------- % If you have any ideas, questions, suggestions or bugs to report, please % feel free to contact me. % -------------------------------------------------------------------------- % Copyright 2011--2022 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. % -------------------------------------------------------------------------- \RequirePackage{tikz,amsmath,xfrac,nicefrac} \usetikzlibrary{arrows.meta} \ExplSyntaxOn \tl_const:Nn \c_chemformula_date_tl {2022/01/23} \tl_const:Nn \c_chemformula_version_number_tl {4.17} \tl_const:Nn \c_chemformula_version_suffix_tl {} \tl_const:Nx \c_chemformula_version_tl { \c_chemformula_version_number_tl \c_chemformula_version_suffix_tl } \tl_const:Nn \c_chemformula_info_tl {typeset~ chemical~ compounds~ and~ reactions} \ProvidesExplPackage {chemformula} {\c_chemformula_date_tl} {\c_chemformula_version_tl} {\c_chemformula_info_tl \c_space_tl (CN)} % -------------------------------------------------------------------------- % warning and error messages: \msg_new:nnn {chemformula} {missing-argument} { Maybe~ you've~ forgotten~ to~ add~ the~ second~ argument~ to~ the~ name~ syntax?~ "!()()".\\ Or~ you~ have~ forgotten~ to~ add~ a~ group~ between~ an~ exclamation~ mark~ and~ the~ following~ parenthesis?~ "!~{}()"\\ Either~ way~ --~ I~ don't~ know~ what~ to~ do~ \msg_line_context: . } \msg_new:nnn {chemformula} {new-arrow} { You've~ tried~ to~ define~ the~ arrow~ type~ \tl_to_str:n {#1}~ with~ \token_to_str:N \NewChemArrow \c_space_tl but~ it~ already~ exists.~ Choose~ another~ name. } \msg_new:nnn {chemformula} {renew-arrow} { You've~ tried~ to~ renew~ the~ arrow~ type~ \tl_to_str:n {#1}~ but~ it~ doesn't~ exist. } \msg_new:nnn {chemformula} {unknown-arrow} { The~ arrow~ type~ \tl_to_str:n {#1} ~ doesn't~ exist~ \msg_line_context: . } \msg_new:nnn {chemformula} {new-bond} { You've~ tried~ to~ define~ the~ bond~ type~ \tl_to_str:n {#1}~ with~ \token_to_str:N \NewChemBond \c_space_tl but~ it~ already~ exists.~ Choose~ another~ name. } \msg_new:nnn {chemformula} {renew-bond} { You've~ tried~ to~ renew~ the~ bond~ type~ \tl_to_str:n {#1}~ but~ it~ doesn't~ exist. } \msg_new:nnn {chemformula} {new-compound-property} { You've~ tried~ to~ define~ the~ compound~ property~ `#1'~ with~ \token_to_str:N \NewChemCompoundProperty \c_space_tl but~ a~ property~ `#1'~ already~ exists.~ Choose~ another~ symbol. } \msg_new:nnn {chemformula} {renew-compound-property} { You've~ tried~ to~ redefine~ the~ compound~ property~ `#1'~ with~ \token_to_str:N \RenewChemCompoundProperty \c_space_tl but~ a~ property~ `#1'~ doesn't~ seem~ to~ exist. } \msg_new:nnn {chemformula} {new-addition-symbol} { You've~ tried~ to~ define~ the~ addition~ symbol~ `#1'~ (input~ symbol:~ `#2')~ with~ \token_to_str:N \NewChemAdditionSymbol \c_space_tl but~ a~ symbol~ with~ the~ name~ `#1'~ or~ the~ input~ `#2'~ already~ exists.~ Choose~ another~ name/input. } \msg_new:nnn {chemformula} {renew-addition-symbol} { You've~ tried~ to~ redefine~ the~ addition~ symbol~ `#1'~ (input~ symbol:~ `#2')~ but~ a~ symbol~ with~ the~ name~ `#1'~ or~ input~ `#2' doesn't~ exist. } \msg_new:nnn {chemformula} {new-symbol} { You've~ tried~ to~ define~ the~ symbol~ `#1'~ with~ \token_to_str:N \NewChemSymbol \c_space_tl but~ a~ symbol~ `#1'~ already~ exists.~ Choose~ another~ input. } \msg_new:nnn {chemformula} {renew-symbol} { You've~ tried~ to~ redefine~ the~ symbol~ `#1'~ with~ \token_to_str:N \NewChemSymbol \c_space_tl but~ a~ symbol~ `#1'~ doesn't~ exist. } \msg_new:nnn {chemformula} {deprecated} { On~ line~ \msg_line_number: : \\ The~ #1~ `#2'~ is~ deprecated.~ Use~ #1~ `#3'~ instead . } \msg_new:nnn {chemformula} {deprecated-function} { The~ command~ #1~ is~ deprecated.~ Use~ #2 instead . } \msg_new:nnn {chemformula} {removed-function} { The~ command~ #1~ has~ been~ removed. } \msg_new:nnn {chemformula} {removed} { On~ line~ \msg_line_number: : \\ The~ #1~ `#2'~ has~ been~ removed~ from~ chemformula. \\ If~ you~ need~ it~ back~ please~ open~ an~ issue~ on~ \\ https://github.com/cgnieder/chemformula/issues \tl_if_blank:nF {#3} { \\ #3 } } \msg_new:nnn {chemformula} {load-time-option} { `#1'~ is~ a~ load-time~ option! \\ You~ cannot~ set~ it~ with~ \token_to_str:N \setchemformula ! \\ You~ need~ to~ use~ \token_to_str:N \usepackage [#1] {chemformula} . } \msg_new:nnn {chemformula} {unknown-option} { Unknown~ option~ `#1' \\ I~ dont'~ know~ the~ option~ `#1'.~ Please~ make~ sure~ there~ is~ no~ typo.~ Check~ the~ manual~ for~ help. } % -------------------------------------------------------------------------- % variants of kernel functions: \cs_generate_variant:Nn \keys_set:nn {nV} \cs_generate_variant:Nn \tl_if_blank:nF {V} \cs_generate_variant:Nn \tl_if_in:nnT {x,nV} \cs_generate_variant:Nn \tl_if_eq:nnT {V,x} \cs_generate_variant:Nn \tl_if_eq:nnTF {o,V} \cs_generate_variant:Nn \tl_set:Nn {cV,Ne} \cs_generate_variant:Nn \tl_put_right:Nn {Ne} \cs_generate_variant:Nn \tl_replace_all:Nnn {NV,Nnx} \cs_generate_variant:Nn \tl_replace_once:Nnn {Nxx} \cs_generate_variant:Nn \tl_set_rescan:Nnn {NnV} \cs_generate_variant:Nn \prop_item:Nn {NV} \cs_generate_variant:Nn \prop_if_in:NnT {Nx} \cs_generate_variant:Nn \dim_set:Nn {NV} \cs_generate_variant:Nn \skip_set:Nn {cV} \cs_generate_variant:Nn \str_if_eq:nnT {V} % -------------------------------------------------------------------------- % VARIABLES % temporary variables: \tl_new:N \l__chemformula_tmpa_tl \tl_new:N \l__chemformula_tmpb_tl \tl_new:N \l__chemformula_tmpc_tl \dim_new:N \l__chemformula_tmpa_dim \dim_new:N \l__chemformula_tmpb_dim \dim_new:N \l__chemformula_tmpc_dim \int_new:N \l__chemformula_tmpa_int \int_new:N \l__chemformula_tmpb_int \int_new:N \l__chemformula_tmpc_int \box_new:N \l__chemformula_tmpa_box \box_new:N \l__chemformula_tmpb_box \seq_new:N \l__chemformula_tmpa_seq \bool_new:N \l__chemformula_tmpa_bool % booleans \bool_new:N \l__chemformula_debug_bool \bool_new:N \l_chemformula_inside_ch_bool \bool_new:N \l_chemformula_formal_charges_bool \bool_new:N \l_chemformula_formal_chem_bool \bool_new:N \l__chemformula_options_bool \bool_new:N \l__chemformula_is_option_bool \bool_new:N \l__chemformula_stoich_bool \bool_new:N \l__chemformula_no_stoich_bool \bool_new:N \l__chemformula_is_addition_symbol_bool \bool_new:N \l__chemformula_is_symbol_bool \bool_new:N \l__chemformula_is_arrow_bool \bool_new:N \l__chemformula_arrow_has_options_bool \bool_new:N \l__chemformula_is_name_bool \bool_new:N \l__chemformula_stoich_is_iupac_bool \bool_new:N \l__chemformula_stoich_parse_iupac_bool \bool_new:N \l__chemformula_first_last_text_bool \bool_new:N \l__chemformula_first_last_double_bool \bool_new:N \l__chemformula_first_last_single_bool \bool_new:N \l__chemformula_first_last_math_bool \bool_new:N \l__chemformula_first_last_dollar_bool \bool_new:N \l__chemformula_first_last_mathbraces_bool \bool_new:N \l__chemformula_number_style_math_bool \bool_new:N \l__chemformula_charge_style_math_bool \bool_new:N \l__chemformula_is_isotope_bool \bool_new:N \l__chemformula_xfrac_bool \bool_new:N \l__chemformula_nicefrac_bool \bool_new:N \l__chemformula_mathfrac_bool \bool_new:N \l__chemformula_fss_bool \bool_new:N \l__chemformula_fontspec_bool \bool_new:N \l__chemformula_fss_family_bool \bool_new:N \l__chemformula_fss_series_bool \bool_new:N \l__chemformula_fss_shape_bool \bool_new:N \l__chemformula_name_width_bool \bool_new:N \l__chemformula_charge_full_shift_bool \bool_new:N \l__chemformula_tikzexternaldisable_bool \bool_new:N \l__chemformula_kroegervink_bool \bool_new:N \l__chemformula_inside_subscript_bool \bool_new:N \l__chemformula_inside_superscript_bool \bool_new:N \l__chemformula_subsuper_use_math_bool \bool_new:N \l__chemformula_subandsuper_bool % dimensions: \dim_new:N \l__chemformula_arrow_length_dim \dim_new:N \l__chemformula_arrow_label_height_dim \dim_new:N \l__chemformula_arrow_label_offset_dim \dim_new:N \l__chemformula_arrow_minimum_length_dim \dim_new:N \l__chemformula_arrow_shortage_dim \dim_new:N \l__chemformula_arrow_offset_dim \dim_new:N \l__chemformula_arrow_yshift_dim \dim_new:N \l__chemformula_radical_radius_dim \dim_new:N \l__chemformula_radical_hshift_dim \dim_new:N \l__chemformula_radical_vshift_dim \dim_new:N \l__chemformula_radical_space_dim \dim_new:N \l__chemformula_arrow_head_dim \dim_new:N \l__chemformula_name_dim \dim_new:N \l__chemformula_adduct_space_dim \dim_new:N \l__chemformula_charge_shift_dim \dim_new:N \l__chemformula_subscript_shift_dim \dim_new:N \l__chemformula_superscript_shift_dim \dim_new:N \l__chemformula_subscript_dim \dim_new:N \l__chemformula_superscript_dim \dim_new:N \l__chemformula_bond_dim \dim_new:N \l__chemformula_bond_space_dim \dim_new:N \l__chemformula_elspec_pair_distance_dim \dim_new:N \l__chemformula_elspec_pair_line_length_dim \dim_new:N \l__chemformula_elspec_pair_width_dim \dim_new:N \l__chemformula_kroegervink_positive_radius_dim \dim_new:N \l__chemformula_kroegervink_positive_hshift_dim \dim_new:N \l__chemformula_kroegervink_positive_vshift_dim \dim_new:N \l__chemformula_kroegervink_positive_space_dim % skips: \skip_new:N \l__chemformula_stoich_space_skip \skip_new:N \l__chemformula_math_space_skip \skip_new:N \l__chemformula_additions_symbol_space_skip % integers: \int_new:N \l__chemformula_count_tokens_int \int_new:N \g__chemformula_lewis_int % token lists: \tl_new:N \l__chemformula_compound_sep_tl \tl_new:N \l__chemformula_compound_tl \tl_new:N \l__chemformula_arrow_ratio_tl \tl_new:N \l__chemformula_radical_style_tl \tl_new:N \l__chemformula_arrow_head_tl \tl_new:N \l__chemformula_upper_label_tl \tl_new:N \l__chemformula_lower_label_tl \tl_new:N \l__chemformula_arrow_style_tl \tl_new:N \l__chemformula_arrow_label_style_tl \tl_new:N \l__chemformula_arrow_type_tl \tl_new:N \l__chemformula_arrow_penalty_tl \tl_new:N \l__chemformula_arrow_offset_tl \tl_new:N \l__chemformula_bond_penalty_tl \tl_new:N \l__chemformula_chemformula_tmpa_tl \tl_new:N \g__chemformula_options_tl \tl_new:N \g__chemformula_output_tl \tl_new:N \l__chemformula_input_tl \tl_new:N \l__chemformula_stoich_tl \tl_new:N \l__chemformula_stoich_format_tl \tl_new:N \l__chemformula_decimal_output_tl \tl_new:N \l__chemformula_font_family_tl \tl_new:N \l__chemformula_font_series_tl \tl_new:N \l__chemformula_font_shape_tl \tl_new:N \l__chemformula_format_tl \tl_new:N \l__chemformula_atom_format_tl \tl_new:N \l__chemformula_fontspec_options_tl \tl_new:N \l__chemformula_fontspec_argument_tl \tl_new:N \l__chemformula_name_format_tl \tl_new:N \l__chemformula_subscript_shift_additional_tl \tl_new:N \l__chemformula_superscript_shift_additional_tl \tl_new:N \l__chemformula_subscript_tl \tl_new:N \l__chemformula_superscript_tl \tl_new:N \l__chemformula_elspec_angle_tl \tl_new:N \l__chemformula_elspec_radius_tl \tl_new:N \l__chemformula_elspec_default_type_tl \tl_new:N \l__chemformula_kroegervink_positive_style_tl \tl_new:N \l__chemformula_kroegervink_neutral_tl \tl_new:N \l__chemformula_adduct_penalty_tl \tl_new:N \l__chemformula_catcodes_tl \tl_new:N \l__chemformula_additions_symbol_penalty_tl \tl_const:Nx \c__chemformula_colon_tl { \token_to_str:N : } % property lists: \prop_new:N \l__chemformula_arrows_code_prop \prop_new:N \l__chemformula_compound_prop \prop_new:N \l__chemformula_bonds_prop \prop_new:N \l__chemformula_stoich_prop \prop_new:N \l__chemformula_charge_prop \prop_new:N \l__chemformula_numbers_prop \prop_new:N \l__chemformula_no_stoich_prop \prop_new:N \l__chemformula_lewis_elspec_types_prop \prop_new:N \l__chemformula_kroegervink_prop \prop_new:N \l__chemformula_symbols_prop \prop_new:N \l__chemformula_clean_subscript_prop \prop_new:N \l__chemformula_addition_symbol_prop % sequences: \seq_new:N \l__chemformula_arrows_type_seq \seq_new:N \l__chemformula_input_seq \seq_new:N \l__chemformula_clean_subscript_seq % boxes: \box_new:N \l__chemformula_arrow_arg_i_box \box_new:N \l__chemformula_arrow_arg_ii_box \box_new:N \l__chemformula_superscript_box \box_new:N \l__chemformula_subscript_box % -------------------------------------------------------------------------- % initial values: \bool_set_true:N \l_chemformula_formal_chem_bool \bool_set_true:N \l__chemformula_mathfrac_bool \bool_set_true:N \l__chemformula_tikzexternaldisable_bool \tl_set:Nn \l__chemformula_compound_sep_tl {.5em} \tl_set:Nn \l__chemformula_arrow_ratio_tl {.6} \tl_set:Nn \l__chemformula_arrow_head_tl {cf} \tl_set:Nn \l__chemformula_arrow_label_style_tl { \footnotesize } \tl_set:Nn \l__chemformula_arrow_penalty_tl {0} \tl_set:Nn \l__chemformula_arrow_offset_tl {.75em} \tl_set:Nn \l__chemformula_bond_penalty_tl {10000} \tl_set:Nn \l__chemformula_decimal_output_tl {.} \tl_set:Nn \l__chemformula_name_format_tl { \scriptsize\centering } \tl_set:Nn \l__chemformula_subscript_shift_additional_tl {0pt} \tl_set:Nn \l__chemformula_superscript_shift_additional_tl {0pt} \tl_set:Nn \l__chemformula_elspec_radius_tl {.5ex} \tl_set:Nn \l__chemformula_elspec_default_type_tl {pair} \tl_set:Nn \l__chemformula_kroegervink_neutral_tl {$\times$} \tl_set:Nn \l__chemformula_adduct_penalty_tl {300} \tl_set_eq:NN \l__chemformula_font_family_tl \f@family \tl_set_eq:NN \l__chemformula_font_series_tl \f@series \tl_set_eq:NN \l__chemformula_font_shape_tl \f@shape \dim_set:Nn \l__chemformula_arrow_label_offset_dim {2pt} \dim_set:Nn \l__chemformula_arrow_yshift_dim {0pt} \dim_set:Nn \l__chemformula_radical_radius_dim {.2ex} \dim_set:Nn \l__chemformula_radical_hshift_dim {.15em} \dim_set:Nn \l__chemformula_radical_vshift_dim {.5ex} \dim_set:Nn \l__chemformula_radical_space_dim {.3em} \dim_set:Nn \l__chemformula_radical_space_dim {.3em} \dim_set:Nn \l__chemformula_adduct_space_dim {.1333em} \dim_set:Nn \l__chemformula_charge_shift_dim {.5ex} \dim_set:Nn \l__chemformula_bond_dim {.5833em} \dim_set:Nn \l__chemformula_bond_space_dim {.07em} \dim_set:Nn \l__chemformula_elspec_pair_distance_dim {1ex} \dim_set:Nn \l__chemformula_elspec_pair_line_length_dim {1.5ex} \dim_set:Nn \l__chemformula_elspec_pair_width_dim {1pt} \dim_set:Nn \l__chemformula_kroegervink_positive_radius_dim {.3ex} \dim_set:Nn \l__chemformula_kroegervink_positive_hshift_dim {.15em} \dim_set:Nn \l__chemformula_kroegervink_positive_vshift_dim {.5ex} \dim_set:Nn \l__chemformula_kroegervink_positive_space_dim {.4em} \dim_zero:N \l__chemformula_superscript_dim \dim_zero:N \l__chemformula_subscript_dim \skip_set:Nn \l__chemformula_stoich_space_skip { .1667em plus .0333em minus .0117em } \skip_set:Nn \l__chemformula_math_space_skip { .1667em plus .0333em minus .0117em } % ---------------------------------------------------------------------------- % debugging \prg_new_conditional:Npnn \__chemformula_if_debug: {T,F,TF} { \bool_if:NTF \l__chemformula_debug_bool { \prg_return_true: } { \prg_return_false: } } % ---------------------------------------------------------------------------- % deprecation & removal: % #1: type % #2: old % #3: new \cs_new_protected:Npn \__chemformula_deprecation_warning:nnn #1#2#3 { \msg_warning:nnnnn {chemformula} {deprecated} {#1} {#2} {#3} } \cs_generate_variant:Nn \__chemformula_deprecation_warning:nnn {nne,nV} % #1: type % #2: old % #3: additional text \cs_new_protected:Npn \chemformula_removal_warning:nnn #1#2#3 { \msg_warning:nnnnn {chemformula} {removed} {#1} {#2} {#3} } \cs_generate_variant:Nn \chemformula_removal_warning:nnn {nV} % #1: type % #2: old \cs_new_protected:Npn \chemformula_removal_warning:nn #1#2 { \msg_warning:nnnn {chemformula} {removed} {#1} {#2} } \cs_generate_variant:Nn \chemformula_removal_warning:nn {nV} % #1: new \cs_new_protected:Npn \chemformula_deprecate_option:n #1 { \__chemformula_deprecation_warning:nVn {option} \l_keys_key_str {#1} } % #1: additional text \cs_new_protected:Npn \chemformula_remove_option:n #1 { \chemformula_removal_warning:nVn {option} \l_keys_key_str {#1} } \cs_new_protected:Npn \chemformula_remove_option: { \chemformula_removal_warning:nV {option} \l_keys_key_str } % #1: old % #2: new \cs_new_protected:Npn \chemformula_deprecate_function:NN #1#2 { \cs_set_protected:Npn #1 { \msg_error:nnnn {chemformula} {deprecated-function} {#1} {#2} #2 } } % #1: old \cs_new_protected:Npn \chemformula_remove_function:N #1 { \cs_set_protected:Npn #1 { \msg_error:nnn {chemformula} {removed-function} {#1} } } % -------------------------------------------------------------------------- % load-time options: \cs_new_protected:Npn \__chemformula_loadtime_error:n #1 { \msg_error:nnV {chemformula} {#1} \l_keys_key_str } \cs_new_protected:Npn \__chemformula_loadtime_warning:n #1 { \msg_warning:nnV {chemformula} {#1} \l_keys_key_str } \keys_define:nn {chemformula/load-time} { debug .bool_set:N = \l__chemformula_debug_bool , debug .initial:n = false } \ProcessKeysPackageOptions {chemformula/load-time} \keys_define:nn {chemformula} { debug .code:n = \__chemformula_loadtime_error:n {load-time-option} , unknown .code:n = \__chemformula_loadtime_warning:n {unknown-option} , load-time / debug .meta:nn = {chemformula} {debug} } % -------------------------------------------------------------------------- % catcode stuff \cs_new_protected:Npn \__chemformula_save_catcodes: { \cs_gset_protected:Npx \__chemformula_restore: { \char_set_catcode:nn { 95 } { \char_value_catcode:n { 95 } }% _ \char_set_catcode:nn { 58 } { \char_value_catcode:n { 58 } }% : \char_set_catcode:nn { 94 } { \char_value_catcode:n { 94 } }% ^ \char_set_catcode:nn { 123 } { \char_value_catcode:n { 123 } }% { \char_set_catcode:nn { 125 } { \char_value_catcode:n { 125 } }% } \char_set_catcode:nn { 35 } { \char_value_catcode:n { 35 } }% # \char_set_catcode:nn { 33 } { \char_value_catcode:n { 33 } }% ! \char_set_catcode:nn { 34 } { \char_value_catcode:n { 34 } }% " \char_set_catcode:nn { 60 } { \char_value_catcode:n { 60 } }% < \char_set_catcode:nn { 62 } { \char_value_catcode:n { 62 } }% > \char_set_catcode:nn { 126 } { \char_value_catcode:n { 126 } }% ~ } } \cs_gset_protected:Npn \__chemformula_basic_catcodes: { % expl3 catcodes: \char_set_catcode_letter:N \_ \char_set_catcode_letter:N \: % I've forgotten why I put this here: \char_set_catcode_math_superscript:N \^ % disable some of the specials (needed for sub- and superscripts): \char_set_catcode_letter:N \# % make the naming work with babel languages like French that make % ! active: \char_set_catcode_other:N \! % make the naming work with babel languages like Spanish that make % < and > active: \char_set_catcode_other:N \> \char_set_catcode_other:N \< % ensure " is other: \char_set_catcode_other:N \" % spaces are spaces: \char_set_catcode_space:N \ } \cs_new_protected:Npn \__chemformula_sanitize:Nn #1#2 { \tl_set_rescan:Nnn #1 { \__chemformula_basic_catcodes: % disable some of the specials (needed for sub- and superscripts): \char_set_catcode_other:N \{ \char_set_catcode_other:N \} } {#2} } \cs_generate_variant:Nn \__chemformula_sanitize:Nn {NV} % -------------------------------------------------------------------------- % general and helper functions: \cs_new_protected:Npn \chemformula_tikz:nn #1#2 { \group_begin: \chemformula_tikzexternaldisable: \tikz [#1] {#2} \group_end: } \cs_generate_variant:Nn \chemformula_tikz:nn {xn,nf} \cs_new_protected:Npn \chemformula_draw:nn #1#2 { \draw [#1] #2 ; } \cs_generate_variant:Nn \chemformula_draw:nn {xn,nx,xx,xf,Vn} \cs_new_protected:Npn \chemformula_node:nn #1#2 { \node [#1] {#2} ; } \cs_generate_variant:Nn \chemformula_node:nn {x} \cs_new_protected:Npn \chemformula_node:nnn #1#2#3 { \node [#1] (#2) {#3} ; } \cs_generate_variant:Nn \chemformula_node:nnn {nx} \cs_new_protected:Npn \chemformula_allow_break: { \tex_penalty:D \c_zero_int } \cs_new_protected:Npn \chemformula_leave_vmode: { \hbox_unpack:N \c_empty_box } \cs_new_protected:Npn \chemformula_nobreak: { \tex_penalty:D 10000 \scan_stop: } \cs_new_protected:Npn \chemformula_skip_nobreak:N #1 { \chemformula_nobreak: \skip_horizontal:N #1 \chemformula_nobreak: } \cs_generate_variant:Nn \chemformula_skip_nobreak:N {c} \cs_new_protected:Npn \chemformula_skip_nobreak:n #1 { \chemformula_nobreak: \skip_horizontal:n {#1} \chemformula_nobreak: } \cs_new_protected:Npn \chemformula_skip_nobreak_penalty:Nn #1#2 { \chemformula_nobreak: \skip_horizontal:N #1 \tex_penalty:D #2 \scan_stop: } \cs_generate_variant:Nn \chemformula_skip_nobreak_penalty:Nn {c,NV} \cs_new_protected:Npn \chemformula_dim_to_width:Nn #1#2 { \hbox_set:Nn \l__chemformula_tmpa_box {#2} \dim_set:Nn #1 { \box_wd:N \l__chemformula_tmpa_box } \box_clear:N \l__chemformula_tmpa_box } % -------------------------------------------------------------------------- % prevent externalisation of tikz parts of the formulae: \hook_gput_code:nnn {begindocument} {chemformula} { \providecommand \tikzexternaldisable {} } \keys_define:nn {chemformula} { tikz-external-disable .bool_set:N = \l__chemformula_tikzexternaldisable_bool } \cs_new_protected:Npn \chemformula_tikzexternaldisable: { \bool_if:NT \l__chemformula_tikzexternaldisable_bool { \tikzexternaldisable } } % -------------------------------------------------------------------------- % circled charge signs: \cs_new_protected:Npn \chemformula_fplus: { \ensuremath { \__chemformula_fplus: } } \cs_new_protected:Npn \__chemformula_fplus: { \mathpalette \__chemformula_fplus_aux: \bigcirc } \cs_new_protected:Npn \__chemformula_fplus_aux: #1#2 { \ooalign { \tex_hfil:D \c_math_toggle_token #1 \chemformula_plain_plus: \c_math_toggle_token \tex_hfil:D \tex_cr:D \tex_hfil:D \c_math_toggle_token #1#2 \c_math_toggle_token \tex_hfil:D \tex_cr:D } } \cs_new_protected:Npn \chemformula_fminus: { \ensuremath { \__chemformula_fminus: } } \cs_new_protected:Npn \__chemformula_fminus: { \mathpalette \__chemformula_fminus_aux_aux: \bigcirc } \cs_new_protected:Npn \__chemformula_fminus_aux_aux: #1#2 { \ooalign { \tex_hfil:D \c_math_toggle_token #1 \chemformula_plain_minus: \c_math_toggle_token \tex_hfil:D \tex_cr:D \tex_hfil:D \c_math_toggle_token #1#2 \c_math_toggle_token \tex_hfil:D \tex_cr:D } } \cs_new_protected:Npn \chemformula_plain_plus: { \bool_if:NTF \l__chemformula_charge_style_math_bool { \ensuremath {+} } { \mode_if_math:TF { \text {+} } {+} } } \cs_new_protected:Npn \chemformula_formal_plus: { \bool_if:NTF \l_chemformula_formal_chem_bool { \chemformula_fplus: } { \mode_if_math:TF { \oplus } { \c_math_toggle_token \oplus \c_math_toggle_token } } } \cs_new_protected:Npn \chemformula_plus: { \bool_if:NTF \l_chemformula_formal_charges_bool { \chemformula_formal_plus: } { \chemformula_plain_plus: } } \cs_new_protected:Npn \chemformula_plain_minus: { \bool_if:NTF \l__chemformula_charge_style_math_bool { \ensuremath {-} } { \mode_if_math:TF { \text { \textendash } } { \textendash } } } \cs_new_protected:Npn \chemformula_formal_minus: { \bool_if:NTF \l_chemformula_formal_chem_bool { \chemformula_fminus: } { \mode_if_math:TF { \ominus } { \c_math_toggle_token \ominus \c_math_toggle_token } } } \cs_new_protected:Npn \chemformula_minus: { \bool_if:NTF \l_chemformula_formal_charges_bool { \chemformula_formal_minus: } { \chemformula_plain_minus: } } % -------------------------------------------------------------------------- % Some basic internal commands: \cs_new_protected:Npn \chemformula_radical_or_decimal: { \peek_meaning:NTF \c_group_begin_token { \chemformula_decimal: } { \chemformula_radical: } } \cs_new_protected:Npn \chemformula_radical: { \hbox_overlap_right:n { \chemformula_tikz:xn { \l__chemformula_radical_style_tl , baseline , minimum~ height = 0pt , minimum~ width = 0pt , inner~ sep = 0pt , outer~ sep = 0pt , overlay } { \fill (0pt,0pt) ++( \l__chemformula_radical_hshift_dim , \l__chemformula_radical_vshift_dim ) circle (\l__chemformula_radical_radius_dim) ; } } \chemformula_skip_nobreak:N \l__chemformula_radical_space_dim } \keys_define:nn {chemformula} { % TikZ style: radical-style .tl_set:N = \l__chemformula_radical_style_tl , radical-radius .dim_set:N = \l__chemformula_radical_radius_dim , % shift before: radical-hshift .dim_set:N = \l__chemformula_radical_hshift_dim , radical-vshift .dim_set:N = \l__chemformula_radical_vshift_dim , % space after: radical-space .dim_set:N = \l__chemformula_radical_space_dim } \cs_new_protected:Npn \chemformula_adduct: { \chemformula_skip_nobreak:N \l__chemformula_adduct_space_dim \textperiodcentered \chemformula_skip_nobreak_penalty:NV \l__chemformula_adduct_space_dim \l__chemformula_adduct_penalty_tl } \cs_new_eq:NN \chemformula_star_adduct: \chemformula_adduct: % -------------------------------------------------------------------------- % Kroeger-Vink notation \cs_new_protected:Npn \chemformula_kroegervink_negative: { \ensuremath { \prime } } \cs_new_protected:Npn \chemformula_kroegervink_neutral: { \ensuremath { \text {\l__chemformula_kroegervink_neutral_tl } } } \cs_new_protected:Npn \chemformula_kroegervink_positive: { \hbox_overlap_right:n { \chemformula_tikz:xn { \l__chemformula_kroegervink_positive_style_tl , baseline , minimum~ height = 0pt , minimum~ width = 0pt , inner~ sep = 0pt , outer~ sep = 0pt , overlay } { \fill (0,0) ++( \l__chemformula_kroegervink_positive_hshift_dim , \l__chemformula_kroegervink_positive_vshift_dim ) circle (\l__chemformula_kroegervink_positive_radius_dim) ; } } \chemformula_skip_nobreak:N \l__chemformula_kroegervink_positive_space_dim } \cs_new_protected:Npn \chemformula_prime: { \bool_if:NTF \l__chemformula_kroegervink_bool { \chemformula_kroegervink_negative: } {'} } \keys_define:nn {chemformula} { kroeger-vink .bool_set:N = \l__chemformula_kroegervink_bool , % TikZ style: kv-positive-style .tl_set:N = \l__chemformula_kroegervink_positive_style_tl , kv-positive-radius .dim_set:N = \l__chemformula_kroegervink_positive_radius_dim , % spacing: kv-positive-hshift .dim_set:N = \l__chemformula_kroegervink_positive_hshift_dim , kv-positive-vshift .dim_set:N = \l__chemformula_kroegervink_positive_vshift_dim , kv-positive-offset .dim_set:N = \l__chemformula_kroegervink_positive_space_dim , % symbol: kv-neutral-symbol .tl_set:N = \l__chemformula_kroegervink_neutral_tl } % -------------------------------------------------------------------------- % ARROW DEFINITION % arrow heads: % full tip for pairs \pgfarrowsdeclare { cf~internal } { cf~internal } { \dim_set:Nn \l__chemformula_arrow_head_dim { 2.5pt + 2.5\pgflinewidth } \pgfarrowsleftextend { -\l__chemformula_arrow_head_dim } \pgfarrowsrightextend { .5\pgflinewidth } } { \dim_set:Nn \l__chemformula_arrow_head_dim { 2.5pt + 2.5\pgflinewidth } \pgfsetdash {} { 0pt } \pgfsetroundjoin \pgfsetroundcap \pgfpathmoveto { \pgfpoint { 0pt } { 0pt } } \pgfpathlineto { \pgfpoint { -\l__chemformula_arrow_head_dim } { .3\l__chemformula_arrow_head_dim } } \pgfpathlineto { \pgfpoint { -.5\l__chemformula_arrow_head_dim } { 0pt } } \pgfpathlineto { \pgfpoint { -\l__chemformula_arrow_head_dim } { -.3\l__chemformula_arrow_head_dim } } \pgfpathlineto { \pgfpoint { 0pt } { 0pt } } \pgfusepathqfillstroke } % half tip on the left \pgfarrowsdeclare { left~cf~internal } { left~cf~internal } { \dim_set:Nn \l__chemformula_arrow_head_dim { 2.5pt + 2.5\pgflinewidth } \pgfarrowsleftextend { -\l__chemformula_arrow_head_dim } \pgfarrowsrightextend { .5\pgflinewidth } } { \dim_set:Nn \l__chemformula_arrow_head_dim { 2.5pt + 2.5\pgflinewidth } \pgfsetdash {} { 0pt } \pgfsetroundjoin \pgfsetroundcap \pgfpathmoveto { \pgfpoint { 0pt } { 0pt } } \pgfpathlineto { \pgfpoint { -\l__chemformula_arrow_head_dim } { .3\l__chemformula_arrow_head_dim } } \pgfpathlineto { \pgfpoint { -.5\l__chemformula_arrow_head_dim } { 0pt } } \pgfpathlineto { \pgfpoint { 0pt } { 0pt } } \pgfusepathqfillstroke } % half tip in the right \pgfarrowsdeclare { right~cf~internal } { right~cf~internal } { \dim_set:Nn \l__chemformula_arrow_head_dim { 2.5pt + 2.5\pgflinewidth } \pgfarrowsleftextend { -\l__chemformula_arrow_head_dim } \pgfarrowsrightextend { .5\pgflinewidth } } { \dim_set:Nn \l__chemformula_arrow_head_dim { 2.5pt + 2.5\pgflinewidth } \pgfsetdash {} { 0pt } \pgfsetroundjoin \pgfsetroundcap \pgfpathmoveto { \pgfpoint { 0pt } { 0pt } } \pgfpathlineto { \pgfpoint { -\l__chemformula_arrow_head_dim } { -.3\l__chemformula_arrow_head_dim } } \pgfpathlineto { \pgfpoint { -.5\l__chemformula_arrow_head_dim } { 0pt } } \pgfpathlineto { \pgfpoint { 0pt } { 0pt } } \pgfusepathqfillstroke } \pgfkeys{ cf~ /.tip = {cf~internal} , left~cf~ /.tip = {left~cf~internal} , right~cf~ /.tip = {right~cf~internal} } % -------------------------------------------------------------------------- % determine length in dependency of labels \cs_new_protected:Npn \__chemformula_determine_arrow_length:NN #1#2 { \dim_set:NV \l__chemformula_arrow_offset_dim \l__chemformula_arrow_offset_tl \box_set_eq:NN \l__chemformula_tmpa_box #1 \dim_set:Nn \l__chemformula_tmpa_dim { \box_wd:N \l__chemformula_tmpa_box } \box_set_eq:NN \l__chemformula_tmpa_box #2 \dim_set:Nn \l__chemformula_tmpb_dim { \box_wd:N \l__chemformula_tmpa_box } \box_clear:N \l__chemformula_tmpa_box \dim_compare:nTF { \l__chemformula_tmpa_dim >= \l__chemformula_tmpb_dim } { \dim_set_eq:NN \l__chemformula_arrow_length_dim \l__chemformula_tmpa_dim } { \dim_set_eq:NN \l__chemformula_arrow_length_dim \l__chemformula_tmpb_dim } \dim_add:Nn \l__chemformula_arrow_length_dim { 2\l__chemformula_arrow_offset_dim } \dim_compare:nF { \l__chemformula_arrow_length_dim > \l__chemformula_arrow_minimum_length_dim } { \dim_set_eq:NN \l__chemformula_arrow_length_dim \l__chemformula_arrow_minimum_length_dim } \dim_set:Nn \l__chemformula_arrow_shortage_dim { ( \l__chemformula_arrow_length_dim - \l__chemformula_arrow_length_dim * \dim_ratio:nn { \l__chemformula_arrow_ratio_tl pt } { 1pt } ) * 1/2 } \box_set_eq:NN \l__chemformula_tmpa_box #1 \dim_set:Nn \l__chemformula_tmpa_dim { \box_ht:N \l__chemformula_tmpa_box + \box_dp:N \l__chemformula_tmpa_box } \box_set_eq:NN \l__chemformula_tmpa_box #2 \dim_set:Nn \l__chemformula_tmpb_dim { \box_ht:N \l__chemformula_tmpa_box + \box_dp:N \l__chemformula_tmpa_box } \box_clear:N \l__chemformula_tmpa_box \dim_compare:nTF { \l__chemformula_tmpa_dim >= \l__chemformula_tmpb_dim } { \dim_set_eq:NN \l__chemformula_arrow_label_height_dim \l__chemformula_tmpa_dim } { \dim_set_eq:NN \l__chemformula_arrow_label_height_dim \l__chemformula_tmpb_dim } } % -------------------------------------------------------------------------- % define arrow types % draw arrows: \cs_new_protected:Npn \__chemformula_draw_arrow:nnn #1#2#3 { \chemformula_if_is_arrow:nTF {#1} { \prop_get:NnN \l__chemformula_arrows_code_prop {#1} \l__chemformula_tmpa_tl \__chemformula_arrow_draw:Vnn \l__chemformula_tmpa_tl {#2} {#3} } { \msg_error:nnn {chemformula} {unknown-arrow} {#1} } } % this will be \arrow inside \ch \DeclareDocumentCommand \charrow { mO{}O{} } { \group_begin: \__chemformula_draw_arrow:nnn {#1} {#2} {#3} \group_end: } % draw the arrows \cs_new_protected:Npn \__chemformula_arrow_draw:nnn #1#2#3 { \chemformula_nobreak: % \__chemformula_sanitize:Nn \l__chemformula_tmpc_tl {#1} % prepare arrow code for drawing: \tl_set_rescan:Nnn \l__chemformula_tmpc_tl { \__chemformula_basic_catcodes: } {#1} % determine length of the arrow \hbox_set:Nn \l__chemformula_arrow_arg_i_box { \tl_use:N \l__chemformula_arrow_label_style_tl \cs_set:Npn \newline { \tabularnewline } \begin {tabular} {c} #2 \end {tabular} } \hbox_set:Nn \l__chemformula_arrow_arg_ii_box { \tl_use:N \l__chemformula_arrow_label_style_tl \cs_set:Npn \newline { \tabularnewline } \begin {tabular} {c} #3 \end {tabular} } \__chemformula_determine_arrow_length:NN \l__chemformula_arrow_arg_i_box \l__chemformula_arrow_arg_ii_box \chemformula_tikz:nf { inner~sep=0, baseline=(chemformula_arrow_start.base) } { % the coordinates \chemformula_draw:xn { \l__chemformula_arrow_style_tl } { coordinate (chemformula_arrow_start) (0pt,0pt) ++ ( \l__chemformula_compound_sep_tl , .3432em) ++ (0pt,\l__chemformula_arrow_yshift_dim) coordinate (cf_arrow_start) ++ ( .5 * \dim_use:N \l__chemformula_arrow_length_dim , 0pt) coordinate (cf_arrow_mid) ++ ( .5 * \dim_use:N \l__chemformula_arrow_length_dim , 0pt) coordinate (cf_arrow_end) ++ ( \l__chemformula_compound_sep_tl , 0pt ) (cf_arrow_start) ++ (\l__chemformula_arrow_shortage_dim , 0pt) coordinate (cf_arrow_mid_start) (cf_arrow_end) ++ (-\l__chemformula_arrow_shortage_dim , 0pt) coordinate (cf_arrow_mid_end) } % the arrow labels: \draw node [ above=\l__chemformula_arrow_label_offset_dim ] at (cf_arrow_mid) { \box_use:N \l__chemformula_arrow_arg_i_box } node [ below=\l__chemformula_arrow_label_offset_dim ] at (cf_arrow_mid) { \box_use:N \l__chemformula_arrow_arg_ii_box } ; \tl_use:N \l__chemformula_tmpc_tl } \chemformula_skip_nobreak_penalty:NV \c_zero_skip \l__chemformula_arrow_penalty_tl } \cs_generate_variant:Nn \__chemformula_arrow_draw:nnn {V} \prg_new_conditional:Npnn \chemformula_if_is_arrow:n #1 {p,T,F,TF} { \__chemformula_sanitize:Nn \l__chemformula_tmpa_tl {#1} \seq_if_in:NVTF \l__chemformula_arrows_type_seq \l__chemformula_tmpa_tl { \prg_return_true: } { \prg_return_false: } } \prg_generate_conditional_variant:Nnn \chemformula_if_is_arrow:n {V} {T,F,TF} \cs_new_protected:Npn \chemformula_define_arrow:nn #1#2 { \__chemformula_sanitize:Nn \l__chemformula_tmpa_tl {#1} \__chemformula_sanitize:Nn \l__chemformula_tmpb_tl {#2} \seq_if_in:NVF \l__chemformula_arrows_type_seq \l__chemformula_tmpa_tl { \seq_put_right:NV \l__chemformula_arrows_type_seq \l__chemformula_tmpa_tl } \prop_put:NVV \l__chemformula_arrows_code_prop \l__chemformula_tmpa_tl \l__chemformula_tmpb_tl } % commands to declare arrows (can also be used by users): % #1: symbol, #2: code \NewDocumentCommand \NewChemArrow {mm} { \chemformula_if_is_arrow:nTF {#1} { \msg_error:nnn {chemformula} {new-arrow} {#1} } { \chemformula_define_arrow:nn {#1} {#2} } } \NewDocumentCommand \DeclareChemArrow {mm} { \chemformula_define_arrow:nn {#1} {#2} } \NewDocumentCommand \RenewChemArrow {mm} { \chemformula_if_is_arrow:nTF {#1} { \chemformula_define_arrow:nn {#1} {#2} } { \msg_error:nnn {chemformula} {renew-arrow} {#1} } } \NewDocumentCommand \ProvideChemArrow {mm} { \chemformula_if_is_arrow:nF {#1} { \chemformula_define_arrow:nn {#1} {#2} } } \NewDocumentCommand \ShowChemArrow {m} { \chemformula_if_is_arrow:nT {#1} { \prop_get:NnN \l__chemformula_arrows_code_prop {#1} \l__chemformula_tmpa_tl \tl_to_str:N \l__chemformula_tmpa_tl } } % declare arrows: % standard arrows: \NewChemArrow {->} { \draw[chemarrow,-cf] (cf_arrow_start) -- (cf_arrow_end) ; } \NewChemArrow {<-} { \draw[chemarrow,cf-] (cf_arrow_start) -- (cf_arrow_end) ; } \NewChemArrow {<->} { \draw[chemarrow,cf-cf] (cf_arrow_start) -- (cf_arrow_end) ; } % equilibria: \NewChemArrow {<=>} { \draw[chemarrow,-left~cf] ([yshift=.15ex]cf_arrow_start) -- ([yshift=.15ex]cf_arrow_end) ; \draw[chemarrow,left~cf-] ([yshift=-.15ex]cf_arrow_start) -- ([yshift=-.15ex]cf_arrow_end) ; } \NewChemArrow {<=>>} { \draw[chemarrow,-left~cf] ([yshift=.15ex]cf_arrow_start) -- ([yshift=.15ex]cf_arrow_end) ; \draw[chemarrow,left~cf-] ([yshift=-.15ex]cf_arrow_mid_start) -- ([yshift=-.15ex]cf_arrow_mid_end) ; } \NewChemArrow {<<=>} { \draw[chemarrow,-left~cf] ([yshift=.15ex]cf_arrow_mid_start) -- ([yshift=.15ex]cf_arrow_mid_end) ; \draw[chemarrow,left~cf-] ([yshift=-.15ex]cf_arrow_start) -- ([yshift=-.15ex]cf_arrow_end) ; } % two arrows: \NewChemArrow {<>} { \draw[chemarrow,-cf] ([yshift=.2ex]cf_arrow_start) -- ([yshift=.2ex]cf_arrow_end) ; \draw[chemarrow,cf-,] ([yshift=-.2ex]cf_arrow_start) -- ([yshift=-.2ex]cf_arrow_end) ; } % isolobal arrow: \NewChemArrow {} { \draw[chemarrow,cf-cf] (cf_arrow_start) -- (cf_arrow_end) ; \draw[chemarrow] (cf_arrow_mid) .. controls ++(-.9ex,-1.5ex) and ++(.9ex,-1.5ex) .. (cf_arrow_mid) ; } % equilibria upside down: \NewChemArrow {>>=<} { \draw[chemarrow,right~cf-] ([yshift=.15ex]cf_arrow_start) -- ([yshift=.15ex]cf_arrow_end) ; \draw[chemarrow,-right~cf] ([yshift=-.15ex]cf_arrow_mid_start) -- ([yshift=-.15ex]cf_arrow_mid_end) ; } \NewChemArrow {>=<<} { \draw[chemarrow,right~cf-] ([yshift=.15ex]cf_arrow_mid_start) -- ([yshift=.15ex]cf_arrow_mid_end) ; \draw[chemarrow,-right~cf] ([yshift=-.15ex]cf_arrow_start) -- ([yshift=-.15ex]cf_arrow_end) ; } \NewChemArrow {>=<} { \draw[chemarrow,right~cf-] ([yshift=.15ex]cf_arrow_start) -- ([yshift=.15ex]cf_arrow_end) ; \draw[chemarrow,-right~cf] ([yshift=-.15ex]cf_arrow_start) -- ([yshift=-.15ex]cf_arrow_end) ; } % \NewChemArrow {<==>} { \draw[chemarrow,double~ equal~ sign~ distance,double,Implies-Implies] (cf_arrow_start) -- (cf_arrow_end) ; } % no reaction: \NewChemArrow {-/>} { \draw[chemarrow,-cf] (cf_arrow_start) -- (cf_arrow_end) ; \draw[chemarrow] (cf_arrow_mid) ++ (.2ex,.4ex) -- ++(-.4ex,-.8ex) ; \draw[chemarrow] (cf_arrow_mid) ++ (-.2ex,.4ex) -- ++(-.4ex,-.8ex) ; } \NewChemArrow {}{ \draw[chemarrow,-left~cf] ([yshift=.15ex]cf_arrow_start) -- ([yshift=.15ex]cf_arrow_end) ; \draw[chemarrow,left~cf-] ([yshift=-.15ex]cf_arrow_start) -- ([yshift=-.15ex]cf_arrow_end) ; \draw[chemarrow] (cf_arrow_mid) circle (.4ex) ; } \NewChemArrow{<=o>>}{ \draw[chemarrow,-left~cf] ([yshift=.15ex]cf_arrow_start) -- ([yshift=.15ex]cf_arrow_end) ; \draw[chemarrow,left~cf-] ([yshift=-.15ex]cf_arrow_mid_start) -- ([yshift=-.15ex]cf_arrow_mid_end) ; \draw[chemarrow] (cf_arrow_mid) circle (.4ex) ; } \NewChemArrow{<<=o>}{ \draw[chemarrow,-left~cf] ([yshift=.15ex]cf_arrow_mid_start) -- ([yshift=.15ex]cf_arrow_mid_end) ; \draw[chemarrow,left~cf-] ([yshift=-.15ex]cf_arrow_start) -- ([yshift=-.15ex]cf_arrow_end) ; \draw[chemarrow] (cf_arrow_mid) circle (.4ex) ; } % -------------------------------------------------------------------------- % arrow customization \keys_define:nn {chemformula} { arrow-offset .tl_set:N = \l__chemformula_arrow_offset_tl , arrow-min-length .dim_set:N = \l__chemformula_arrow_minimum_length_dim , arrow-yshift .dim_set:N = \l__chemformula_arrow_yshift_dim , arrow-ratio .tl_set:N = \l__chemformula_arrow_ratio_tl , label-offset .dim_set:N = \l__chemformula_arrow_label_offset_dim , compound-sep .tl_set:N = \l__chemformula_compound_sep_tl , arrow-style .tl_set:N = \l__chemformula_arrow_style_tl , label-style .tl_set:N = \l__chemformula_arrow_label_style_tl , arrow-penalty .tl_set:N = \l__chemformula_arrow_penalty_tl , arrow-style .code:n = \tikzset { chemarrow/.style={#1} } , } % -------------------------------------------------------------------------- % MAIN COMMAND \cs_set_protected:Npn \__chemformula_ch_main:n #1 { \group_begin: % abort if `#1' is blank: \tl_if_blank:nF {#1} { % disable \xspace: \cs_set_eq:NN \xspace \scan_stop: \bool_set_true:N \l_chemformula_inside_ch_bool \tl_if_blank:VF \g__chemformula_options_tl { \keys_set:nV {chemformula} \g__chemformula_options_tl } \__chemformula_read_input:n {#1} \__chemformula_prepare_output:NV \l__chemformula_input_tl \l__chemformula_catcodes_tl \chemformula_write:V \l__chemformula_input_tl \__chemformula_if_debug:T { \tl_show:N \l__chemformula_input_tl } } \group_end: } \cs_new_protected:Npn \__chemformula_read_input:n #1 { \__chemformula_read_input:w #1 ~ \q_stop } \cs_generate_variant:Nn \__chemformula_read_input:n {V} \cs_new_protected:Npn \__chemformula_read_input:w #1 ~ #2 \q_stop { \__chemformula_input:n {#1} \tl_set:Nn \l__chemformula_tmpa_tl {#2} \tl_if_blank:VF \l__chemformula_tmpa_tl { \tl_trim_spaces:N \l__chemformula_tmpa_tl \__chemformula_read_input:V \l__chemformula_tmpa_tl } } \cs_new_protected:Npn \chemformula_write:n #1 { \mode_if_math:TF { \text { \chemformula_font_inner: #1} } { { \chemformula_font_inner: #1 } } } \cs_generate_variant:Nn \chemformula_write:n {V} % internal version of \ch command: \cs_new_protected:Npn \chemformula_ch:nn #1#2 { \group_align_safe_begin: \chemformula_leave_vmode: \tl_if_blank:nTF {#1} { \tl_gclear:N \g__chemformula_options_tl } { \tl_gset:Nn \g__chemformula_options_tl {#1} } \__chemformula_ch_newline:w #2 \\ \q_nil \q_stop \group_align_safe_end: \tl_use:N \g__chemformula_output_tl \tl_gclear:N \g__chemformula_output_tl } \cs_generate_variant:Nn \chemformula_ch:nn {V,nV,VV} % Trickery to use \ch inside align environment: % bypass \\: \cs_new_protected:Npn \__chemformula_ch_newline:w #1 \\ #2 \q_stop { \__chemformula_ch_align:w #1 & \q_nil \q_stop \quark_if_nil:nF {#2} { \tl_gput_right:Nn \g__chemformula_output_tl { \\ } % look for optional argument: \peek_meaning:NTF [ { \__chemformula_ch_newline_skip:w } { \__chemformula_ch_newline:w } #2 \q_stop } } \cs_new_protected:Npn \__chemformula_ch_newline_skip:w [#1] { \tl_gput_right:Nn \g__chemformula_output_tl { [#1] } \__chemformula_ch_newline:w } % bypass &: \cs_new_protected:Npn \__chemformula_ch_align:w #1 & #2 \q_stop { \__chemformula_ch_intertext:w #1 \intertext{} \q_nil \q_stop \quark_if_nil:nF {#2} { \tl_gput_right:Nn \g__chemformula_output_tl {&} \__chemformula_ch_align:w #2 \q_stop } } % bypass \intertext: \cs_new_protected:Npn \__chemformula_ch_intertext:w #1 \intertext#2 #3 \q_stop { \__chemformula_ch_shortintertext:w #1 \shortintertext{} \q_nil \q_stop \quark_if_nil:nF {#3} { \tl_gput_right:Nn \g__chemformula_output_tl { \intertext {#2} } \__chemformula_ch_intertext:w #3 \q_stop } } % bypass \shortintertext: \cs_new_protected:Npn \__chemformula_ch_shortintertext:w #1 \shortintertext#2 #3 \q_stop { \tl_gput_right:Nn \g__chemformula_output_tl { \__chemformula_ch_main:n {#1} } \quark_if_nil:nF {#3} { \tl_gput_right:Nn \g__chemformula_output_tl { \shortintertext {#2} } \__chemformula_ch_shortintertext:w #3 \q_stop } } % -------------------------------------------------------------------------- % user commands: \NewDocumentCommand \ch { O{}m } { \chemformula_ch:nn {#1} {#2} } \cs_new_protected:Npn \chemformula_chcpd:nn #1#2 { \group_begin: \tl_if_blank:nF {#2} { \keys_set:nn {chemformula} {#1} \__chemformula_save_catcodes: \__chemformula_sanitize:Nn \l__chemformula_chemformula_tmpa_tl {#2} \__chemformula_input_compound_no_check:NV \l__chemformula_compound_tl \l__chemformula_chemformula_tmpa_tl \__chemformula_prepare_output:NV \l__chemformula_compound_tl \l__chemformula_catcodes_tl \chemformula_write:V \l__chemformula_compound_tl } \group_end: } \NewDocumentCommand \chcpd { O{}m } { \chemformula_chcpd:nn {#1} {#2} } % -------------------------------------------------------------------------- % arrow generation & detection \cs_new_protected:Npn \__chemformula_generate_arrows:Nn #1#2 { \tl_set_rescan:Nnn \l__chemformula_tmpa_tl { \char_set_catcode_other:N \> \char_set_catcode_other:N \< \char_set_catcode_other:N \- \char_set_catcode_other:N \= } {#2} \int_zero:N \l__chemformula_tmpa_int \seq_clear:N \l__chemformula_tmpa_seq \seq_map_inline:Nn \l__chemformula_arrows_type_seq { \tl_if_in:VnT \l__chemformula_tmpa_tl {##1} { \int_incr:N \l__chemformula_tmpa_int \seq_put_right:Nn \l__chemformula_tmpa_seq {##1} } } \int_compare:nTF { \l__chemformula_tmpa_int = 1 } { \tl_replace_once:Nxx \l__chemformula_tmpa_tl { \seq_item:Nn \l__chemformula_tmpa_seq {1} } { \exp_not:N \charrow { \seq_item:Nn \l__chemformula_tmpa_seq {1} } } } { \int_zero:N \l__chemformula_tmpa_int \int_zero:N \l__chemformula_tmpb_int \int_zero:N \l__chemformula_tmpc_int \seq_map_inline:Nn \l__chemformula_tmpa_seq { \int_incr:N \l__chemformula_tmpa_int \int_compare:nT { \l__chemformula_tmpb_int < \tl_count:n {##1} } { \int_set:Nn \l__chemformula_tmpb_int { \tl_count:n {##1} } \int_set_eq:NN \l__chemformula_tmpc_int \l__chemformula_tmpa_int } } \tl_replace_once:Nxx \l__chemformula_tmpa_tl { \seq_item:Nn \l__chemformula_tmpa_seq {\l__chemformula_tmpc_int} } { \exp_not:N \charrow { \seq_item:Nn \l__chemformula_tmpa_seq { \l__chemformula_tmpc_int } } } } \tl_set:NV #1 \l__chemformula_tmpa_tl } \cs_generate_variant:Nn \__chemformula_generate_arrows:Nn {NV} \cs_new_protected:Npn \__chemformula_detect_arrows:n #1 { \bool_set_false:N \l__chemformula_is_arrow_bool \prop_map_inline:Nn \l__chemformula_arrows_code_prop { \__chemformula_sanitize:Nn \l__chemformula_tmpa_tl {##1} \tl_if_in:nVT {#1} \l__chemformula_tmpa_tl { \bool_set_true:N \l__chemformula_is_arrow_bool \prop_map_break: } } \bool_if:NT \l__chemformula_is_arrow_bool { \tl_if_in:nnT {#1} {[} { \bool_set_true:N \l__chemformula_arrow_has_options_bool } } } % -------------------------------------------------------------------------- % compound names \cs_new_protected:Npn \__chemformula_name_compound:w { \peek_meaning:NTF ( { \chname } { ! } } \NewDocumentCommand \chname { R(){}R(){} } { \chemformula_chwritebelow:nn {#1} {#2} } \cs_new_protected:Npn \chemformula_chwritebelow:nn #1#2 { \c_math_toggle_token \underset { \bool_if:NF \l__chemformula_name_width_bool { \chemformula_dim_to_width:Nn \l__chemformula_name_dim { \chemformula_name_write:n {#1} } } \parbox { \dim_use:N \l__chemformula_name_dim } { \chemformula_name_write:n {#1} } } { \text { \group_begin: \strut #2 \group_end: } } \c_math_toggle_token } \cs_new_protected:Npn \chemformula_name_write:n #1 { \group_begin: \l__chemformula_name_format_tl {#1} \group_end: } \cs_new_protected:Npn \__chemformula_generate_name:Nn #1#2 { \__chemformula_sanitize:Nn \l__chemformula_tmpa_tl {#2} \tl_if_in:VnT \l__chemformula_tmpa_tl {!} { \tl_replace_all:Nnn \l__chemformula_tmpa_tl {!} { \__chemformula_name_compound:w } } \tl_set:NV #1 \l__chemformula_tmpa_tl } \cs_generate_variant:Nn \__chemformula_generate_name:Nn {NV} \cs_new_protected:Npn \__chemformula_detect_name:n #1 { \bool_set_false:N \l__chemformula_is_name_bool \tl_set:Nn \l__chemformula_tmpa_tl {#1} \tl_if_in:VnT \l__chemformula_tmpa_tl { ! } { \bool_set_true:N \l__chemformula_is_name_bool } } % -------------------------------------------------------------------------- % parsing input % compounds: \cs_new_protected:Npn \chemformula_new_compound_property:nn #1#2 { \prop_if_in:NnTF \l__chemformula_compound_prop {#1} { \msg_error:nnn {chemformula} {new-compound-property} {#1} } { \prop_put:Nnn \l__chemformula_compound_prop {#1} {#2} } } \cs_new_protected:Npn \chemformula_renew_compound_property:nn #1#2 { \prop_if_in:NnTF \l__chemformula_compound_prop {#1} { \prop_put:Nnn \l__chemformula_compound_prop {#1} {#2} } { \msg_error:nnn {chemformula} {renew-compound-property} {#1} } } \cs_new_protected:Npn \chemformula_provide_compound_property:nn #1#2 { \prop_put_if_new:Nnn \l__chemformula_compound_prop {#1} {#2} } \cs_new_protected:Npn \chemformula_declare_compound_property:nn #1#2 { \prop_put:Nnn \l__chemformula_compound_prop {#1} {#2} } \cs_new_protected:Npn \chemformula_remove_compound_property:n #1 { \prop_remove:Nn \l__chemformula_compound_prop {#1} } \NewDocumentCommand \NewChemCompoundProperty {mm} { \chemformula_new_compound_property:nn {#1} {#2} } \NewDocumentCommand \RenewChemCompoundProperty {mm} { \chemformula_renew_compound_property:nn {#1} {#2} } \NewDocumentCommand \ProvideChemCompoundProperty {mm} { \chemformula_provide_compound_property:nn {#1} {#2} } \NewDocumentCommand \DeclareChemCompoundProperty {mm} { \chemformula_declare_compound_property:nn {#1} {#2} } \NewDocumentCommand \RemoveChemCompoundProperty {m} { \chemformula_remove_compound_property:n {#1} } \chemformula_new_compound_property:nn { 0 } { \chemformula_subscript:n { 0 } } \chemformula_new_compound_property:nn { 1 } { \chemformula_subscript:n { 1 } } \chemformula_new_compound_property:nn { 2 } { \chemformula_subscript:n { 2 } } \chemformula_new_compound_property:nn { 3 } { \chemformula_subscript:n { 3 } } \chemformula_new_compound_property:nn { 4 } { \chemformula_subscript:n { 4 } } \chemformula_new_compound_property:nn { 5 } { \chemformula_subscript:n { 5 } } \chemformula_new_compound_property:nn { 6 } { \chemformula_subscript:n { 6 } } \chemformula_new_compound_property:nn { 7 } { \chemformula_subscript:n { 7 } } \chemformula_new_compound_property:nn { 8 } { \chemformula_subscript:n { 8 } } \chemformula_new_compound_property:nn { 9 } { \chemformula_subscript:n { 9 } } \chemformula_new_compound_property:nn { * } { \chemformula_star_adduct: } \chemformula_new_compound_property:nn { . } { \chemformula_adduct: } \chemformula_new_compound_property:nn { - } { \chemformula_single_bond: } \chemformula_new_compound_property:nn { = } { \chemformula_double_bond: } \chemformula_new_compound_property:nn { + } { \chemformula_triple_bond: } \chemformula_new_compound_property:nn { ' } { \chemformula_prime: } % numbers \prop_put:Nnn \l__chemformula_numbers_prop { 0 } { 0 } \prop_put:Nnn \l__chemformula_numbers_prop { 1 } { 1 } \prop_put:Nnn \l__chemformula_numbers_prop { 2 } { 2 } \prop_put:Nnn \l__chemformula_numbers_prop { 3 } { 3 } \prop_put:Nnn \l__chemformula_numbers_prop { 4 } { 4 } \prop_put:Nnn \l__chemformula_numbers_prop { 5 } { 5 } \prop_put:Nnn \l__chemformula_numbers_prop { 6 } { 6 } \prop_put:Nnn \l__chemformula_numbers_prop { 7 } { 7 } \prop_put:Nnn \l__chemformula_numbers_prop { 8 } { 8 } \prop_put:Nnn \l__chemformula_numbers_prop { 9 } { 9 } % behaviour in a charge \prop_put:Nnn \l__chemformula_charge_prop { 0 } { \chemformula_charge_style:n { 0 } } \prop_put:Nnn \l__chemformula_charge_prop { 1 } { \chemformula_charge_style:n { 1 } } \prop_put:Nnn \l__chemformula_charge_prop { 2 } { \chemformula_charge_style:n { 2 } } \prop_put:Nnn \l__chemformula_charge_prop { 3 } { \chemformula_charge_style:n { 3 } } \prop_put:Nnn \l__chemformula_charge_prop { 4 } { \chemformula_charge_style:n { 4 } } \prop_put:Nnn \l__chemformula_charge_prop { 5 } { \chemformula_charge_style:n { 5 } } \prop_put:Nnn \l__chemformula_charge_prop { 6 } { \chemformula_charge_style:n { 6 } } \prop_put:Nnn \l__chemformula_charge_prop { 7 } { \chemformula_charge_style:n { 7 } } \prop_put:Nnn \l__chemformula_charge_prop { 8 } { \chemformula_charge_style:n { 8 } } \prop_put:Nnn \l__chemformula_charge_prop { 9 } { \chemformula_charge_style:n { 9 } } \prop_put:Nnn \l__chemformula_charge_prop { + } { \chemformula_plus: } \prop_put:Nnn \l__chemformula_charge_prop { - } { \chemformula_minus: } \prop_put:Nnn \l__chemformula_charge_prop { . } { \chemformula_radical_or_decimal: } \prop_put:Nnn \l__chemformula_charge_prop { , } { \chemformula_decimal: } % stoichiometric factors \prop_put:Nnn \l__chemformula_stoich_prop { 0 } { 0 } \prop_put:Nnn \l__chemformula_stoich_prop { 1 } { 1 } \prop_put:Nnn \l__chemformula_stoich_prop { 2 } { 2 } \prop_put:Nnn \l__chemformula_stoich_prop { 3 } { 3 } \prop_put:Nnn \l__chemformula_stoich_prop { 4 } { 4 } \prop_put:Nnn \l__chemformula_stoich_prop { 5 } { 5 } \prop_put:Nnn \l__chemformula_stoich_prop { 6 } { 6 } \prop_put:Nnn \l__chemformula_stoich_prop { 7 } { 7 } \prop_put:Nnn \l__chemformula_stoich_prop { 8 } { 8 } \prop_put:Nnn \l__chemformula_stoich_prop { 9 } { 9 } \prop_put:Nnn \l__chemformula_stoich_prop { . } { \chemformula_decimal: } \prop_put:Nnn \l__chemformula_stoich_prop { , } { \chemformula_decimal: } \prop_put:Nnn \l__chemformula_stoich_prop { / } { / } \prop_put:Nnn \l__chemformula_stoich_prop { _ } { _ } \prop_put:Nnn \l__chemformula_stoich_prop { ( } { ( } \prop_put:Nnn \l__chemformula_stoich_prop { ) } { ) } \prop_put:Nnn \l__chemformula_no_stoich_prop { . } { } \prop_put:Nnn \l__chemformula_no_stoich_prop { , } { } \prop_put:Nnn \l__chemformula_no_stoich_prop { / } { } \prop_put:Nnn \l__chemformula_no_stoich_prop { _ } { } \prop_put:Nnn \l__chemformula_no_stoich_prop { ( } { } \prop_put:Nnn \l__chemformula_no_stoich_prop { ) } { } \prop_put:Nnn \l__chemformula_kroegervink_prop { 0 } { \chemformula_charge_style:n { 0 } } \prop_put:Nnn \l__chemformula_kroegervink_prop { 1 } { \chemformula_charge_style:n { 1 } } \prop_put:Nnn \l__chemformula_kroegervink_prop { 2 } { \chemformula_charge_style:n { 2 } } \prop_put:Nnn \l__chemformula_kroegervink_prop { 3 } { \chemformula_charge_style:n { 3 } } \prop_put:Nnn \l__chemformula_kroegervink_prop { 4 } { \chemformula_charge_style:n { 4 } } \prop_put:Nnn \l__chemformula_kroegervink_prop { 5 } { \chemformula_charge_style:n { 5 } } \prop_put:Nnn \l__chemformula_kroegervink_prop { 6 } { \chemformula_charge_style:n { 6 } } \prop_put:Nnn \l__chemformula_kroegervink_prop { 7 } { \chemformula_charge_style:n { 7 } } \prop_put:Nnn \l__chemformula_kroegervink_prop { 8 } { \chemformula_charge_style:n { 8 } } \prop_put:Nnn \l__chemformula_kroegervink_prop { 9 } { \chemformula_charge_style:n { 9 } } \prop_put:Nnn \l__chemformula_kroegervink_prop { + } { \chemformula_plus: } \prop_put:Nnn \l__chemformula_kroegervink_prop { - } { \chemformula_minus: } \prop_put:Nnn \l__chemformula_kroegervink_prop { . } { \chemformula_radical_or_decimal: } \prop_put:Nnn \l__chemformula_kroegervink_prop { , } { \chemformula_decimal: } \prop_put:Nnn \l__chemformula_kroegervink_prop { ' } { \chemformula_kroegervink_negative: } \prop_put:Nnn \l__chemformula_kroegervink_prop { x } { \chemformula_kroegervink_neutral: } \prop_put:Nnn \l__chemformula_kroegervink_prop { * } { \chemformula_kroegervink_positive: } \prop_put:Nnn \l__chemformula_kroegervink_prop { . } { \chemformula_kroegervink_positive: } % -------------------------------------------------------------------------- % bonds: \cs_new_protected:Npn \chemformula@bondlength { \l__chemformula_bond_dim } \cs_new_protected:Npn \chemformula_single_bond: { \chemformula_bond:n {single} } \cs_new_protected:Npn \chemformula_double_bond: { \chemformula_bond:n {double} } \cs_new_protected:Npn \chemformula_triple_bond: { \chemformula_bond:n {triple} } \cs_new_protected:Npn \chemformula_bond:n #1 { \chemformula_skip_nobreak:N \l__chemformula_bond_space_dim \hbox_set:Nn \l__chemformula_tmpa_box {K} \dim_set:Nn \l__chemformula_tmpa_dim { \box_ht:N \l__chemformula_tmpa_box } \chemformula_tikz:nn { inner~sep = 0pt , outer~sep = 0pt , text~height = \l__chemformula_tmpa_dim , baseline = (chemformula-bond-ground.base) } { \coordinate (chemformula-bond-ground) at (0pt,0pt) ; \draw (chemformula-bond-ground) ++ (0pt,.5\l__chemformula_tmpa_dim) coordinate (chemformula-bond-start) ; \draw (chemformula-bond-start) ++(\l__chemformula_bond_dim ,0pt) coordinate (chemformula-bond-end) ; \tl_if_blank:nTF {#1} { \__chemformula_bond_draw:n {single} } { \__chemformula_bond_draw:n {#1} } } \chemformula_skip_nobreak_penalty:NV \l__chemformula_bond_space_dim \l__chemformula_bond_penalty_tl } \cs_new_protected:Npn \__chemformula_bond_draw:n #1 { \__chemformula_reset:Nn \l__chemformula_tmpa_tl {#1} \prop_item:NV \l__chemformula_bonds_prop \l__chemformula_tmpa_tl } \cs_new_protected:Npn \chemformula_declare_bond:nn #1#2 { \cs_if_exist:cTF { chemformula_bond_type_#1: } { \cs_set:cpn { chemformula_bond_type_#1: } {} } { \cs_new_protected:cpn { chemformula_bond_type_#1: } {} } \prop_put:Nnn \l__chemformula_bonds_prop {#1} {#2} } \cs_new_protected:Npn \chemformula_new_bond:nn #1#2 { \cs_if_exist:cTF { chemformula_bond_type_#1: } { \msg_error:nnn {chemformula} {new-bond} {#1} } { \chemformula_declare_bond:nn {#1} {#2} } } \cs_new_protected:Npn \chemformula_provide_bond:nn #1#2 { \cs_if_exist:cF { chemformula_bond_type_#1: } { \chemformula_declare_bond:nn {#1} {#2} } } \cs_new_protected:Npn \chemformula_renew_bond:nn #1#2 { \cs_if_exist:cTF { chemformula_bond_type_#1: } { \chemformula_declare_bond:nn {#1} {#2} } { \msg_error:nnn {chemformula} {renew-bond} {#1} } } \cs_new_protected:Npn \chemformula_new_bond_alias:nn #1#2 { \cs_if_exist:cTF { chemformula_bond_type_#2: } { \cs_if_exist:cTF { chemformula_bond_type_#1: } { \msg_error:nnn {chemformula} {new-bond} {#1} } { \cs_new_protected:cpn { chemformula_bond_type_#1: } {} } \prop_get:NnN \l__chemformula_bonds_prop {#2} \l__chemformula_tmpa_tl \prop_put:Nno \l__chemformula_bonds_prop {#1} { \l__chemformula_tmpa_tl } } { \msg_error:nnnn {chemformula} {bond-alias} {#1} {#2} } } \cs_new_protected:Npn \chemformula_declare_bond_alias:nn #1#2 { \cs_if_exist:cTF { chemformula_bond_type_#2: } { \cs_if_exist:cF { chemformula_bond_type_#1: } { \cs_new_protected:cpn { chemformula_bond_type_#1: } {} } \prop_get:NnN \l__chemformula_bonds_prop {#2} \l__chemformula_tmpa_tl \prop_put:Nno \l__chemformula_bonds_prop {#1} { \l__chemformula_tmpa_tl } } { \msg_error:nnnn {chemformula} {bond-alias} {#1} {#2} } } \cs_new_protected:Npn \chemformula_show_bond:n #1 { \prop_get:NnN \l__chemformula_bonds_prop {#1} \l__chemformula_tmpa_tl \tl_to_str:N \l__chemformula_tmpa_tl } \NewDocumentCommand \NewChemBond {mm} { \chemformula_new_bond:nn {#1} {#2} } \NewDocumentCommand \ProvideChemBond {mm} { \chemformula_provide_bond:nn {#1} {#2} } \NewDocumentCommand \DeclareChemBond {mm} { \chemformula_declare_bond:nn {#1} {#2} } \NewDocumentCommand \RenewChemBond {mm} { \chemformula_renew_bond:nn {#1} {#2} } \NewDocumentCommand \NewChemBondAlias {mm} { \chemformula_new_bond_alias:nn {#1} {#2} } \NewDocumentCommand \DeclareChemBondAlias {mm} { \chemformula_declare_bond_alias:nn {#1} {#2} } \NewDocumentCommand \ShowChemBond {m} { \chemformula_show_bond:n {#1} } \NewDocumentCommand \bond {m} { \chemformula_bond:n {#1} } % now let's declare some default bonds: \NewChemBond {single} { \draw[chembond] (chemformula-bond-start) -- (chemformula-bond-end) ; } \NewChemBondAlias {normal} {single} \NewChemBondAlias {sb} {single} \NewChemBond {semisingle} { \draw[chembond,densely~dotted] (chemformula-bond-start) -- (chemformula-bond-end) ; } \NewChemBondAlias {dotted} {semisingle} \NewChemBond {double} { \foreach \i in {-.0858em,.0858em}{ \draw[chembond] ([yshift=\i]chemformula-bond-start) -- ([yshift=\i]chemformula-bond-end) ; } } \NewChemBondAlias {db} {double} \NewChemBond {semidouble} { \foreach \i/\style in {-.0858em/,.0858em/densely~dotted}{ \draw[chembond,\style] ([yshift=\i]chemformula-bond-start) -- ([yshift=\i]chemformula-bond-end) ; } } \NewChemBondAlias {deloc} {semidouble} \NewChemBond {triple} { \foreach \i in {-.1287em,0em,.1287em}{ \draw[chembond] ([yshift=\i]chemformula-bond-start) -- ([yshift=\i]chemformula-bond-end) ; } } \NewChemBondAlias {tp} {triple} \NewChemBond {semitriple} { \foreach \i/\style in {-.1287em/,0em/,.1287em/densely~dotted}{ \draw[chembond,\style] ([yshift=\i]chemformula-bond-start) -- ([yshift=\i]chemformula-bond-end) ; } } \NewChemBondAlias {tdeloc} {semitriple} \NewChemBond {coordright} { \draw[chembond,Butt~Cap->] (chemformula-bond-start) -- (chemformula-bond-end) ; } \NewChemBondAlias {co>} {coordright} \NewChemBond {coordleft} { \draw[chembond,<-Butt~Cap] (chemformula-bond-start) -- (chemformula-bond-end) ; } \NewChemBondAlias { 0pt } { \chemformula_skip_nobreak:N \l__chemformula_tmpa_dim } } \group_end: % clean up \bool_set_false:N \l__chemformula_is_isotope_bool \tl_clear:N \l__chemformula_subscript_tl \tl_clear:N \l__chemformula_superscript_tl } % -------------------------------------------------------------------------- % read the input \cs_new_protected:Npn \__chemformula_input:n #1 { \__chemformula_save_catcodes: \__chemformula_sanitize:Nn \l__chemformula_chemformula_tmpa_tl {#1} \__chemformula_input_escape_text:V \l__chemformula_chemformula_tmpa_tl \__chemformula_input_escape_math:n {#1} \__chemformula_input_stoich:n {#1} \__chemformula_clean_chemformula:V \l__chemformula_chemformula_tmpa_tl \__chemformula_input_compound:NV \l__chemformula_input_tl \l__chemformula_chemformula_tmpa_tl \__chemformula_input_arrow:n {#1} \__chemformula_input_name:n {#1} \__chemformula_input_addition:n {#1} \__chemformula_input_symbol:n {#1} } % -------------------------------------------------------------------------- % set options for next compound: \cs_new_protected:Npn \__chemformula_input_options:n #1 { \tl_set_rescan:Nnn \l__chemformula_tmpa_tl {} {#1} \tl_set:Ne \l__chemformula_tmpb_tl { \tl_tail:V \l__chemformula_tmpa_tl } \tl_set:Ne \l__chemformula_tmpa_tl { \tl_head:V \l__chemformula_tmpa_tl } \str_if_eq:VnTF \l__chemformula_tmpa_tl {@} { \bool_set_false:N \l__chemformula_options_bool \bool_set_true:N \l__chemformula_is_option_bool \exp_last_unbraced:Nno \tl_set:Nn \l__chemformula_internal_options_tl { \l__chemformula_tmpb_tl } } { \bool_set_false:N \l__chemformula_is_option_bool } } % -------------------------------------------------------------------------- % input stoichiometric factors \cs_new_protected:Npn \chemformula_decimal: { { \l__chemformula_decimal_output_tl } } \cs_new_protected:Npn \__chemformula_input_stoich:n #1 { \bool_set_true:N \l__chemformula_stoich_bool % the factor consists only of a parenthesis or a decimal marcer: \bool_set_true:N \l__chemformula_no_stoich_bool \tl_map_inline:nn {#1} { \prop_if_in:NnF \l__chemformula_no_stoich_prop {##1} { \bool_set_false:N \l__chemformula_no_stoich_bool \tl_map_break: } } \bool_if:NF \l__chemformula_no_stoich_bool { \tl_map_inline:nn {#1} { \prop_get:NnNTF \l__chemformula_stoich_prop {##1} \l__chemformula_tmpa_tl { \bool_if:NT \l__chemformula_stoich_bool { \tl_put_right:NV \l__chemformula_stoich_tl \l__chemformula_tmpa_tl } } { \bool_set_false:N \l__chemformula_stoich_bool \tl_map_break: } } } \bool_if:NTF \l__chemformula_stoich_bool { \tl_if_blank:VF \l__chemformula_stoich_tl { \tl_put_left:Nn \l__chemformula_stoich_tl { \q_mark } \__chemformula_sanitize:NV \l__chemformula_stoich_tl \l__chemformula_stoich_tl \chemformula_print_stoich:V \l__chemformula_stoich_tl } } { \tl_clear:N \l__chemformula_stoich_tl } } \cs_new_protected:Npn \chemformula_bm:n #1 {#1} \cs_new_protected:Npn \chemformula_print_stoich:n #1 { \chemformula_parse_stoich:n {#1} } \cs_generate_variant:Nn \chemformula_print_stoich:n {V} \cs_new_protected:Npn \__chemformula_print_stoich:n #1 { { \l__chemformula_stoich_format_tl {#1} } } \cs_new_protected:Npn \chemformula_parse_stoich:n #1 { \__chemformula_parse_stoich:w #1 \q_nil } \NewDocumentCommand \chstoich {m} { \group_begin: \__chemformula_input_stoich:n {#1} \l__chemformula_input_tl \group_end: } \cs_new_protected:Npn \__chemformula_parse_stoich:w \q_mark #1 \q_nil { \__chemformula_bool_set_if_first_last:Nnnn \l__chemformula_stoich_is_iupac_bool {#1} { ( } { ) } \bool_if:NTF \l__chemformula_stoich_is_iupac_bool { \__chemformula_parse_stoich_iupac:n {#1} } { \__chemformula_parse_stoich_regular:n {#1} } } \DeclareInstance { xfrac } { chemformula-text-frac } { text } { slash-left-kern = -.15em , numerator-top-sep = 0pt , slash-right-kern = -.15em } \cs_new_protected:Npn \__chemformula_parse_stoich_regular:n #1 { \tl_if_in:nnTF {#1} { / } { \__chemformula_parse_stoich_frac:n {#1} } { \__chemformula_parse_stoich_decimal:n {#1} } } \cs_new_protected:Npn \__chemformula_parse_stoich_decimal:n #1 { % get head: \tl_set:Nx \l__chemformula_tmpa_tl { \tl_head:n {#1} } \tl_set:Nn \l__chemformula_tmpb_tl { \chemformula_decimal: } % check if stoich starts with decimal-marker and add leading 0 if so: \tl_if_eq:NNTF \l__chemformula_tmpa_tl \l__chemformula_tmpb_tl { \tl_put_right:Nn \l__chemformula_input_tl { \__chemformula_print_stoich:n {0#1} } } { \tl_put_right:Nn \l__chemformula_input_tl { \__chemformula_print_stoich:n {#1} } } } \cs_new_protected:Npn \__chemformula_parse_stoich_frac:n #1 { \tl_if_in:nnTF {#1} { _ } { \__chemformula_parse_stoich_misc_frac:w #1 \q_nil } { \__chemformula_parse_stoich_frac:w #1 \q_nil } } \cs_new_protected:Npn \__chemformula_parse_stoich_frac:w #1/#2 \q_nil { \tl_put_right:Nn \l__chemformula_input_tl { \__chemformula_print_stoich:n { \__chemformula_frac:nn {#1} {#2} } } } \cs_new_protected:Npn \__chemformula_parse_stoich_misc_frac:w #1_#2/#3 \q_nil { \tl_put_right:Nn \l__chemformula_input_tl { \__chemformula_print_stoich:n { \__chemformula_misc_frac:nnn {#1} {#2} {#3} } } } \cs_new_protected:Npn \__chemformula_parse_stoich_iupac:n #1 { \bool_if:NTF \l__chemformula_stoich_parse_iupac_bool { \__chemformula_parse_stoich_iupac:w #1 \q_nil } { \tl_put_right:Nn \l__chemformula_input_tl { \__chemformula_print_stoich:n {#1} } } } \cs_new_protected:Npn \__chemformula_parse_stoich_iupac:w (#1) \q_nil { \tl_put_right:Nn \l__chemformula_input_tl { ( } \__chemformula_parse_stoich_regular:n {#1} \tl_put_right:Nn \l__chemformula_input_tl { ) } } \cs_new_eq:NN \chemformula_math_frac:nn \frac \cs_new_protected:Npn \__chemformula_frac:nn #1#2 { \bool_if:NT \l__chemformula_xfrac_bool { \sfrac[chemformula-text-frac]{#1}{#2} } \bool_if:NT \l__chemformula_nicefrac_bool { \nicefrac{#1}{#2} } \bool_if:NT \l__chemformula_mathfrac_bool { \c_math_toggle_token \chemformula_math_frac:nn { \text {#1} } { \text {#2} } \c_math_toggle_token } } \cs_new_protected:Npn \__chemformula_misc_frac:nnn #1#2#3 { \bool_if:NT \l__chemformula_xfrac_bool { #1\sfrac[chemformula-text-frac]{#2}{#3} } \bool_if:NT \l__chemformula_nicefrac_bool { #1\nicefrac{#2}{#3} } \bool_if:NT \l__chemformula_mathfrac_bool { #1 \c_math_toggle_token \chemformula_math_frac:nn { \text {#2} } { \text {#3} } \c_math_toggle_token } } % -------------------------------------------------------------------------- \cs_new_protected:Npn \chemformula_atom: { \mode_if_math:F { \l__chemformula_atom_format_tl } } % input compounds \cs_new_protected:Npn \__chemformula_input_compound:Nn #1#2 { \tl_if_blank:VTF \l__chemformula_stoich_tl { \__chemformula_detect_addition_symbols:n {#2} \__chemformula_detect_symbols:n {#2} \__chemformula_detect_arrows:n {#2} \__chemformula_detect_name:n {#2} \__chemformula_input_options:n {#2} \bool_if:NT \l__chemformula_is_option_bool { \bool_set_true:N \l__chemformula_options_bool \tl_put_right:Ne #1 { \group_begin: % open group \keys_set:nn {chemformula} { \exp_not:V \l__chemformula_internal_options_tl } \chemformula_atom: } \tl_clear:N \l__chemformula_internal_options_tl } \bool_lazy_any:nF { { \l__chemformula_is_option_bool } { \l__chemformula_is_addition_symbol_bool } { \l__chemformula_is_symbol_bool } { \l__chemformula_is_arrow_bool } { \l__chemformula_is_name_bool } { \l__chemformula_first_last_text_bool } { \l__chemformula_first_last_math_bool } } { \chemformula_atom: \__chemformula_input_compound_no_check:Nn #1 {#2} \bool_if:NT \l__chemformula_options_bool { \tl_put_right:Nn #1 { % end group \group_end: } \bool_set_false:N \l__chemformula_options_bool } } } { \tl_put_right:Nn #1 { \chemformula_skip_nobreak:N \l__chemformula_stoich_space_skip } \tl_clear:N \l__chemformula_stoich_tl } } \cs_generate_variant:Nn \__chemformula_input_compound:Nn {NV} \cs_new_protected:Npn \chemformula_font_inner: { \bool_if:NT \l__chemformula_fss_bool { \bool_if:NT \l__chemformula_fss_family_bool { \fontfamily { \l__chemformula_font_family_tl } } \bool_if:NT \l__chemformula_fss_series_bool { \fontseries { \l__chemformula_font_series_tl } } \bool_if:NT \l__chemformula_fss_shape_bool { \fontshape { \l__chemformula_font_shape_tl } } \selectfont } \bool_if:NT \l__chemformula_fontspec_bool { \cs_if_exist_use:N \chemformula_font: } \tl_use:N \l__chemformula_format_tl \tl_if_eq:onTF { \f@series } {bx} { \cs_set_eq:NN \chemformula_bm:n \bm } { \cs_set:Nn \chemformula_bm:n {##1} } } % \cs_new_protected:Npn \chemformula_font: {} \cs_new_protected:Npn \__chemformula_fontspec:n #1 { \tl_if_in:nnTF {#1} {[} { \__chemformula_fontspec_aux:w #1 \q_stop } { \__chemformula_fontspec_aux:w [] #1 \q_stop } } \cs_new_protected:Npn \__chemformula_fontspec_aux:w [#1]#2 \q_stop { \newfontfamily \chemformula_font: [#1] {#2} } \cs_new_protected:Npn \__chemformula_prepare_output:Nn #1#2 { \tl_set_rescan:NnV #1 { \__chemformula_restore: #2 % we /need/ those: \char_set_catcode_letter:N \@ \char_set_catcode_letter:N \_ \char_set_catcode_letter:N \: } #1 } \cs_generate_variant:Nn \__chemformula_prepare_output:Nn {NV} \cs_new_protected:Npn \__chemformula_reset:Nn #1#2 { \tl_set_rescan:Nnn #1 { \__chemformula_restore: } {#2} } \cs_generate_variant:Nn \__chemformula_reset:Nn {NV} \prg_new_protected_conditional:Npnn \__chemformula_if_only_parens:n #1 {T,F,TF} { \bool_set_true:N \l__chemformula_tmpa_bool \tl_map_inline:nn {#1} { \str_case:nnF {##1} { {[} { } {]} { } {(} { } {)} { } } { \bool_set_false:N \l__chemformula_tmpa_bool } } \bool_if:NTF \l__chemformula_tmpa_bool { \prg_return_true: } { \prg_return_false: } } % if the compound starts with a number or a sub- or superscript then it is an % isotope: \cs_new_protected:Npn \__chemformula_check_for_isotope:N #1 { \tl_if_eq:xnT { \tl_head:V #1 } {^} { \tl_put_left:Nn #1 { \bool_set_true:N \l__chemformula_is_isotope_bool } } \tl_if_eq:xnT { \tl_head:V #1 } {_} { \tl_put_left:Nn #1 { \bool_set_true:N \l__chemformula_is_isotope_bool } } \prop_if_in:NxT \l__chemformula_numbers_prop { \tl_head:V #1 } { \tl_put_left:Nn #1 { \bool_set_true:N \l__chemformula_is_isotope_bool } } } \cs_new_protected:Npn \__chemformula_prepare_sub_and_superscripts:N #1 { \tl_if_in:VnT #1 {^} { \tl_replace_all:Nnn #1 {^} { \chemformula_superscript:n } } \tl_if_in:VnT #1 {_} { \tl_replace_all:Nnn #1 {_} { \chemformula_subscript:n } } } % #1: tl that holds compound % #2: code for each token \cs_new_protected:Npn \__chemformula_compound_map_inline:Nn #1#2 { % ##1: token % ##2: plus case % ##3: minus case % ##4: else case \cs_set_protected:Npn \__chemformula_if_last_token_charge:nnnF ##1##2##3##4 { \int_compare:nTF { \l__chemformula_count_tokens_int = \tl_count:N #1 } { \tl_if_eq:nnTF {##1} {+} {##2} { \tl_if_eq:nnTF {##1} {-} {##3} {##4} } } {##4} } \int_zero:N \l__chemformula_count_tokens_int \tl_map_inline:Nn #1 { \int_incr:N \l__chemformula_count_tokens_int % do we end with a charge? #2 } } % this is the chemical formula: % #1: tl var to safe processed formula in % #2: formula \cs_new_protected:Npn \__chemformula_input_compound_no_check:Nn #1#2 { \__chemformula_if_only_parens:nTF {#2} { \tl_put_right:Nn #1 {#2} } { \__chemformula_sanitize:Nn \l__chemformula_tmpa_tl {#2} % let's see if the compound starts with a sub- or superscript - if yes % this is an isotope: \__chemformula_check_for_isotope:N \l__chemformula_tmpa_tl % preparations for sub- and superscripting: \__chemformula_prepare_sub_and_superscripts:N \l__chemformula_tmpa_tl \__chemformula_compound_map_inline:Nn \l__chemformula_tmpa_tl { % do we end with a charge? \__chemformula_if_last_token_charge:nnnF {##1} { \tl_put_right:Nn #1 { \chemformula_superscript:n { \chemformula_plus: } } } { \tl_put_right:Nn #1 { \chemformula_superscript:n { \chemformula_minus: } } } { \prop_get:NnNTF \l__chemformula_compound_prop {##1} \l__chemformula_tmpb_tl { \tl_put_right:NV #1 \l__chemformula_tmpb_tl } { \token_if_letter:NTF ##1 { \tl_put_right:Nn #1 { ##1 } } { \tl_put_right:Nn #1 {##1} } } } } % if Kroeger-Vink notation is active: \bool_if:NT \l__chemformula_kroegervink_bool { \tl_replace_all:Nnn #1 { \chemformula_prime: } { \chemformula_superscript:n { \chemformula_prime: } } } } \tl_clear:N \l__chemformula_tmpa_tl } \cs_generate_variant:Nn \__chemformula_input_compound_no_check:Nn {NV} % -------------------------------------------------------------------------- % clean up chemformula commands: \cs_new_protected:Npn \__chemformula_clean_chemformula:n #1 { \cs_set:Nn \chemformula_text:n { \mode_if_math:TF { \text {##1} } {##1} } \cs_set:Npn \chemformula_xspace: {} } \cs_generate_variant:Nn \__chemformula_clean_chemformula:n {V} % -------------------------------------------------------------------------- % input "and" sign \skip_set:Nn \l__chemformula_additions_symbol_space_skip {.3em plus .1em minus .1em} \tl_set:Nn \l__chemformula_additions_symbol_penalty_tl {700} % #1: name % #2: input symbol % #3: output symbol \cs_new_protected:Npn \chemformula_new_addition_symbol:nnn #1#2#3 { \prop_put:Nnn \l__chemformula_addition_symbol_prop {#1} {#2} \skip_zero_new:c {l__chemformula_#1_space_skip} \skip_set:cV {l__chemformula_#1_space_skip} \l__chemformula_additions_symbol_space_skip \tl_clear_new:c {l__chemformula_#1_penalty_tl} \tl_set:cV {l__chemformula_#1_penalty_tl} \l__chemformula_additions_symbol_penalty_tl \tl_clear_new:c {l__chemformula_#1_output_tl} \tl_set:cn {l__chemformula_#1_output_tl} {#3} \keys_define:nn {chemformula} { #1-space .skip_set:c = {l__chemformula_#1_space_skip} , #1-penalty .tl_set:c = {l__chemformula_#1_penalty_tl} , #1-output-symbol .tl_set:c = {l__chemformula_#1_output_tl} } } % #1: name \cs_new_protected:Npn \chemformula_get_addition_symbol:n #1 { \chemformula_skip_nobreak:c {l__chemformula_#1_space_skip} \tl_use:c {l__chemformula_#1_output_tl} \chemformula_skip_nobreak_penalty:cn {l__chemformula_#1_space_skip} { \use:c {l__chemformula_#1_penalty_tl} } } % #1: name \cs_new_protected:Npn \__chemformula_input_addition:n #1 { \prop_map_inline:Nn \l__chemformula_addition_symbol_prop { \str_if_eq:nnT {#1} {##2} { \tl_put_right:Nn \l__chemformula_input_tl { \chemformula_get_addition_symbol:n {##1} } \prop_map_break: } } } % #1: input string \cs_new_protected:Npn \__chemformula_detect_addition_symbols:n #1 { \bool_set_false:N \l__chemformula_is_addition_symbol_bool \chemformula_is_addition_symbol_input:nT {#1} { \bool_set_true:N \l__chemformula_is_addition_symbol_bool } } \prg_new_protected_conditional:Npnn \chemformula_is_addition_symbol_input:n #1 {T,F,TF} { \bool_set_false:N \l__chemformula_tmpa_bool \prop_map_inline:Nn \l__chemformula_addition_symbol_prop { \str_if_eq:nnT {#1} {##2} { \bool_set_true:N \l__chemformula_tmpa_bool \prop_map_break: } } \bool_if:NTF \l__chemformula_tmpa_bool { \prg_return_true: } { \prg_return_false: } } \prg_new_conditional:Npnn \chemformula_is_addition_symbol_name:n #1 {T,F,TF} { \prop_if_in:NnTF \l__chemformula_addition_symbol_prop {#1} { \prg_return_true: } { \prg_return_false: } } \NewDocumentCommand \NewChemAdditionSymbol {mmm} { \chemformula_is_addition_symbol_name:nT {#1} { \msg_error:nnnn {chemformula} {new-addition-symbol} {#1} {#2} } \chemformula_is_addition_symbol_input:nT {#2} { \msg_error:nnnn {chemformula} {new-addition-symbol} {#1} {#2} } \chemformula_new_addition_symbol:nnn {#1} {#2} {#3} } \NewDocumentCommand \ProvideChemAdditionSymbol {mmm} { \chemformula_is_addition_symbol_name:nF {#1} { \chemformula_is_addition_symbol_input:nF {#2} { \chemformula_new_addition_symbol:nnn {#1} {#2} {#3} } } } \NewDocumentCommand \RenewChemAdditionSymbol {mmm} { \chemformula_is_addition_symbol_name:nF {#1} { \msg_error:nnnn {chemformula} {renew-addition-symbol} {#1} {#2} } \chemformula_is_addition_symbol_input:nF {#2} { \msg_error:nnnn {chemformula} {renew-addition-symbol} {#1} {#2} } \chemformula_new_addition_symbol:nnn {#1} {#2} {#3} } \NewDocumentCommand \DeclareChemAdditionSymbol {mmm} { \chemformula_new_addition_symbol:nnn {#1} {#2} {#3} } % default addition symbols: \NewChemAdditionSymbol {plus} {+} {+} \NewChemAdditionSymbol {minus} {-} {$-$} % -------------------------------------------------------------------------- % input escaping gas and precipitate \cs_new_protected:Npn \__chemformula_input_symbol:n #1 { \prop_map_inline:Nn \l__chemformula_symbols_prop { \str_if_eq:nnT {#1} {##1} { \tl_put_right:Nn \l__chemformula_input_tl {##2} \prop_map_break: } } \bool_set_false:N \l__chemformula_is_symbol_bool } \cs_new_protected:Npn \chemformula_new_symbol:nn #1#2 { \prop_put:Nnn \l__chemformula_symbols_prop {#1} {#2} } \cs_new_protected:Npn \__chemformula_detect_symbols:n #1 { \bool_set_false:N \l__chemformula_is_symbol_bool \chemformula_is_symbol:nT {#1} { \bool_set_true:N \l__chemformula_is_symbol_bool } } \prg_new_conditional:Npnn \chemformula_is_symbol:n #1 {T,F,TF} { \prop_if_in:NnTF \l__chemformula_symbols_prop {#1} { \prg_return_true: } { \prg_return_false: } } \NewDocumentCommand \NewChemSymbol {mm} { \chemformula_is_symbol:nTF {#1} { \msg_error:nnn {chemformula} {new-symbol} {#1} } { \chemformula_new_symbol:nn {#1} {#2} } } \NewDocumentCommand \ProvideChemSymbol {mm} { \chemformula_is_symbol:nF {#1} { \chemformula_new_symbol:nn {#1} {#2} } } \NewDocumentCommand \RenewChemSymbol {mm} { \chemformula_is_symbol:nTF {#1} { \chemformula_new_symbol:nn {#1} {#2} } { \msg_error:nnn {chemformula} {renew-symbol} {#1} } } \NewDocumentCommand \DeclareChemSymbol {mm} { \chemformula_new_symbol:nn {#1} {#2} } \NewChemSymbol {v} {$\downarrow$} \NewChemSymbol {^} {$\uparrow$} % -------------------------------------------------------------------------- % input arrow \cs_new_protected:Npn \__chemformula_input_arrow:n #1 { \bool_lazy_all:nT { { \l__chemformula_is_arrow_bool } { !\l__chemformula_first_last_text_bool } { !\l__chemformula_first_last_math_bool } } { \__chemformula_generate_arrows:Nn \l__chemformula_tmpa_tl {#1} \tl_put_right:NV \l__chemformula_input_tl \l__chemformula_tmpa_tl } \bool_set_false:N \l__chemformula_is_arrow_bool } \cs_generate_variant:Nn \__chemformula_input_arrow:n {o,V} % -------------------------------------------------------------------------- % input compound name \cs_new_protected:Npn \__chemformula_input_name:n #1 { \bool_lazy_all:nT { { \l__chemformula_is_name_bool } { !\l__chemformula_first_last_text_bool } { !\l__chemformula_first_last_math_bool } } { \__chemformula_generate_name:Nn \l__chemformula_tmpa_tl {#1} \tl_put_right:NV \l__chemformula_input_tl \l__chemformula_tmpa_tl } \bool_set_false:N \l__chemformula_is_name_bool } % -------------------------------------------------------------------------- % input escaped text % #1: #2: #3: #4: \cs_new_protected:Npn \__chemformula_bool_set_if_first_last:Nnnn #1#2#3#4 { \int_zero:N \l__chemformula_tmpa_int \int_zero:N \l__chemformula_tmpb_int \int_set:Nn \l__chemformula_tmpa_int { \tl_count:n {#2} } \tl_map_inline:nn {#2} { \int_incr:N \l__chemformula_tmpb_int \int_compare:nT { \l__chemformula_tmpb_int = 1 } { \tl_if_eq:nnT {##1} {#3} { \bool_set_true:N #1 } } \int_compare:nT { \l__chemformula_tmpb_int = \l__chemformula_tmpa_int } { \tl_if_eq:nnF {##1} {#4} { \bool_set_false:N #1 } } } } \cs_new_protected:Npn \__chemformula_input_escape_text:n #1 { \__chemformula_first_last_text:n {#1} \bool_if:NT \l__chemformula_first_last_double_bool { \bool_set_true:N \l__chemformula_first_last_text_bool \__chemformula_read_escape_double:w #1 \q_nil } \bool_if:NT \l__chemformula_first_last_single_bool { \bool_set_true:N \l__chemformula_first_last_text_bool \__chemformula_read_escape_single:w #1 \q_nil } } \cs_generate_variant:Nn \__chemformula_input_escape_text:n {V} \cs_new_protected:Npn \__chemformula_read_escape_text:n #1 { \tl_set_rescan:Nnn \l__chemformula_tmpa_tl { % \char_set_catcode_letter:N \_ % \char_set_catcode_other:N \: \char_set_catcode_space:N \~ } {#1} \tl_replace_all:Nnn \l__chemformula_tmpa_tl { \_ } { chemformulaplaceholder } \tl_replace_all:Nnn \l__chemformula_tmpa_tl {_} { \sb } \tl_replace_all:Nnn \l__chemformula_tmpa_tl { chemformulaplaceholder } { \_ } \tl_put_right:NV \l__chemformula_input_tl \l__chemformula_tmpa_tl } \cs_new_protected:Npn \__chemformula_read_escape_double:w "#1" \q_nil { \__chemformula_read_escape_text:n {#1} } \cs_new_protected:Npn \__chemformula_read_escape_single:w '#1' \q_nil { \__chemformula_read_escape_text:n {#1} } \cs_new_protected:Npn \__chemformula_first_last_text:n #1 { \bool_set_false:N \l__chemformula_first_last_double_bool \bool_set_false:N \l__chemformula_first_last_single_bool \bool_set_false:N \l__chemformula_first_last_text_bool \__chemformula_bool_set_if_first_last:Nnnn \l__chemformula_first_last_double_bool {#1} { " } { " } \bool_if:NF \l__chemformula_first_last_double_bool { \__chemformula_bool_set_if_first_last:Nnnn \l__chemformula_first_last_single_bool {#1} { ' } { ' } } } % -------------------------------------------------------------------------- % input escaped math \cs_new_protected:Npn \__chemformula_input_escape_math:n #1 { \__chemformula_first_last_math:n {#1} \bool_if:NT \l__chemformula_first_last_dollar_bool { \bool_set_true:N \l__chemformula_first_last_math_bool \__chemformula_read_escape_dollar:w #1 \q_nil } \bool_if:NT \l__chemformula_first_last_mathbraces_bool { \bool_set_true:N \l__chemformula_first_last_math_bool \__chemformula_read_escape_mathbraces:w #1 \q_nil } } \cs_new_protected:Npn \__chemformula_read_escape_math:n #1 { \tl_set_rescan:Nnn \l__chemformula_tmpa_tl { \char_set_catcode_letter:N \_ \char_set_catcode_letter:N \: } { \c_math_toggle_token #1 \c_math_toggle_token } \tl_replace_all:Nnn \l__chemformula_tmpa_tl {_} { \sb } \tl_put_left:Nn \l__chemformula_tmpa_tl { \group_begin: } \tl_put_right:Nn \l__chemformula_tmpa_tl { \group_end: } \tl_put_right:NV \l__chemformula_input_tl \l__chemformula_tmpa_tl \tl_put_right:Nn \l__chemformula_input_tl { \chemformula_skip_nobreak:N \l__chemformula_math_space_skip } } \cs_new_protected:Npn \__chemformula_read_escape_dollar:w $#1$ \q_nil { \__chemformula_read_escape_math:n {#1} } \cs_new_protected:Npn \__chemformula_read_escape_mathbraces:w \(#1\) \q_nil { \__chemformula_read_escape_math:n {#1} } \cs_new_protected:Npn \__chemformula_first_last_math:n #1 { \bool_set_false:N \l__chemformula_first_last_math_bool \bool_set_false:N \l__chemformula_first_last_dollar_bool \bool_set_false:N \l__chemformula_first_last_mathbraces_bool \__chemformula_bool_set_if_first_last:Nnnn \l__chemformula_first_last_dollar_bool {#1} { $ } { $ } \bool_if:NF \l__chemformula_first_last_dollar_bool { \__chemformula_bool_set_if_first_last:Nnnn \l__chemformula_first_last_mathbraces_bool {#1} { \( } { \) } } } % -------------------------------------------------------------------------- % customization of output other than arrows \keys_define:nn {chemformula} { circled .choice: , circled / none .code:n = { \bool_set_false:N \l_chemformula_formal_charges_bool } , circled / formal .code:n = { \bool_set_false:N \l_chemformula_formal_charges_bool } , circled / all .code:n = { \bool_set_true:N \l_chemformula_formal_charges_bool } , circled .default:n = all , circletype .choice: , circletype / math .code:n = { \bool_set_false:N \l_chemformula_formal_chem_bool } , circletype / chem .code:n = { \bool_set_true:N \l_chemformula_formal_chem_bool } , circletype .default:n = chem , charge-hshift .code:n = \tl_if_eq:nnTF {#1} { full } { \bool_set_true:N \l__chemformula_charge_full_shift_bool } { \bool_set_false:N \l__chemformula_charge_full_shift_bool \dim_set:Nn \l__chemformula_charge_shift_dim {#1} } , math-scripts .bool_set:N = \l__chemformula_subsuper_use_math_bool , math-scripts .initial:n = false , charge-hshift .default:n = .25em , charge-vshift .tl_set:N = \l__chemformula_superscript_shift_additional_tl , charge-style .choice: , charge-style / text .code:n = \bool_set_false:N \l__chemformula_charge_style_math_bool , charge-style / math .code:n = \bool_set_true:N \l__chemformula_charge_style_math_bool , subscript-vshift .tl_set:N = \l__chemformula_subscript_shift_additional_tl , subscript-vshift .default:n = 0pt , subscript-style .choice: , subscript-style / text .code:n = \bool_set_false:N \l__chemformula_number_style_math_bool , subscript-style / math .code:n = \bool_set_true:N \l__chemformula_number_style_math_bool , decimal-marker .tl_set:N = \l__chemformula_decimal_output_tl , frac-style .choice: , frac-style / math .code:n = \bool_set_false:N \l__chemformula_xfrac_bool \bool_set_false:N \l__chemformula_nicefrac_bool \bool_set_true:N \l__chemformula_mathfrac_bool , frac-style / xfrac .code:n = \bool_set_true:N \l__chemformula_xfrac_bool \bool_set_false:N \l__chemformula_nicefrac_bool \bool_set_false:N \l__chemformula_mathfrac_bool , frac-style / nicefrac .code:n = \bool_set_false:N \l__chemformula_xfrac_bool \bool_set_true:N \l__chemformula_nicefrac_bool \bool_set_false:N \l__chemformula_mathfrac_bool , frac-math-cmd .cs_set_protected:Np = \chemformula_math_frac:nn #1#2 , frac-math-cmd .initial:n = \frac {#1} {#2} , stoich-paren-parse .bool_set:N = \l__chemformula_stoich_parse_iupac_bool , stoich-space .skip_set:N = \l__chemformula_stoich_space_skip , stoich-format .tl_set:N = \l__chemformula_stoich_format_tl , stoich-print .code:n = \chemformula_remove_option:n {Use~ the~ option~ `stoich-format'~ instead.} , adduct-space .dim_set:N = \l__chemformula_adduct_space_dim , adduct-penalty .tl_set:N = \l__chemformula_adduct_penalty_tl , math-space .skip_set:N = \l__chemformula_math_space_skip , name-format .tl_set:N = \l__chemformula_name_format_tl , name-width .code:n = \tl_if_eq:nnTF {#1} { auto } { \bool_set_false:N \l__chemformula_name_width_bool } { \bool_set_true:N \l__chemformula_name_width_bool \dim_set:Nn \l__chemformula_name_dim {#1} } , bond-length .dim_set:N = \l__chemformula_bond_dim , bond-offset .dim_set:N = \l__chemformula_bond_space_dim , bond-style .code:n = \tikzset { chembond/.style={Butt~Cap-Butt~Cap,#1} } , bond-penalty .tl_set:N = \l__chemformula_bond_penalty_tl , font-family .code:n = \bool_set_true:N \l__chemformula_fss_bool \bool_set_false:N \l__chemformula_fontspec_bool \bool_set_true:N \l__chemformula_fss_family_bool \tl_set:Nn \l__chemformula_font_family_tl {#1} , font-series .code:n = \bool_set_true:N \l__chemformula_fss_bool \bool_set_false:N \l__chemformula_fontspec_bool \bool_set_true:N \l__chemformula_fss_series_bool \tl_set:Nn \l__chemformula_font_series_tl {#1} , font-shape .code:n = \bool_set_true:N \l__chemformula_fss_bool \bool_set_false:N \l__chemformula_fontspec_bool \bool_set_true:N \l__chemformula_fss_shape_bool \tl_set:Nn \l__chemformula_font_shape_tl {#1} , font-spec .code:n = \bool_set_false:N \l__chemformula_fss_bool \bool_set_true:N \l__chemformula_fontspec_bool \__chemformula_fontspec:n {#1} , format .code:n = \bool_set_false:N \l__chemformula_fss_bool \bool_set_false:N \l__chemformula_fontspec_bool \tl_set:Nn \l__chemformula_format_tl {#1} , atom-format .tl_set:N = \l__chemformula_atom_format_tl , set-catcodes .tl_set:N = \l__chemformula_catcodes_tl } % -------------------------------------------------------------------------- % \chlewis[opions]{el spec}{atom} \keys_define:nn {chemformula} { lewis-default .tl_set:N = \l__chemformula_elspec_default_type_tl , lewis-distance .dim_set:N = \l__chemformula_elspec_pair_distance_dim , lewis-line-length .dim_set:N = \l__chemformula_elspec_pair_line_length_dim , lewis-line-width .dim_set:N = \l__chemformula_elspec_pair_width_dim , lewis-offset .tl_set:N = \l__chemformula_elspec_radius_tl } % #1: options % #2- el spec % #3: atom \cs_new_protected:Npn \chemformula_lewis:nnn #1#2#3 { \group_begin: \keys_set:nn {chemformula} {#1} \int_gincr:N \g__chemformula_lewis_int \chemformula_get_lewis_sequence:Nn \l__chemformula_tmpa_seq {#2} \chemformula_tikz:nn { baseline } { \chemformula_node:nxn { anchor=base , inner~sep=0pt } { chlewis-\int_use:N \g__chemformula_lewis_int } { \bool_if:NTF \l_chemformula_inside_ch_bool {#3} { \chemformula_chcpd:nn {} {#3} } } \seq_map_inline:Nn \l__chemformula_tmpa_seq { \chemformula_lewis_get_angle_and_spec:n {##1} } } \group_end: } \cs_new_protected:Npn \chemformula_get_lewis_sequence:Nn #1#2 { \tl_set:Nn \l__chemformula_tmpa_tl {#2} \tl_replace_all:Nnn \l__chemformula_tmpa_tl {:} { \scan_stop: : , } \tl_replace_all:NVn \l__chemformula_tmpa_tl \c__chemformula_colon_tl { \scan_stop: : , } \tl_replace_all:Nnn \l__chemformula_tmpa_tl {.} { \scan_stop: . , } \tl_replace_all:Nnn \l__chemformula_tmpa_tl {|} { \scan_stop: | , } \tl_replace_all:Nnn \l__chemformula_tmpa_tl {o} { \scan_stop: o , } \seq_set_split:NnV #1 {,} \l__chemformula_tmpa_tl } \cs_new_protected:Npn \chemformula_lewis_get_angle_and_spec:n #1 { \__chemformula_lewis_get_angle_and_spec:w #1 \scan_stop: \scan_stop: \q_stop } \cs_new_protected:Npn \__chemformula_lewis_get_angle_and_spec:w #1 \scan_stop: #2 \scan_stop: #3 \q_stop { \tl_if_blank:nF {#1} { \tl_set:Nn \l__chemformula_elspec_angle_tl {#1} \tl_if_blank:nTF {#2} { \tl_set_eq:NN \l__chemformula_elspec_type_tl \l__chemformula_elspec_default_type_tl } { \tl_set:Nn \l__chemformula_elspec_type_tl {#2} } \__chemformula_lewis_set_elspec_type:V \l__chemformula_elspec_type_tl } } \cs_new_protected:Npn \__chemformula_lewis_set_elspec_type:n #1 { \prop_get:NnNT \l__chemformula_lewis_elspec_types_prop {#1} \l__chemformula_tmpa_tl { \tl_use:N \l__chemformula_tmpa_tl } } \cs_generate_variant:Nn \__chemformula_lewis_set_elspec_type:n {V} % available types: \cs_new_protected:Npn \chemformula_declare_lewis_elspec_type:nn #1#2 { \prop_put:Nnn \l__chemformula_lewis_elspec_types_prop {#1} {#2} } \chemformula_declare_lewis_elspec_type:nn {|} { \__chemformula_lewis_elspec_pair_line: } \chemformula_declare_lewis_elspec_type:nn {:} { \__chemformula_lewis_elspec_pair_dots: } \chemformula_declare_lewis_elspec_type:nn {.} { \__chemformula_lewis_elspec_single: } \chemformula_declare_lewis_elspec_type:nn {o} { \__chemformula_lewis_elspec_empty: } \chemformula_declare_lewis_elspec_type:nn {pair} { \__chemformula_lewis_elspec_pair_dots: } \chemformula_declare_lewis_elspec_type:nn {pair~(dotted)} { \__chemformula_lewis_elspec_pair_dots: } \chemformula_declare_lewis_elspec_type:nn {pair~(line)} { \__chemformula_lewis_elspec_pair_line: } \chemformula_declare_lewis_elspec_type:nn {single} { \__chemformula_lewis_elspec_single: } \chemformula_declare_lewis_elspec_type:nn {empty} { \__chemformula_lewis_elspec_empty: } % functions that do the actual drawing: \cs_new_protected:Npn \__chemformula_lewis_elspec_pair_dots: { \chemformula_draw:nn { fill, inner~sep=0pt, outer~sep=0pt } { (node~cs \c__chemformula_colon_tl name = chlewis-\int_use:N \g__chemformula_lewis_int , angle = \l__chemformula_elspec_angle_tl ) ++ ( \l__chemformula_elspec_angle_tl \c__chemformula_colon_tl \l__chemformula_elspec_radius_tl ) ++ ( \l__chemformula_elspec_angle_tl +90 \c__chemformula_colon_tl .5\l__chemformula_elspec_pair_distance_dim ) circle (\l__chemformula_radical_radius_dim) ++ ( \l__chemformula_elspec_angle_tl -90 \c__chemformula_colon_tl \l__chemformula_elspec_pair_distance_dim ) circle (\l__chemformula_radical_radius_dim) } } \cs_new_protected:Npn \__chemformula_lewis_elspec_pair_line: { \chemformula_draw:nn { line~width = \l__chemformula_elspec_pair_width_dim } { (node~cs \c__chemformula_colon_tl name = chlewis-\int_use:N \g__chemformula_lewis_int , angle = \l__chemformula_elspec_angle_tl ) ++ ( \l__chemformula_elspec_angle_tl \c__chemformula_colon_tl \l__chemformula_elspec_radius_tl ) ++ ( \l__chemformula_elspec_angle_tl +90 \c__chemformula_colon_tl .5\l__chemformula_elspec_pair_line_length_dim ) -- ++ ( \l__chemformula_elspec_angle_tl -90 \c__chemformula_colon_tl \l__chemformula_elspec_pair_line_length_dim ) } } \cs_new_protected:Npn \__chemformula_lewis_elspec_single: { \chemformula_draw:nn { fill, inner~sep=0pt, outer~sep=0pt } { (node~cs \c__chemformula_colon_tl name = chlewis-\int_use:N \g__chemformula_lewis_int , angle = \l__chemformula_elspec_angle_tl ) ++ ( \l__chemformula_elspec_angle_tl \c__chemformula_colon_tl \l__chemformula_elspec_radius_tl ) circle (\l__chemformula_radical_radius_dim) } } \cs_new_protected:Npn \__chemformula_lewis_elspec_empty: { \chemformula_draw:nn { } { (node~cs \c__chemformula_colon_tl name = chlewis-\int_use:N \g__chemformula_lewis_int , angle = \l__chemformula_elspec_angle_tl ) ++ ( \l__chemformula_elspec_angle_tl \c__chemformula_colon_tl \l__chemformula_elspec_radius_tl ) ++ ( \l__chemformula_elspec_angle_tl +90 \c__chemformula_colon_tl .5\l__chemformula_elspec_pair_line_length_dim ) coordinate (chlewis-tmp1) ++ ( \l__chemformula_elspec_angle_tl -90 \c__chemformula_colon_tl \l__chemformula_elspec_pair_line_length_dim ) coordinate (chlewis-tmp2) ++ ( \l__chemformula_elspec_angle_tl \c__chemformula_colon_tl .25\l__chemformula_elspec_pair_line_length_dim ) coordinate (chlewis-tmp3) ++ ( \l__chemformula_elspec_angle_tl +90 \c__chemformula_colon_tl \l__chemformula_elspec_pair_line_length_dim ) coordinate (chlewis-tmp4) (chlewis-tmp1) -- (chlewis-tmp2) -- (chlewis-tmp3) -- (chlewis-tmp4) -- cycle } } \NewDocumentCommand\chlewis{O{}mm} { \chemformula_lewis:nnn {#1} {#2} {#3} } % -------------------------------------------------------------------------- \NewDocumentCommand \setchemformula {m} { \keys_set:nn {chemformula} {#1} } \setchemformula{ bond-style = {} , arrow-style = {} } % -------------------------------------------------------------------------- % hyperref support \hook_gput_code:nnn {package/hyperref/after} {chemformula} { \pdfstringdefDisableCommands { \cs_set:Npn \chcpd #1 {#1} \cs_set:Npn \charrow #1 {#1} \cs_set:Npn \chname (#1)(#2) { #2~(#1) } \cs_set:Npn \ch #1 {#1} \cs_set:Npn \chlewis #1#2 {#2} } } \file_input_stop: % --------------------------------------------------------------------------