% --------------------------------------------------------------------------
%
% the CHEMMACROS package -- module: `reactions'
%
% --------------------------------------------------------------------------
% Clemens Niederberger
% --------------------------------------------------------------------------
% https://github.org/cgnieder/chemmacros/
% contact@mychemistry.eu
% --------------------------------------------------------------------------
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% --------------------------------------------------------------------------
% Copyright 2011--2020 Clemens Niederberger
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Clemens Niederberger.
% --------------------------------------------------------------------------
\ChemModule{reactions}{2020/02/02 reaction environments}

\chemmacros_load_module:n {chemformula}

\RequirePackage{mathtools}

% --------------------------------------------------------------------------
\cs_new_protected:Npn \__chemmacros_record_for_lor:nnnnn #1#2#3#4#5
  {
    \tl_if_eq:nnT {#1} {reaction}
      {
        \group_begin:
          % we need to prevent \Hy@make@anchor from being written to the lor
          % file:
          \bool_if:NT \l__chemmacros_hyperref_bool
            { \cs_set:Npn \Hy@make@anchor {} }
          \addcontentsline {lor} {reaction}
            {
              \tl_use:N \l__chemmacros_reaction_lorname_tl
              \tl_use:N \c_space_tl
              #2 #3 #4 #5
              \tl_use:N \g__chemmacros_reaction_description_tl
            }
          \tl_gclear:N \g__chemmacros_reaction_description_tl
        \group_end:
      }
  }

% redefine mathtools' command \MT_define_tagform:nwnn to ensure we add an
% entry to the list of reactions even if the user redefines the reaction tag
% this should probably be done via patching...
\AfterPackage* { mathtools }
  {
    \cs_set_protected:Npn \MT_define_tagform:nwnn #1[#2]#3#4
      {
        \@namedef{MT_tagform_#1:n}##1
          {
            % this is the original part:
            \maketag@@@{#3\ignorespaces#2{##1}\unskip\@@italiccorr#4}
            % this is added => this disturbs hyperref:
            \__chemmacros_record_for_lor:nnnnn
              {#1} {#3} {#2} {##1} {#4}
          }
      }
  }

\tl_new:N \g__chemmacros_reaction_description_tl

\cs_new_protected:Npn \chemmacros_add_reaction_description:n #1
  {
    \tl_if_blank:nF {#1}
      { \tl_gset:Nn \g__chemmacros_reaction_description_tl {:~#1} }
  }

\NewDocumentCommand \AddRxnDesc {m}
  { \chemmacros_add_reaction_description:n {#1} }

% define \listofreactions
\tl_new:N  \l__chemmacros_reaction_lorname_tl
\tl_new:N  \reactionlistname
\tl_new:N  \l__chemmacros_reaction_heading_tl

\cs_new:Npn \__chemmacros_reaction_heading:n #1
  { \l__chemmacros_reaction_heading_tl {#1} }
\cs_generate_variant:Nn \__chemmacros_reaction_heading:n { V }

\ChemCompatibilityTo{5.6}
\tl_set:Nn \l__chemmacros_reaction_lorname_tl
  { \chemmacros_translate:n {reaction} }
\EndChemCompatibility
\ChemCompatibilityFrom{5.6}
\tl_set:Nn \l__chemmacros_reaction_lorname_tl
  { \chemmacros_translate:n {Reaction} }
\EndChemCompatibility

\tl_set:Nn \reactionlistname { \chemmacros_translate:n {list-of-reactions} }

\chemmacros_define_keys:nn {reactions}
  {
    list-name .tl_set:N = \reactionlistname ,
    list-entry .tl_set:N = \l__chemmacros_reaction_lorname_tl ,
  }
\ChemCompatibilityFrom{5.2}
\chemmacros_define_keys:nn {reactions}
  {
    list-heading-cmd .code:n =
      \cs_set_protected:Npn \__chemmacros_reaction_heading:n ##1 {#1}
  }
\EndChemCompatibility

\cs_if_exist:NTF \chapter
  {
    \chemmacros_if_compatibility:nnTF {>=} {5.2}
      {
        \chemmacros_set_keys:nn {reactions}
          { list-heading-cmd = \chapter* {#1} }
      }
      { \cs_set_protected:Npn \__chemmacros_reaction_heading:n { \chapter* } }
  }
  {
    \chemmacros_if_compatibility:nnTF {>=} {5.2}
      {
        \chemmacros_set_keys:nn {reactions}
          { list-heading-cmd = \section* {#1} }
      }
      { \cs_set_protected:Npn \__chemmacros_reaction_heading:n { \section* } }
  }

\cs_new_protected:Npn \listofreactions
  {
    \__chemmacros_reaction_heading:V \reactionlistname
    \@starttoc {lor}
  }

\ChemCompatibilityTo{5.6}
\cs_new_protected:Npn \l@reaction #1#2
  { \@dottedtocline {1} {1.5em} {2.3em} {#1} {#2} }
\EndChemCompatibility

\ChemCompatibilityFrom{5.6}
\cs_new_eq:NN \l@reaction \l@figure

\bool_new:N \l__chemmacros_reactions_tocbasic_bool
\cs_if_exist:NT \KOMAClassName
  { \bool_set_true:N \l__chemmacros_reactions_tocbasic_bool }

\tl_new:N \l__chemmacros_reactions_tag_open_tl
\tl_new:N \l__chemmacros_reactions_tag_close_tl
\tl_new:N \l__chemmacros_reactions_before_tag_tl

\chemmacros_define_keys:nn {reactions}
  {
    tocbasic   .bool_set:N = \l__chemmacros_reactions_tocbasic_bool ,
    tag-open   .tl_set:N   = \l__chemmacros_reactions_tag_open_tl ,
    tag-open   .initial:n  = \{ ,
    tag-close  .tl_set:N   = \l__chemmacros_reactions_tag_close_tl ,
    tag-close  .initial:n  = \} ,
    before-tag .tl_set:N   = \l__chemmacros_reactions_before_tag_tl
  }

\AtEndPreamble
  {
    \bool_lazy_or:nnT
      { \chemmacros_if_package_loaded_p:n {tocbasic} }
      { \l__chemmacros_reactions_tocbasic_bool }
      {
        \RequirePackage {tocbasic}
        \addtotoclist [float] {lor}
        \cs_set_protected:Npn \listofreactions { \listoftoc {lor} }
        \cs_new:Npn \listoflorname { \reactionlistname }
      }
  }

\ChemCleverefSupport {reaction}
  { \chemmacros_translate:n {reaction} }
  [ \chemmacros_translate:n {Reaction} ]
  { \chemmacros_translate:n {reactions} }
  [ \chemmacros_translate:n {Reactions} ]

\AfterPackage* {cleveref}
  {
    \creflabelformat {reaction}
      {
        #2
        \l__chemmacros_reactions_tag_open_tl
        #1
        \l__chemmacros_reactions_tag_close_tl
        #3
      }
  }

\ChemFancyrefSupport {rct}
  { \chemmacros_translate:n {reaction} }
  [ \chemmacros_translate:n {Reaction} ]
\EndChemCompatibility
  
% create new tagform
\ChemCompatibilityTo{5.6}
\newtagform {reaction} {\{} {\}}
\EndChemCompatibility
\ChemCompatibilityFrom{5.6}
\newtagform {reaction}
  [\l__chemmacros_reactions_before_tag_tl]
  {\l__chemmacros_reactions_tag_open_tl}
  {\l__chemmacros_reactions_tag_close_tl}
\EndChemCompatibility
\newcounter {chemmacros_save_reaction}
\newcounter {reaction}

\ChemCompatibilityTo{5.6}
\cs_new_protected:Npn \__chemmacros_begin_reaction:
  {
    % create individual names for `hyperref':
    \bool_if:NT \l__chemmacros_hyperref_bool
      {
        \cs_set:Npn \theHequation
          { R . \theHsection . \arabic {reaction} }
      }
    % enable labelformat `reaction':
    \bool_if:NT \l__chemmacros_varioref_bool
      { \cs_set_eq:NN \p@equation \p@reaction }
    \setcounter {chemmacros_save_reaction} { \value {equation} }
    \setcounter {equation} { \value {reaction} }
    \usetagform {reaction}
  }
\EndChemCompatibility

\ChemCompatibilityFrom{5.6}
\cs_new_protected:Npn \__chemmacros_begin_reaction:
  {
    \patchcmd \thereaction {reaction} {equation} {} {}
    \cs_set_eq:NN \theequation \thereaction
    \cs_set_eq:NN \r@equation \r@reaction
    \cs_set_eq:NN \p@equation \p@reaction
    \cs_set:Npn \theHequation { R . \theHsection . \theequation }
    \setcounter {chemmacros_save_reaction} { \value {equation} }
    \setcounter {equation} { \value {reaction} }
    \chemmacros_if_package_loaded:nT {cleveref}
      { \crefalias {equation} {reaction} }
    \usetagform {reaction}
  }
\EndChemCompatibility

% switch back to equation tags
\cs_new_protected:Npn \__chemmacros_end_reaction:
  {
    \setcounter {reaction} { \value {equation} }
    \setcounter {equation} { \value {chemmacros_save_reaction} }
  }

\tl_new:N \l__chemmacros_reactions_args_tl

\cs_new_protected:Npn \__chemmacros_reactions_build_args:n #1
  { \tl_put_right:Nn \l__chemmacros_reactions_args_tl { {## #1} } }

\cs_new_protected:Npn \chemmacros_define_reaction:nnn #1#2#3
  {
    \int_compare:nNnT {#3+0} > {0}
      {
        \tl_clear:N \l__chemmacros_reactions_args_tl
        \int_step_function:nnnN {2} {1} {#3+1} \__chemmacros_reactions_build_args:n
      }
    \chemmacros_declare_reaction_env:nnnV {#1} {#2} {#3} \l__chemmacros_reactions_args_tl
  }

% #1: chem
% #2: math
% #3: args number
% #4: argument list ({#2}{#3}...)
\cs_new_protected:Npn \chemmacros_declare_reaction_env:nnnn #1#2#3#4
  {
    \exp_args:Nnx \DeclareDocumentEnvironment {#1}
      { \int_compare:nT { #3+0 = 0 } {!} O{} \prg_replicate:nn {#3+0} {m} }
      {
        \chemmacros_add_reaction_description:n {##1}
        \__chemmacros_begin_reaction:
        \chemmacros_reaction_read:nnw {#2} {#4}
      }
      {
        \__chemmacros_end_reaction:
        \ignorespacesafterend
      }
  }
\cs_generate_variant:Nn \chemmacros_declare_reaction_env:nnnn {nnnV}

\ChemCompatibilityTo{5.6}
\cs_new_protected:Npn \chemmacros_reaction_read:nnw #1#2#3 \end
  {
    \begin{#1}#2
      \chemmacros_reaction:n {#3}
    \end{#1}
    \end
  }
\EndChemCompatibility

\ChemCompatibilityFrom{5.6}
\cs_new_protected:Npn \chemmacros_reaction_read:nnw #1#2#3 \end
  {
    \tl_clear:N \l__chemmacros_tmpa_tl
    \seq_clear:N \l__chemmacros_tmpc_seq
    \seq_set_split:Nnn \l__chemmacros_tmpa_seq {\\} {#3}
    \int_set:Nn \l__chemmacros_tmpa_int
      { \seq_count:N \l__chemmacros_tmpa_seq }
    \int_zero:N \l__chemmacros_tmpb_int
    \seq_map_inline:Nn \l__chemmacros_tmpa_seq
      {
        \int_incr:N \l__chemmacros_tmpb_int
        \seq_clear:N \l__chemmacros_tmpc_seq
        \seq_set_split:Nnn \l__chemmacros_tmpb_seq {&} {##1}
        \seq_map_inline:Nn \l__chemmacros_tmpb_seq
          {
            \seq_put_right:Nn \l__chemmacros_tmpc_seq
              { \chemmacros_reaction:n {####1} }
          }
        \tl_put_right:Nx \l__chemmacros_tmpa_tl
          { \seq_use:Nn \l__chemmacros_tmpc_seq {&} }
        \int_compare:nF
          { \l__chemmacros_tmpa_int = \l__chemmacros_tmpb_int }
          { \tl_put_right:Nn \l__chemmacros_tmpa_tl {\\} }
      }
    \chemmacros_reaction_write:nnV {#1} {#2} \l__chemmacros_tmpa_tl
    \end
  }

\cs_new_protected:Npn \chemmacros_reaction_write:nnn #1#2#3
  {
    \begin{#1}#2
      #3
    \end{#1}
  }
\cs_generate_variant:Nn \chemmacros_reaction_write:nnn { nnV }
\EndChemCompatibility

\NewChemMacroset* {Reaction} {mO{}m}
  { \chemmacros_define_reaction:nnn {#1} {#3} {#2} }

\NewChemReaction {reaction}   {equation}
\NewChemReaction {reaction*}  {equation*}
\NewChemReaction {reactions}  {align}
\NewChemReaction {reactions*} {align*}

% --------------------------------------------------------------------------
\ChemCompatibilityTo{5.6}
\DeclareTranslationFallback     {list-of-reactions} {List~ of~ Reactions}
\DeclareTranslation {English}   {list-of-reactions} {List~ of~ Reactions}
\DeclareTranslation {German}    {list-of-reactions} {Reaktionsverzeichnis}
\DeclareTranslation {Italian}   {list-of-reactions} {Elenco~ delle~ reazioni}
\DeclareTranslation {French}    {list-of-reactions} {Table~ des~ r\'{e}actions}
\DeclareTranslation {Dutch}     {list-of-reactions} {Lijst~ van~ reacties}

\DeclareTranslationFallback     {reaction} {Reaction}
\DeclareTranslation {English}   {reaction} {Reaction}
\DeclareTranslation {German}    {reaction} {Reaktion}
\DeclareTranslation {Italian}   {reaction} {Reazione}
\DeclareTranslation {French}    {reaction} {R\'{e}action}
\DeclareTranslation {Dutch}     {reaction} {Reactie}
\EndChemCompatibility

\ChemCompatibilityFrom{5.6}
\chemmacros_declare_translations:nn {list-of-reactions}
  {
    fallback  = List~ of~ Reactions ,
    English   = List~ of~ Reactions ,
    German    = Reaktionsverzeichnis ,
    Italian   = Elenco~ delle~ reazioni ,
    French    = Table~ des~ r\'{e}actions ,
    Dutch     = Lijst~ van~ reacties ,
    Norwegian = Reaksjonsliste ,
    Nynorsk   = Reaksjonsliste
  }

\chemmacros_declare_translations:nn {reaction}
  {
    fallback  = reaction ,
    English   = reaction ,
    German    = Reaktion ,
    Italian   = reazione ,
    French    = r\'{e}action ,
    Dutch     = reactie ,
    Norwegian = reaksjon ,
    Nynorsk   = reaksjon
  }

\chemmacros_declare_translations:nn {reactions}
  {
    fallback  = reactions ,
    English   = reactions ,
    German    = Reaktionen ,
    Italian   = reazioni ,
    French    = r\'{e}actions ,
    Dutch     = reacties ,
    Norwegian = reaksjoner ,
	Nynorsk   = reaksjonar
  }

\chemmacros_declare_translations:nn {Reaction}
  {
    fallback  = Reaction ,
    English   = Reaction ,
    German    = Reaktion ,
    Italian   = Reazione ,
    French    = R\'{e}action ,
    Dutch     = Reactie ,
    Norwegian = Reaksjon ,
    Nynorsk   = Reaksjon
  }

\chemmacros_declare_translations:nn {Reactions}
  {
    fallback = Reactions ,
    English  = Reactions ,
    German   = Reaktionen ,
    Italian  = Reazioni ,
    French   = R\'{e}actions ,
    Dutch    = Reacties ,
    Norwegian = Reaksjoner ,
    Nynorsk   = Reaksjonar
 }
\EndChemCompatibility
% --------------------------------------------------------------------------
\file_input_stop:

2015/09/15 - adapt to `method' option => do not use chemformula's macros
             directly
2015/10/14 - new option `list-heading-cmd'
2016/02/09 - added \ignorespacesafterend to environments
2016/03/17 - tocbasic integration of lor
           - add missing compatibility check for the usage of the
             `list-heading-cmd' option
2016/04/02 - adapt to new formula methods
2016/04/27 - correct \__chemmacros_begin_reaction: so tags obey \thereaction
           - add cleveref support
           - add fancyref support
           - moved translations from lang module to reactions module
2016/05/04 - options `tag-open', `tag-close' and `before-tag'
2019/09/23 - added Norwegian translations
2019/09/27 - change `O{}' argument of reactions into `!O{}'
2020/02/02 - lazy boolean evaluation
