%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % --------------------------------------------------------------------------- % % - the CHEMMACROS bundle - % % - chemformula.sty - % % - macros and commands for chemists - % % --------------------------------------------------------------------------- % % - Clemens Niederberger - % % - 2012/02/05 - % % --------------------------------------------------------------------------- % % - http://www.mychemistry.eu/ - % % - contact@mychemistry.eu - % % --------------------------------------------------------------------------- % % - If you have any ideas, questions, suggestions or bugs to report, please - % % - feel free to contact me. - % % --------------------------------------------------------------------------- % % - Copyright 2011-2012 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{ expl3 } \ProvidesExplPackage {chemformula} {2012/02/05} {3.0c} {typeset chemical compounds and reactions} %-----------------------------------------------------------------------------% % WARNING AND ERROR MESSAGES \msg_set:nnnn { chemformula } { missing-argument } { Wrong~name~input~ \msg_line_context: . } { Maybe~you've~forgotten~to~add~the~second~argument~to~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_set:nnnn { chemformula } { explicit } { It~seems~you've~loaded~`chemformula'~explicitly. } { It~seems~you've loaded~`chemformula'~explicitly.~This~should~work~but~the~ recommended~way~is~to~load~it~via~the~bundle,~i.e.~by~using~ \token_to_str:N \usepackage \{ chemmacros \}. } %-----------------------------------------------------------------------------% % test, if we are loaded without the `chemmacros' package \cs_if_exist:cF { ver@chemmacros.sty } { \msg_warning:nn { chemformula } { explicit } } % pass options to the `chemmacros' package \DeclareOption* { \PassOptionsToPackage { \CurrentOption } { chemmacros } } \ProcessOptions\relax \RequirePackage { chemmacros , nicefrac } %-----------------------------------------------------------------------------% % HELPER FUNCTIONS \cs_new:Npn \chemformula_tikz:nn #1#2 { \tikz [ #1 ] { #2 } } \cs_generate_variant:Nn \chemformula_tikz:nn { xn,nf } \cs_new:Npn \chemformula_draw:nn #1#2 { \draw [ #1 ] #2 ; } \cs_generate_variant:Nn \chemformula_draw:nn { xn,nx,xx,xf } %-----------------------------------------------------------------------------% % Some basic internal commands: \cs_new:Nn \chemformula_plus: { \bool_if:nTF { \l_chemmacros_circled_bool && !\l_chemmacros_circled_formal_bool } { \bool_if:NTF \l_chemmacros_circled_chem_bool { \chemmacros_fplus: } { \mode_if_math:TF { \oplus } { $ \oplus $ } } } { \bool_if:NTF \l_chemformula_charge_style_math_bool { \ensuremath { + } } { \mode_if_math:TF { \text { + } } { + } } } } \cs_new:Nn \chemformula_minus: { \bool_if:nTF { \l_chemmacros_circled_bool && !\l_chemmacros_circled_formal_bool } { \bool_if:NTF \l_chemmacros_circled_chem_bool { \chemmacros_fminus: } { \mode_if_math:TF { \ominus } { $ \ominus $ } } } { \bool_if:NTF \l_chemformula_charge_style_math_bool { \ensuremath { - } } { \mode_if_math:TF { \text { \textendash } } { \textendash } } } } \cs_new:Nn \chemformula_radical: { \textperiodcentered } \cs_new:Nn \chemformula_adduct: { \skip_horizontal:N \l_chemformula_cdot_space_dim \textperiodcentered \skip_horizontal:N \l_chemformula_cdot_space_dim } %-----------------------------------------------------------------------------% % ARROW DEFINITION % arrow heads: \dim_new:N \l_chemformula_arrow_head_dim % full tip for pairs \pgfarrowsdeclare { cf } { cf } { \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 } { left~cf } { \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 } { right~cf } { \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 } %-----------------------------------------------------------------------------% % dimension variables \dim_new:N \l_chemformula_arrow_length_dim \dim_new:N \l_chemformula_arrow_label_offset_dim \dim_set:Nn \l_chemformula_arrow_label_offset_dim { 2pt } \dim_new:N \l_chemformula_arrow_shortage_dim \tl_new:N \l_chemformula_arrow_ratio_tl \tl_set:Nn \l_chemformula_arrow_ratio_tl { .6 } \dim_new:N \l_chemformula_arrow_offset_dim \dim_set:Nn \l_chemformula_arrow_offset_dim { 1.5ex } \dim_new:N \l_chemformula_compound_sep_dim \dim_set:Nn \l_chemformula_compound_sep_dim { \medskipamount } \dim_new:N \l_chemformula_arrow_yshift_dim \dim_set:Nn \l_chemformula_arrow_yshift_dim { 0pt } % determine length in dependency of labels \cs_new:Npn \chemformula_determine_arrow_length:nn #1#2 { \hbox_set:Nn \l_tmpa_box { { #1 } } \dim_set:Nn \l_tmpa_dim { \box_wd:N \l_tmpa_box } \hbox_set:Nn \l_tmpa_box { { #2 } } \dim_set:Nn \l_tmpb_dim { \box_wd:N \l_tmpa_box } \box_clear:N \l_tmpa_box \dim_compare:nTF { \l_tmpa_dim >= \l_tmpb_dim } { \dim_set_eq:NN \l_chemformula_arrow_length_dim \l_tmpa_dim } { \dim_set_eq:NN \l_chemformula_arrow_length_dim \l_tmpb_dim } \dim_add:Nn \l_chemformula_arrow_length_dim { \l_chemformula_arrow_offset_dim } \dim_add:Nn \l_chemformula_arrow_length_dim { \l_chemformula_arrow_offset_dim } \dim_set:Nn \l_chemformula_arrow_shortage_dim { \l_chemformula_arrow_length_dim * \dim_ratio:nn { \l_chemformula_arrow_ratio_tl pt } { 1pt } } \dim_set:Nn \l_chemformula_arrow_shortage_dim { \l_chemformula_arrow_length_dim - \l_chemformula_arrow_shortage_dim } \dim_set:Nn \l_chemformula_arrow_shortage_dim { \l_chemformula_arrow_shortage_dim * \dim_ratio:nn { 1pt } { 2pt } } } %-----------------------------------------------------------------------------% % define arrow types \tl_new:N \l_chemformula_arrow_head_tl \tl_set:Nn \l_chemformula_arrow_head_tl { cf } \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_set:Nn \l_chemformula_arrow_label_style_tl { \footnotesize } % <-> \NewDocumentCommand \chemformula_arrow_mesomeric:w { O{}O{} } { \chemformula_determine_arrow_length:nn { #1 } { #2 } \chemformula_tikz:nf { inner~sep=0, baseline=(chemformula_arrow_start.base) } { \chemformula_draw:xn { \l_chemformula_arrow_head_tl-\l_chemformula_arrow_head_tl , \l_chemformula_arrow_style_tl } { coordinate (chemformula_arrow_start) (0,0) ++ (\l_chemformula_compound_sep_dim,.3432em) ++ (0,\l_chemformula_arrow_yshift_dim) -- ++ ( \dim_use:N \l_chemformula_arrow_length_dim , 0) node[pos=.5,above=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #1 } node[pos=.5,below=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #2 } } \chemformula_draw:nn {} { (\l_chemformula_compound_sep_dim,.3432em) ++ (0,\l_chemformula_arrow_yshift_dim) ++ ( \l_chemformula_compound_sep_dim + \dim_use:N \l_chemformula_arrow_length_dim , 0) } } } % -> \NewDocumentCommand \chemformula_arrow_right:w { O{}O{} } { \chemformula_determine_arrow_length:nn { #1 } { #2 } \chemformula_tikz:nn { inner~sep=0, baseline=(chemformula_arrow_start.base) } { \chemformula_draw:xn { -\l_chemformula_arrow_head_tl , \l_chemformula_arrow_style_tl } { coordinate (chemformula_arrow_start) (0,0) ++ (\l_chemformula_compound_sep_dim,.3432em) ++ (0,\l_chemformula_arrow_yshift_dim) -- ++ ( \dim_use:N \l_chemformula_arrow_length_dim , 0) node[pos=.5,above=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #1 } node[pos=.5,below=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #2 } } \chemformula_draw:nn {} { (\l_chemformula_compound_sep_dim,.3432em) ++ (0,\l_chemformula_arrow_yshift_dim) ++ ( \l_chemformula_compound_sep_dim + \dim_use:N \l_chemformula_arrow_length_dim , 0) } } } % <- \NewDocumentCommand \chemformula_arrow_left:w { O{}O{} } { \chemformula_determine_arrow_length:nn { #1 } { #2 } \chemformula_tikz:nn { inner~sep=0, baseline=(chemformula_arrow_start.base) } { \chemformula_draw:xn { \l_chemformula_arrow_head_tl- , \l_chemformula_arrow_style_tl } { coordinate (chemformula_arrow_start) (0,0) ++ (\l_chemformula_compound_sep_dim,.3432em) ++ (0,\l_chemformula_arrow_yshift_dim) -- ++ ( \dim_use:N \l_chemformula_arrow_length_dim , 0) node[pos=.5,above=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #1 } node[pos=.5,below=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #2 } } \chemformula_draw:nn {} { (\l_chemformula_compound_sep_dim,.3432em) ++ (0,\l_chemformula_arrow_yshift_dim)++ ( \l_chemformula_compound_sep_dim + \dim_use:N \l_chemformula_arrow_length_dim , 0) } } } % <=> \NewDocumentCommand \chemformula_arrow_equilibrium:w { O{}O{} } { \chemformula_determine_arrow_length:nn { #1 } { #2 } \chemformula_tikz:nn { inner~sep=0, baseline=(chemformula_arrow_start.base) } { \chemformula_draw:xn { -left~\l_chemformula_arrow_head_tl , \l_chemformula_arrow_style_tl } { coordinate (chemformula_arrow_start) (0,0) ++ (\l_chemformula_compound_sep_dim,.429em) ++ (0,\l_chemformula_arrow_yshift_dim) -- ++ ( \dim_use:N \l_chemformula_arrow_length_dim , 0) node[pos=.5,above=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #1 } } \chemformula_draw:xn { left~\l_chemformula_arrow_head_tl- , \l_chemformula_arrow_style_tl } { (chemformula_arrow_start) ++ (\l_chemformula_compound_sep_dim,.2574em) ++ (0,\l_chemformula_arrow_yshift_dim) -- ++ ( \dim_use:N \l_chemformula_arrow_length_dim , 0) node[pos=.5,below=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #2 } } \chemformula_draw:nn {} { (\l_chemformula_compound_sep_dim,.3432em) ++ (0,\l_chemformula_arrow_yshift_dim) ++ ( \l_chemformula_compound_sep_dim + \dim_use:N \l_chemformula_arrow_length_dim , 0) } } } % <=>> \NewDocumentCommand \chemformula_arrow_equilibrium_right:w { O{}O{} } { \chemformula_determine_arrow_length:nn { #1 } { #2 } \chemformula_tikz:nn { inner~sep=0, baseline=(chemformula_arrow_start.base) } { \chemformula_draw:xn { -left~\l_chemformula_arrow_head_tl , \l_chemformula_arrow_style_tl } { coordinate (chemformula_arrow_start) (0,0) ++ (\l_chemformula_compound_sep_dim,.429em) ++ (0,\dim_use:N \l_chemformula_arrow_yshift_dim) -- ++ ( \dim_use:N \l_chemformula_arrow_length_dim , 0) node[pos=.5,above=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #1 } } \chemformula_draw:xn { left~\l_chemformula_arrow_head_tl- , \l_chemformula_arrow_style_tl } { (chemformula_arrow_start) ++ (\l_chemformula_compound_sep_dim + \l_chemformula_arrow_shortage_dim,.2574em) ++ (0,\l_chemformula_arrow_yshift_dim) -- ++ ( \dim_use:N \l_chemformula_arrow_length_dim -2*\l_chemformula_arrow_shortage_dim , 0) node[pos=.5,below=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #2 } } \chemformula_draw:nn {} { (\l_chemformula_compound_sep_dim,.3432em) ++ (0,\l_chemformula_arrow_yshift_dim) ++ ( \l_chemformula_compound_sep_dim + \dim_use:N \l_chemformula_arrow_length_dim , 0) } } } % <<=> \NewDocumentCommand \chemformula_arrow_equilibrium_left:w { O{}O{} } { \chemformula_determine_arrow_length:nn { #1 } { #2 } \chemformula_tikz:nn { inner~sep=0, baseline=(chemformula_arrow_start.base) } { \chemformula_draw:xn { -left~\l_chemformula_arrow_head_tl , \l_chemformula_arrow_style_tl } { coordinate (chemformula_arrow_start) (0,0) ++ (\l_chemformula_compound_sep_dim + \l_chemformula_arrow_shortage_dim,.429em) ++ (0,\l_chemformula_arrow_yshift_dim) -- ++ ( \dim_use:N \l_chemformula_arrow_length_dim - 2*\l_chemformula_arrow_shortage_dim , 0) node[pos=.5,above=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #1 } } \chemformula_draw:xn { left~\l_chemformula_arrow_head_tl- , \l_chemformula_arrow_style_tl } { (chemformula_arrow_start) ++ (\l_chemformula_compound_sep_dim,.2574em) ++ (0,\l_chemformula_arrow_yshift_dim) -- ++ ( \dim_use:N \l_chemformula_arrow_length_dim , 0) node[pos=.5,below=\l_chemformula_arrow_label_offset_dim,font=\l_chemformula_arrow_label_style_tl,butt~cap-butt~cap] { #2 } } \chemformula_draw:nn {} { (\l_chemformula_compound_sep_dim,.3432em) ++ (0,\l_chemformula_arrow_yshift_dim) ++ ( \l_chemformula_compound_sep_dim + \dim_use:N \l_chemformula_arrow_length_dim , 0) } } } %-----------------------------------------------------------------------------% % arrow customization \keys_define:nn { chemmacros / chemformula } { arrow-offset .dim_set:N = \l_chemformula_arrow_offset_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 .dim_set:N = \l_chemformula_compound_sep_dim , arrow-tips .tl_set:N = \l_chemformula_arrow_head_tl , arrow-style .tl_set:N = \l_chemformula_arrow_style_tl , label-style .tl_set:N = \l_chemformula_arrow_label_style_tl } %-----------------------------------------------------------------------------% % MAIN COMMAND \NewDocumentCommand \chemformula_ch_aux_iii:w { > { \SplitList { ~ } } m } { \group_begin: \tl_if_blank:oF { \g_chemformula_options_tl } { \keys_set:no { chemmacros / chemformula } { \g_chemformula_options_tl } } \tl_map_function:nN { #1 } \chemformula_input:n \chemformula_generate_arrows:N \l_chemformula_input_tl \chemformula_generate_name:N \l_chemformula_output_tl \tl_set_rescan:Nno \l_chemformula_output_tl { \ExplSyntaxOn } { \l_chemformula_output_tl } \chemformula_write:n { \l_chemformula_output_tl } \group_end: } \cs_new:Nn \chemformula_ch:nn { \group_align_safe_begin: \IfNoValueTF { #1 } { \tl_gclear:N \g_chemformula_options_tl } { \tl_gset:Nn \g_chemformula_options_tl { #1 } } \chemformula_ch_aux_i:w #2 \\ \q_no_value \q_stop \group_align_safe_end: \tl_use:N \g_chemformula_output_tl \tl_gclear:N \g_chemformula_output_tl } \cs_new:Npn \chemformula_ch_aux_i:w #1 \\ #2 \q_stop { \chemformula_ch_aux_ii:w #1 & \q_no_value \q_stop \quark_if_no_value:nF { #2 } { \tl_gput_right:Nn \g_chemformula_output_tl { \\ } \chemformula_ch_aux_i:w #2 \q_stop } } \cs_new:Npn \chemformula_ch_aux_ii:w #1 & #2 \q_stop { \tl_gput_right:Nn \g_chemformula_output_tl { \chemformula_ch_aux_iii:w { #1 } } \quark_if_no_value:nF { #2 } { \tl_gput_right:Nn \g_chemformula_output_tl { & } \chemformula_ch_aux_ii:w #2 \q_stop } } % user command: \NewDocumentCommand \ch { om } { \chemformula_ch:nn { #1 } { #2 } } \cs_new:Npn \chemformula_write:n #1 { \mode_if_math:TF { \mathchoice { \hbox:n { #1 } } { \hbox:n { #1 } } { \hbox:n { \scriptsize #1 } } { \hbox:n { \tiny #1 } } } { #1 } } %-----------------------------------------------------------------------------% % arrow generation & detection \cs_new:Npn \chemformula_generate_arrows:n #1 { \tl_set:No \l_tmpa_tl { #1 } \tl_if_in:onT { \l_tmpa_tl } { <-> } { \tl_replace_all:Nnn \l_tmpa_tl { <-> } { \chemformula_arrow_mesomeric:w } } \tl_if_in:onT { \l_tmpa_tl } { -> } { \tl_replace_all:Nnn \l_tmpa_tl { -> } { \chemformula_arrow_right:w } } \tl_if_in:onT { \l_tmpa_tl } { <- } { \tl_replace_all:Nnn \l_tmpa_tl { <- } { \chemformula_arrow_left:w } } \tl_if_in:onT { \l_tmpa_tl } { glgw_l } { \tl_replace_all:Nnn \l_tmpa_tl { glgw_l } { \chemformula_arrow_equilibrium_left:w } } \tl_if_in:onT { \l_tmpa_tl } { <=>> } { \tl_replace_all:Nnn \l_tmpa_tl { <=>> } { \chemformula_arrow_equilibrium_right:w } } \tl_if_in:onT { \l_tmpa_tl } { <=> } { \tl_replace_all:Nnn \l_tmpa_tl { <=> } { \chemformula_arrow_equilibrium:w } } \tl_set_eq:NN \l_chemformula_output_tl \l_tmpa_tl } \cs_generate_variant:Nn \chemformula_generate_arrows:n { N } \cs_new:Npn \chemformula_detect_arrows:n #1 { \bool_set_false:N \l_chemformula_is_arrow_bool \tl_set:No \l_tmpa_tl { #1 } \tl_if_in:onT { \l_tmpa_tl } { <-> } { \bool_set_true:N \l_chemformula_is_arrow_bool } \tl_if_in:onT { \l_tmpa_tl } { -> } { \bool_set_true:N \l_chemformula_is_arrow_bool } \tl_if_in:onT { \l_tmpa_tl } { <- } { \bool_set_true:N \l_chemformula_is_arrow_bool } \tl_if_in:onT { \l_tmpa_tl } { <=>> } { \bool_set_true:N \l_chemformula_is_arrow_bool } \tl_if_in:onT { \l_tmpa_tl } { glgw_l } { \bool_set_true:N \l_chemformula_is_arrow_bool } \tl_if_in:onT { \l_tmpa_tl } { <=> } { \bool_set_true:N \l_chemformula_is_arrow_bool } } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % compound names \dim_new:N \l_chemformula_name_dim \cs_new:Npn \chemformula_name_cmpd:w { \peek_meaning:NTF { ( } { \chemformula_name_cmpd_aux:w } { ! } } \cs_new:Npn \chemformula_name_cmpd_aux:w (#1)(#2) { \( \underset { \bool_if:NF \l_chemformula_name_width_bool { \width_to_dim:Nn \l_chemformula_name_dim { \l_chemformula_name_format_tl #1 } } \parbox { \dim_use:N \l_chemformula_name_dim } { \l_chemformula_name_format_tl #1 } } { \text { \vphantom{\gas} #2 } } \) } \cs_new:Npn \width_to_dim:nn #1#2 { \hbox_set:Nn \l_tmpa_box { #2 } \dim_set:Nn #1 { \box_wd:N \l_tmpa_box } \box_clear:N \l_tmpa_box } \cs_generate_variant:Nn \width_to_dim:nn { Nn } \cs_new:Npn \chemformula_generate_name:n #1 { \tl_set:No \l_tmpa_tl { #1 } \tl_if_in:onT { \l_tmpa_tl } { ! } { \tl_replace_all:Nnn \l_tmpa_tl { ! } { \chemformula_name_cmpd:w } } \tl_set_eq:NN \l_chemformula_output_tl \l_tmpa_tl } \cs_generate_variant:Nn \chemformula_generate_name:n { N } \cs_new:Npn \chemformula_detect_name:n #1 { \bool_set_false:N \l_chemformula_is_name_bool \tl_set:No \l_tmpa_tl { #1 } \tl_if_in:onT { \l_tmpa_tl } { ! } { \bool_set_true:N \l_chemformula_is_name_bool } } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % parsing input % booleans: \bool_new:N \l_chemformula_stoich_bool \bool_new:N \l_chemformula_is_plus_bool \bool_new:N \l_chemformula_is_up_bool \bool_new:N \l_chemformula_is_down_bool \bool_new:N \l_chemformula_is_arrow_bool \bool_new:N \l_chemformula_is_name_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_number_style_math_bool \bool_new:N \l_chemformula_charge_style_math_bool \bool_new:N \l_chemformula_sub_bool \bool_new:N \l_chemformula_sup_bool \bool_new:N \l_chemformula_xfrac_bool \bool_new:N \l_chemformula_nicefrac_bool \bool_new:N \l_chemformula_mathfrac_bool \bool_set_true: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_shift_bool % token lists: \tl_new:N \l_chemformula_tmpa_tl \tl_new:N \g_chemformula_options_tl \tl_new:N \g_chemformula_output_tl \tl_new:N \l_chemformula_output_tl \tl_new:N \l_chemformula_input_tl \tl_new:N \l_chemformula_stoich_tl \tl_new:N \l_chemformula_decimal_output_tl \tl_set:Nn \l_chemformula_decimal_output_tl { . } \tl_new:N \l_chemformula_font_family_tl \tl_set_eq:NN \l_chemformula_font_family_tl \f@family \tl_new:N \l_chemformula_font_series_tl \tl_set_eq:NN \l_chemformula_font_series_tl \f@series \tl_new:N \l_chemformula_font_shape_tl \tl_set_eq:NN \l_chemformula_font_shape_tl \f@shape \tl_new:N \l_chemformula_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_set:Nn \l_chemformula_name_format_tl { \scriptsize\centering } % dimensions: \dim_new:N \l_chemformula_stoich_space_dim \dim_set:Nn \l_chemformula_stoich_space_dim { .1667em } \dim_new:N \l_chemformula_math_space_dim \dim_set:Nn \l_chemformula_math_space_dim { .1667em } \dim_new:N \l_chemformula_plus_space_dim \dim_set:Nn \l_chemformula_plus_space_dim { .3em } \dim_new:N \l_chemformula_cdot_space_dim \dim_set:Nn \l_chemformula_cdot_space_dim { .1333em } \dim_new:N \l_chemformula_charge_shift_dim \dim_set:Nn \l_chemformula_charge_shift_dim { .3ex } \dim_new:N \l_chemformula_subscript_shift_default_dim \dim_set:Nn \l_chemformula_subscript_shift_default_dim { -.6ex } \dim_new:N \l_chemformula_subscript_shift_dim \dim_set_eq:NN \l_chemformula_subscript_shift_dim \l_chemformula_subscript_shift_default_dim \dim_new:N \l_chemformula_subscript_shift_additional_dim \dim_new:N \l_chemformula_subscript_dim \dim_zero:N \l_chemformula_subscript_dim \dim_new:N \l_chemformula_supscript_dim \dim_zero:N \l_chemformula_supscript_dim \dim_new:N \l_chemformula_bond_dim \hbox_set:Nn \l_tmpa_box { \textendash } \dim_set:Nn \l_chemformula_bond_dim { \box_wd:N \l_tmpa_box } \box_clear:N \l_tmpa_box % integers: \int_new:N \l_chemformula_count_tokens_int % property lists: % behaviour in a compound \prop_new:N \l_chemformula_cmpd_prop \prop_put:Nnn \l_chemformula_cmpd_prop { 0 } { \chemformula_subscript:n { 0 } } \prop_put:Nnn \l_chemformula_cmpd_prop { 1 } { \chemformula_subscript:n { 1 } } \prop_put:Nnn \l_chemformula_cmpd_prop { 2 } { \chemformula_subscript:n { 2 } } \prop_put:Nnn \l_chemformula_cmpd_prop { 3 } { \chemformula_subscript:n { 3 } } \prop_put:Nnn \l_chemformula_cmpd_prop { 4 } { \chemformula_subscript:n { 4 } } \prop_put:Nnn \l_chemformula_cmpd_prop { 5 } { \chemformula_subscript:n { 5 } } \prop_put:Nnn \l_chemformula_cmpd_prop { 6 } { \chemformula_subscript:n { 6 } } \prop_put:Nnn \l_chemformula_cmpd_prop { 7 } { \chemformula_subscript:n { 7 } } \prop_put:Nnn \l_chemformula_cmpd_prop { 8 } { \chemformula_subscript:n { 8 } } \prop_put:Nnn \l_chemformula_cmpd_prop { 9 } { \chemformula_subscript:n { 9 } } \prop_put:Nnn \l_chemformula_cmpd_prop { * } { \chemformula_adduct: } \prop_put:Nnn \l_chemformula_cmpd_prop { . } { \chemformula_adduct: } \prop_put:Nnn \l_chemformula_cmpd_prop { - } { \chemformula_single_bond: } \prop_put:Nnn \l_chemformula_cmpd_prop { = } { \chemformula_double_bond: } \prop_put:Nnn \l_chemformula_cmpd_prop { + } { \chemformula_triple_bond: } % numbers \prop_new:N \l_chemformula_numbers_prop \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_new:N \l_chemformula_charge_prop \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: } % stoichiometric factors \prop_new:N \l_chemformula_stoich_prop \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 { . } { { \l_chemformula_decimal_output_tl } } \prop_put:Nnn \l_chemformula_stoich_prop { , } { { \l_chemformula_decimal_output_tl } } \prop_put:Nnn \l_chemformula_stoich_prop { / } { / } \prop_put:Nnn \l_chemformula_stoich_prop { _ } { _ } %-----------------------------------------------------------------------------% % bonds: \cs_new:Npn \chemformula_single_bond: { \bool_if:NTF \l_chemformula_sup_bool { \chemformula_minus: } { \chemformula_tikz:nn { inner~sep=0, outer~sep=0 } { \draw node[draw=none,minimum~height=1em,minimum~width=0] (chemformula-single-bond) at (0,0) {} ; \draw[butt~cap-butt~cap] (chemformula-single-bond) ++ (0,-.1716em) -- ++( \l_chemformula_bond_dim ,0) ; } } } \cs_new:Npn \chemformula_double_bond: { \chemformula_tikz:nn { inner~sep=0, outer~sep=0 } { \draw node[draw=none,minimum~height=1em,minimum~width=0] (chemformula-double-bond) at (0,0) {} ; \draw[butt~cap-butt~cap] (chemformula-double-bond) ++ (0,-.0858em) -- ++( \l_chemformula_bond_dim ,0) ; \draw[butt~cap-butt~cap] (chemformula-double-bond) ++ (0,-.2574em) -- ++( \l_chemformula_bond_dim ,0) ; } } \cs_new:Npn \chemformula_triple_bond: { \chemformula_tikz:nn { inner~sep=0, outer~sep=0 } { \draw node[draw=none,minimum~height=1em,minimum~width=0] (chemformula-triple-bond) at (0,0) {} ; \draw[butt~cap-butt~cap] (chemformula-triple-bond) ++ (0,-.0429em) -- ++( \l_chemformula_bond_dim ,0) ; \draw[butt~cap-butt~cap] (chemformula-triple-bond) ++ (0,-.1716em) -- ++( \l_chemformula_bond_dim ,0) ; \draw[butt~cap-butt~cap](chemformula-triple-bond) ++ (0,-.3003em) -- ++( \l_chemformula_bond_dim ,0) ; } } %-----------------------------------------------------------------------------% % sub- and superscripts \cs_new:Nn \chemformula_number_style:n { \bool_if:NTF \l_chemformula_number_style_math_bool { \ensuremath { #1 } } { \ensuremath { \text { #1 } } } } \cs_new:Nn \chemformula_charge_style:n { \bool_if:NTF \l_chemformula_charge_style_math_bool { \ensuremath { #1 } } { \ensuremath { \text { #1 } } } } \cs_new:Npn \chemformula_subscript:n #1 { \bool_set_true:N \l_chemformula_sub_bool % clean up wrong input \tl_set:Nn \l_tmpc_tl { #1 } \tl_replace_all:Nnn \l_tmpc_tl { \chemformula_single_bond: } { \chemformula_minus: } \tl_replace_all:Nnn \l_tmpc_tl { \chemformula_triple_bond: } {\chemformula_plus: } \tl_replace_all:Nnn \l_tmpc_tl { \chemformula_adduct: } { . } % measure width and save it \hbox_set:Nn \l_tmpa_box { $\mathchoice { \scriptstyle } { \scriptstyle } { \scriptscriptstyle } { \scriptscriptstyle } \prop_get:NnNTF \l_chemformula_numbers_prop { #1 } \l_tmpa_tl { \chemformula_number_style:n { \l_tmpa_tl } } { \chemformula_number_style:n { \l_tmpc_tl } }$ } \dim_set:Nn \l_chemformula_subscript_dim { -\box_wd:N \l_tmpa_box } \box_clear:N \l_tmpa_box \bool_if:NT \l_chemformula_sup_bool { \chemformula_sub_or_supscript_skip: \bool_if:NT \l_chemformula_charge_shift_bool { \skip_horizontal:n { \l_chemformula_charge_shift_dim +1pt } \bool_set_false:N \l_chemformula_charge_shift_bool } \dim_zero:N \l_chemformula_supscript_dim } % typeset subscript \tex_raise:D \l_chemformula_subscript_shift_dim \hbox:n { $\mathchoice { \scriptstyle } { \scriptstyle } { \scriptscriptstyle } { \scriptscriptstyle } \prop_get:NnNTF \l_chemformula_numbers_prop { #1 } \l_tmpa_tl { \chemformula_number_style:n { \l_tmpa_tl } } { \chemformula_number_style:n { \l_tmpc_tl } }$ } % look ahead what's coming next and set boolean accordingly \peek_meaning:NTF \chemformula_supscript:n { \bool_set_true:N \l_chemformula_sub_bool } { \peek_meaning:NTF \chemformula_chief_supscript:n { \bool_set_true:N \l_chemformula_sub_bool } { \bool_set_false:N \l_chemformula_sub_bool } } } \cs_new:Npn \chemformula_supscript:n #1 { \bool_set_true:N \l_chemformula_sup_bool % clean up wrong input \tl_set:Nn \l_tmpc_tl { #1 } \tl_replace_all:Nnn \l_tmpc_tl { \chemformula_single_bond: } { \chemformula_minus: } \tl_replace_all:Nnn \l_tmpc_tl { - } { \chemformula_minus: } \tl_replace_all:Nnn \l_tmpc_tl { \chemformula_triple_bond: } { \chemformula_plus: } \tl_replace_all:Nnn \l_tmpc_tl { + } { \chemformula_plus: } \tl_replace_all:Nnn \l_tmpc_tl { \chemformula_adduct: } { \chemformula_radical: } \tl_replace_all:Nnn \l_tmpc_tl { . } { \chemformula_radical: } % measure width and save it \prop_get:NnNTF \l_chemformula_charge_prop { #1 } \l_tmpa_tl { \exp_args:NNo \hbox_set:Nn \l_tmpa_box { $ ^ { \chemformula_charge_style:n { \l_tmpa_tl } } $ } } { \exp_args:NNo \hbox_set:Nn \l_tmpa_box { $ ^ { \chemformula_charge_style:n { \l_tmpc_tl } } $ } } \dim_set:Nn \l_chemformula_supscript_dim { -\box_wd:N \l_tmpa_box } \box_clear:N \l_tmpa_box \bool_if:NT \l_chemformula_sub_bool { \chemformula_sub_or_supscript_skip: \skip_horizontal:N \l_chemformula_charge_shift_dim \bool_set_true:N \l_chemformula_charge_shift_bool \dim_zero:N \l_chemformula_subscript_dim } % typeset superscript \prop_get:NnNTF \l_chemformula_charge_prop { #1 } \l_tmpa_tl { $ ^ { \chemformula_charge_style:n { \l_tmpa_tl } } $ } { $ ^ { \chemformula_charge_style:n { \l_tmpc_tl } } $ } % look ahead what's coming next and set boolean accordingly \peek_meaning:NTF \chemformula_subscript:n { \bool_set_true:N \l_chemformula_sup_bool } { \peek_meaning:NTF \chemformula_chief_subscript:n { \bool_set_true:N \l_chemformula_sup_bool } { \bool_set_false:N \l_chemformula_sup_bool } } } \cs_new:Npn \chemformula_sub_or_supscript_skip: { \dim_compare:nTF { \dim_abs:n { \l_chemformula_subscript_dim } <= \dim_abs:n { \l_chemformula_supscript_dim } } { \skip_horizontal:N \l_chemformula_subscript_dim } { \skip_horizontal:N \l_chemformula_supscript_dim } \bool_set_false:N \l_chemformula_sup_bool \bool_set_false:N \l_chemformula_sub_bool } % handle sub- in superscripts and vice versa \cs_new:Npn \chemformula_chief_supscript:n #1 { \tl_if_eq:nnTF { #1 } { \chemformula_supscript:n } { \chemformula_supscript:n } { \tl_if_eq:nnTF { #1 } { \chemformula_subscript:n } { \chemformula_supscript:n } { \tl_set:Nn \l_tmpc_tl { #1 } \tl_if_in:nnT { #1 } { \chemformula_subscript:n } { \tl_remove_all:Nn \l_tmpc_tl { \chemformula_subscript:n } } \tl_if_in:nnT { #1 } { \chemformula_supscript:n } { \tl_remove_all:Nn \l_tmpc_tl { \chemformula_supscript:n } } \exp_args:No \chemformula_supscript:n { \l_tmpc_tl } } } } \cs_new:Npn \chemformula_chief_subscript:n #1 { \tl_if_eq:nnTF { #1 }{ \chemformula_supscript:n } { \chemformula_subscript:n } { \tl_if_eq:nnTF { #1 }{ \chemformula_subscript:n } { \chemformula_subscript:n } { \tl_set:Nn \l_tmpc_tl { #1 } \tl_if_in:nnT { #1 } { \chemformula_subscript:n } { \tl_remove_all:Nn \l_tmpc_tl { \chemformula_subscript:n } } \tl_if_in:nnT { #1 } { \chemformula_supscript:n } { \tl_remove_all:Nn \l_tmpc_tl { \chemformula_supscript:n } } \exp_args:No \chemformula_subscript:n { \l_tmpc_tl } } } } \cs_new:Npn \chemformula_test_for_subscript:n #1 { \peek_meaning:NT \chemformula_subscript:n { \bool_if:NT \l_chemformula_sup_bool { \skip_horizontal:N #1 } \bool_set_false:N \l_chemformula_sup_bool } } \cs_new:Npn \chemformula_test_for_supscript:n #1 { \peek_meaning:NT \chemformula_subscript:n { \bool_if:NT \l_chemformula_sup_bool { \skip_horizontal:N #1 } \bool_set_false:N \l_chemformula_sup_bool } } %-----------------------------------------------------------------------------% % read the input \cs_new:Npn \chemformula_input:n #1 { \tl_set_rescan:Nnn \l_chemformula_tmpa_tl { % \char_set_catcode_letter:N \_ \char_set_catcode_letter:N \{ \char_set_catcode_letter:N \} \char_set_catcode_letter:N \\ \char_set_catcode_other:N \" } { #1 } \chemformula_input_escape_text:o { \l_chemformula_tmpa_tl } \chemformula_input_escape_math:n { #1 } \chemformula_input_stoich:n { #1 } % need to take care of <<=> arrow \tl_if_in:onT { \l_chemformula_tmpa_tl } { <<=> } { \tl_replace_all:Nnn \l_chemformula_tmpa_tl { <<=> } { glgw_l } } \chemformula_clean_chem_macros:o { \l_chemformula_tmpa_tl } \chemformula_input_cmpd:oN { \l_chemformula_tmpa_tl } \l_chemformula_input_tl \chemformula_input_arrow:o { \l_chemformula_tmpa_tl } \chemformula_input_name:n { #1 } \chemformula_input_plus:n { #1 } \chemformula_input_up:n { #1 } \chemformula_input_down:n { #1 } } %-----------------------------------------------------------------------------% % input stoichiometric factors \cs_new:Npn \chemformula_input_stoich:n #1 { \bool_set_true:N \l_chemformula_stoich_bool \tl_put_right:Nn \l_chemformula_stoich_tl { \chemformula_font_inner: } \tl_map_inline:nn { #1 } { \prop_get:NnNTF \l_chemformula_stoich_prop { ##1 } \l_tmpa_tl { \bool_if:NT \l_chemformula_stoich_bool { \tl_put_right:Nx \l_chemformula_stoich_tl { \l_tmpa_tl } } } { \bool_set_false:N \l_chemformula_stoich_bool } } \bool_if:NTF \l_chemformula_stoich_bool { \tl_if_blank:VF \l_chemformula_stoich_tl { \tl_set_rescan:Nno \l_chemformula_stoich_tl { \ExplSyntaxOn } { \l_chemformula_stoich_tl } \exp_args:No \chemformula_parse_stoich:n { \l_chemformula_stoich_tl } } } { \tl_clear:N \l_chemformula_stoich_tl } } \cs_new:Nn \chemformula_bm:n { #1 } \cs_new:Npn \chemformula_parse_stoich:n #1 { \tl_if_in:nnTF { #1 } { _ } { \chemformula_parse_stoich_misc_frac:w #1 \q_nil } { \tl_if_in:nnTF { #1 } { / } { \chemformula_parse_stoich_frac:w #1 \q_nil } { \tl_put_right:Nn \l_chemformula_input_tl { #1 } } } } \DeclareInstance { xfrac } { chemformula-text-frac } { text } { slash-left-kern = -.15em , slash-right-kern = -.15em } \cs_new:Npn \chemformula_parse_stoich_frac:w #1/#2 \q_nil { \tl_put_right:Nn \l_chemformula_input_tl { \chemformula_frac:nn { #1 } { #2 } } } \cs_new:Npn \chemformula_parse_stoich_misc_frac:w #1_#2/#3 \q_nil { \tl_put_right:Nn \l_chemformula_input_tl { \chemformula_misc_frac:nnn { #1 } { #2 } { #3 } } } \cs_new: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 { $ \frac{ \text { #1 } } { \text { #2 } } $ } } \cs_new: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 $ \frac{ \text { #2 } } { \text { #3 } } $ } } %-----------------------------------------------------------------------------% % input compounds \cs_new:Nn \chemformula_input_cmpd:nN { \tl_if_blank:VTF \l_chemformula_stoich_tl { \tl_if_eq:nnT { #1 } { + } { \bool_set_true:N \l_chemformula_is_plus_bool } \tl_if_eq:nnT { #1 } { v } { \bool_set_true:N \l_chemformula_is_down_bool } \tl_if_eq:nnT { #1 } { ^ } { \bool_set_true:N \l_chemformula_is_up_bool } \chemformula_detect_arrows:n { #1 } \chemformula_detect_name:n { #1 } \bool_if:nT { !\l_chemformula_is_plus_bool && !\l_chemformula_is_down_bool && !\l_chemformula_is_up_bool && !\l_chemformula_is_arrow_bool && !\l_chemformula_is_name_bool && !\l_chemformula_first_last_text_bool && !\l_chemformula_first_last_math_bool } { \tl_put_right:Nn #2 { \chemformula_font_inner: } \chemformula_handle_sub_and_supscripts:nN { #1 } #2 } } { \tl_put_right:Nn #2 { \skip_horizontal:N \l_chemformula_stoich_space_dim } \tl_clear:N \l_chemformula_stoich_tl } } \cs_generate_variant:Nn \chemformula_input_cmpd:nN { oN } \cs_new:Nn \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 { \chemformula_font: } \tl_use:N \l_chemformula_format_tl \exp_args:No \tl_if_eq:nnTF { \f@series } { bx } { \cs_set_eq:NN \chemformula_bm:n \bm } { \cs_set:Nn \chemformula_bm:n { ##1 } } } \cs_new:Nn \chemformula_font: {} \cs_new:Nn \chemformula_fontspec:n { \tl_if_in:nnTF { #1 } { [ } { \chemformula_fontspec_aux:w #1 \q_stop } { \chemformula_fontspec_aux:w [] #1 \q_stop } } \cs_new:Npn \chemformula_fontspec_aux:w [#1]#2 \q_stop { \newfontfamily \chemformula_font: [ #1 ] { #2 } } \cs_new:Nn \chemformula_handle_sub_and_supscripts:nN { \tl_set_rescan:Nnn \l_tmpa_tl { \char_set_catcode_letter:N \_ \char_set_catcode_letter:N \{ \char_set_catcode_letter:N \} \char_set_catcode_letter:N \\ } { #1 } \tl_if_in:VnT \l_tmpa_tl { ^ } { \tl_replace_all:Nnn \l_tmpa_tl { ^ } { \chemformula_chief_supscript:n } } \tl_if_in:VnT \l_tmpa_tl { _ } { \tl_replace_all:Nnn \l_tmpa_tl { _ } { \chemformula_chief_subscript:n } } \int_zero:N \l_chemformula_count_tokens_int \tl_map_inline:Nn \l_tmpa_tl { \int_incr:N \l_chemformula_count_tokens_int \int_compare:nTF { \l_chemformula_count_tokens_int = \tl_length:N \l_tmpa_tl } { \tl_if_eq:nnTF { ##1 } { + } { \tl_put_right:Nn #2 { \chemformula_supscript:n { \chemformula_plus: } } } { \tl_if_eq:nnTF { ##1 } { - } { \tl_put_right:Nn #2 { \chemformula_supscript:n { \chemformula_minus: } } } { \prop_get:NnNTF \l_chemformula_cmpd_prop { ##1 } \l_tmpb_tl { \tl_put_right:No #2 { \l_tmpb_tl } } { \tl_put_right:Nn #2 { ##1 } } } } } { \prop_get:NnNTF \l_chemformula_cmpd_prop { ##1 } \l_tmpb_tl { \tl_put_right:No #2 { \l_tmpb_tl } } { \tl_put_right:Nn #2 { ##1 } } } } } %-----------------------------------------------------------------------------% % clean up chemmacros commands: \cs_new:Nn \chemformula_clean_chem_macros:n { \cs_set:Nn \chemmacros_text:n { \mode_if_math:TF { \text { \chemformula_font_inner: ##1 } } { \chemformula_font_inner: ##1 } } \cs_set:Npn \chemmacros_xspace: {} \tl_set:Nn \l_tmpa_tl { #1 } \exp_args:NNo \tl_replace_all:Nnn \l_tmpa_tl { \l_chemformula_aq_tl } { _{(aq)} } \bool_if:NTF \l_chemmacros_german_bool { \exp_args:NNo \tl_replace_all:Nnn \l_tmpa_tl { \l_chemformula_sld_tl } { _{(f)} } } { \exp_args:NNo \tl_replace_all:Nnn \l_tmpa_tl { \l_chemformula_sld_tl } { _{(s)} } } \bool_if:NTF \l_chemmacros_german_bool { \exp_args:NNo \tl_replace_all:Nnn \l_tmpa_tl { \l_chemformula_lqd_tl } { _{(f\/l)} } } { \exp_args:NNo \tl_replace_all:Nnn \l_tmpa_tl { \l_chemformula_lqd_tl } { _{(l)} } } \exp_args:NNo \tl_replace_all:Nnn \l_tmpa_tl { \l_chemformula_gas_tl } { _{(g)} } \tl_set_eq:NN \l_chemformula_tmpa_tl \l_tmpa_tl } \cs_generate_variant:Nn \chemformula_clean_chem_macros:n { o } \tl_new:N \l_chemformula_aq_tl \tl_set_rescan:Nnn \l_chemformula_aq_tl { \char_set_catcode_letter:N \\ } { \aq } \tl_set_rescan:Nnn \l_chemformula_sld_tl { \char_set_catcode_letter:N \\ } { \sld } \tl_set_rescan:Nnn \l_chemformula_lqd_tl { \char_set_catcode_letter:N \\ } { \lqd } \tl_set_rescan:Nnn \l_chemformula_gas_tl { \char_set_catcode_letter:N \\ } { \gas } %-----------------------------------------------------------------------------% % input "and" sign \cs_new:Nn \chemformula_input_plus:n { \tl_if_eq:nnT { #1 } { + } { \tl_put_right:Nn \l_chemformula_input_tl { \skip_horizontal:N \l_chemformula_plus_space_dim + \skip_horizontal:N \l_chemformula_plus_space_dim } } \bool_set_false:N \l_chemformula_is_plus_bool } %-----------------------------------------------------------------------------% % input escaping gas \cs_new:Nn \chemformula_input_up:n { \tl_if_eq:nnT { #1 } { ^ } { \tl_put_right:Nn \l_chemformula_input_tl { $\uparrow$ } } \bool_set_false:N \l_chemformula_is_up_bool } %-----------------------------------------------------------------------------% % input precipitate \cs_new:Nn \chemformula_input_down:n { \tl_if_eq:nnT { #1 } { v } { \tl_put_right:Nn \l_chemformula_input_tl { $\downarrow$ } } \bool_set_false:N \l_chemformula_is_down_bool } %-----------------------------------------------------------------------------% % input arrow \cs_new:Nn \chemformula_input_arrow:n { \bool_if:nT { \l_chemformula_is_arrow_bool && !\l_chemformula_first_last_text_bool && !\l_chemformula_first_last_math_bool } { \tl_put_right:Nn \l_chemformula_input_tl { #1 } } \bool_set_false:N \l_chemformula_is_arrow_bool } \cs_generate_variant:Nn \chemformula_input_arrow:n { o } %-----------------------------------------------------------------------------% % input compound name \cs_new:Nn \chemformula_input_name:n { \bool_if:nT { \l_chemformula_is_name_bool && !\l_chemformula_first_last_text_bool && !\l_chemformula_first_last_math_bool } { \tl_put_right:Nn \l_chemformula_input_tl { #1 } } \bool_set_false:N \l_chemformula_is_name_bool } %-----------------------------------------------------------------------------% % input escaped text \cs_new:Nn \chemformula_input_escape_text:n { \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 { o } \cs_new:Npn \chemformula_read_escape_double:w "#1" \q_nil { \tl_set_rescan:Nnn \l_tmpa_tl { \ExplSyntaxOn \char_set_catcode_other:N \: } { #1 } \tl_replace_all:Nnn \l_tmpa_tl { \_ } { chemformulaplaceholder } \tl_replace_all:Nnn \l_tmpa_tl { _ } { \sb } \tl_replace_all:Nnn \l_tmpa_tl { chemformulaplaceholder } { \_ } \tl_set_rescan:Nno \l_tmpa_tl { \ExplSyntaxOff } { \l_tmpa_tl } \tl_put_right:NV \l_chemformula_input_tl \l_tmpa_tl } \cs_new:Npn \chemformula_read_escape_single:w '#1' \q_nil { \tl_set_rescan:Nnn \l_tmpa_tl { \ExplSyntaxOn \char_set_catcode_other:N \: } { { #1 } } \tl_replace_all:Nnn \l_tmpa_tl { \_ } { chemformulaplaceholder } \tl_replace_all:Nnn \l_tmpa_tl { _ } { \sb } \tl_replace_all:Nnn \l_tmpa_tl { chemformulaplaceholder } { \_ } \tl_set_rescan:Nno \l_tmpa_tl { \ExplSyntaxOff } { \l_tmpa_tl } \tl_put_right:NV \l_chemformula_input_tl \l_tmpa_tl } \cs_new:Nn \chemformula_first_last_text:n { \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 \int_zero:N \l_tmpa_int \int_zero:N \l_tmpb_int \tl_map_inline:nn { #1 } { \int_incr:N \l_tmpa_int } \tl_map_inline:nn { #1 } { \int_incr:N \l_tmpb_int \int_compare:nT { \l_tmpb_int = 1 } { \tl_if_eq:nnT { ##1 } { " } { \bool_set_true:N \l_chemformula_first_last_double_bool } } \int_compare:nT { \l_tmpb_int = \l_tmpa_int } { \tl_if_eq:nnF { ##1 } { " } { \bool_set_false:N \l_chemformula_first_last_double_bool } } } \bool_if:NF \l_chemformula_first_last_double_bool { \int_zero:N \l_tmpb_int \tl_map_inline:nn { #1 } { \int_incr:N \l_tmpb_int \int_compare:nT { \l_tmpb_int = 1 } { \tl_if_eq:nnT { ##1 } { ' } { \bool_set_true:N \l_chemformula_first_last_single_bool } } \int_compare:nT { \l_tmpb_int = \l_tmpa_int } { \tl_if_eq:nnF { ##1 } { ' } { \bool_set_false:N \l_chemformula_first_last_single_bool } } } } } %-----------------------------------------------------------------------------% % input escaped math \cs_new:Nn \chemformula_input_escape_math:n { \chemformula_first_last_math:n { #1 } \bool_if:NT \l_chemformula_first_last_math_bool { \chemformula_read_escape_math:w #1 \q_nil } } \cs_new:Npn \chemformula_read_escape_math:w $#1$ \q_nil { \tl_set_rescan:Nnn \l_tmpa_tl { \ExplSyntaxOn \char_set_catcode_letter:N \{ \char_set_catcode_letter:N \} } { \mbox { \( #1 \) } } \tl_replace_all:Nnn \l_tmpa_tl { \_ } { chemformulaplaceholder } \tl_replace_all:Nnn \l_tmpa_tl { _ } { \sb } \tl_replace_all:Nnn \l_tmpa_tl { chemformulaplaceholder } { \_ } \tl_set_rescan:Nno \l_tmpa_tl { \ExplSyntaxOff } { \l_tmpa_tl } \tl_put_right:NV \l_chemformula_input_tl \l_tmpa_tl \tl_put_right:Nn \l_chemformula_input_tl { \skip_horizontal:N \l_chemformula_math_space_dim } } \cs_new:Nn \chemformula_first_last_math:n { \bool_set_false:N \l_chemformula_first_last_math_bool \int_zero:N \l_tmpa_int \int_zero:N \l_tmpb_int \tl_map_inline:nn { #1 } { \int_incr:N \l_tmpa_int } \tl_map_inline:nn { #1 } { \int_incr:N \l_tmpb_int \int_compare:nT { \l_tmpb_int = 1 } { \tl_if_eq:nnT { ##1 } { $ } { \bool_set_true:N \l_chemformula_first_last_math_bool } } \int_compare:nT { \l_tmpb_int = \l_tmpa_int } { \tl_if_eq:nnF { ##1 } { $ } { \bool_set_false:N \l_chemformula_first_last_math_bool } } } } %-----------------------------------------------------------------------------% % customization of output other than arrows \keys_define:nn { chemmacros / chemformula } { charge-hshift .dim_set:N = \l_chemformula_charge_shift_dim , charge-hshift .default:n = .3ex , 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 .code:n = { \dim_set:Nn \l_chemformula_subscript_shift_additional_dim { #1 } \dim_set:Nn \l_chemformula_subscript_shift_dim { \l_chemformula_subscript_shift_default_dim + \l_chemformula_subscript_shift_additional_dim } } , 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 , stoich-space .dim_set:N = \l_chemformula_stoich_space_dim , adduct-space .dim_set:N = \l_chemformula_cdot_space_dim , plus-space .dim_set:N = \l_chemformula_plus_space_dim , math-space .dim_set:N = \l_chemformula_math_space_dim , 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 , 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 } } %-----------------------------------------------------------------------------% % hyperref support \AfterPackage* { hyperref } { \pdfstringdefDisableCommands { \cs_set:Npn \cn #1 { #1 } } } \tex_endinput:D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION HISTORY 2012/01/28 - version 3.0 - first published to CTAN with the chemmacros bundle 2012/01/30 - version 3.0a - bugfix: subscripts in escaped inputs failed, renamed formula => chemformula 2012/02/02 - version 3.0b - updated documentation 2012/02/05 - version 3.0c - renamed pictogram files %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % TODO - Addukte: Zahlen nach * und . automatisch erkennen? - allow fractions in subscripts: _{$\frac{1}{2}$} ? - optionale argumente von \\ nach außen weiterreichen? - vertikaler shift für superskripte? - the explicit definition of each arrow on its own is inefficient. also these definitions abuse the `xparse' command \NewDocumentCommand for internal commands => needs to be taken care of