%%
%% This is file `projlib-math.sty',
%% generated with the docstrip utility.
%%
%% Copyright (C) 2021-2024 by Jinwen XU
%% 
%% This is part of the ProjLib Toolkit.
%% 
%% This work may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License, either version 1.3c of this license or (at
%% your option) any later version. The latest version of this license is in
%% 
%%     http://www.latex-project.org/lppl.txt
%% 
%% and version 1.3c or later is part of all distributions of LaTeX version
%% 2005/12/01 or later.
%% 
\NeedsTeXFormat{LaTeX2e}[2022-06-01]
\ProvidesExplPackage
  {projlib-math}
  {2024/03/01} {}
  {Efficient math setup}

\keys_define:nn { projlib-math }
  {
    , unknown     .code:n     = {}
  }
\ProcessKeyOptions [ projlib-math ]

\providecommand* \ProvideCommandCopy
  {
    \declare@commandcopy{\@firstofone}{\@firstoftwo{}}
  }

\RequirePackage { mathtools }
\RequirePackage { mathrsfs }
\PassOptionsToPackage { warnings-off = { mathtools-colon, mathtools-overbracket } } { unicode-math }
\IfPackageLoadedTF { unicode-math } {} { \RequirePackage { amssymb } }

\msg_new:nnn { projlib-math }
  { operator-not-define }
  { The~math~operator~"\iow_char:N \\#1"~cannot~be~defined,~a~command~with~the~same~name~has~already~existed. }

\keys_define:nn { projlib-math-operator }
  {
    , style        .tl_set:N     = \l__projlib_math_operator_style_tl
    , unknown      .code:n       = {}
  }

\cs_new_protected:Nn \projlib_math_define_operator:nnn
  % #1 = bool for star or empty
  % #2 = list of operators
  % #3 = the option
  {
    \tl_clear:N \l__projlib_math_operator_style_tl
    \keys_set:nn { projlib-math-operator } { #3 }
    \clist_map_inline:nn { #2 }
      {
        \str_if_in:nnTF { ##1 } { = }
          {
            \seq_set_split:Nnn \l_tmpa_seq { = } { ##1 }
            \__projlib_math_define_operator:nee { #1 } { \seq_item:Nn \l_tmpa_seq { 1 } } { \seq_item:Nn \l_tmpa_seq { 2 } }
          }
          {
            \__projlib_math_define_operator:nee { #1 } { ##1 } { ##1 }
          }
      }
  }

\cs_new_protected:Nn \__projlib_math_define_operator:nnn
  % #1 = bool for star or empty
  % #2 = the operator
  % #3 = the content
  {
    \cs_if_exist:cTF { #2 }
      {
        \msg_warning:nnn  { projlib-math } { operator-not-define } { #2 }
      }
      {
        \bool_if:NTF #1
          {
            \exp_args:Nnf \use:n
              { \exp_args:Nnc \use:n { \DeclareMathOperator* } { #2 } }
          }
          {
            \exp_args:Nnf \use:n
              { \exp_args:Nc \DeclareMathOperator { #2 } }
          }
          % This is the f-argument of  \exp_args:Nnf :
          {
            \exp_args:NnV \use:nn
              { \exp_stop_f: }
              { \l__projlib_math_operator_style_tl } { #3 }
          }
      }
  }
\cs_generate_variant:Nn \__projlib_math_define_operator:nnn { nee }

\NewDocumentCommand \ProjLibDefineMathOperator { s O{} m O{} }
  {
    \tl_if_blank:nTF { #2 }
      {
        \projlib_math_define_operator:nnn { #1 } { #3 } { #4 }
      }
      {
        \projlib_math_define_operator:nnn { #1 } { #3 } { #2 }
      }
  }

\ProvideCommandCopy \DefineMathOperator \ProjLibDefineMathOperator
\ProvideCommandCopy \DefineOperator \ProjLibDefineMathOperator

\msg_new:nnn { projlib-math }
  { symbol-not-define }
  { The~symbol~/~shortcut~"\iow_char:N \\#1"~cannot~be~defined,~a~command~with~the~same~name~has~already~existed. }

\msg_new:nnn { projlib-math }
  { symbol-type-not-define }
  { The~symbol~/~shortcut~type~"#1"~is~not~available,~a~command~with~the~same~name~has~already~existed. }

\keys_define:nn { projlib-math-symbol }
  {
    , prefix       .clist_set:N  = \l__projlib_math_symbol_prefix_clist
    , type         .tl_set:N     = \l__projlib_math_symbol_type_tl
    , style        .tl_set:N     = \l__projlib_math_symbol_style_tl
    , unknown      .code:n       = {}
  }

\cs_new_protected:Nn \projlib_math_define_symbol:nnn
  % #1 = bool for star or empty
  % (currently the starred version is the same as normal version)
  % #2 = list of symbols
  % #3 = the option
  {
    \clist_clear:N \l__projlib_math_symbol_prefix_clist
    \tl_clear:N \l__projlib_math_symbol_type_tl
    \tl_set:Nn \l__projlib_math_symbol_style_tl { \mathrm }
    \keys_set:nn { projlib-math-symbol } { #3 }
    \tl_if_empty:NF \l__projlib_math_symbol_type_tl
      {
        \cs_if_exist:cTF { \l__projlib_math_symbol_type_tl }
          {
            \exp_args:Nne \use:n
              { \msg_warning:nnn  { projlib-math } { symbol-type-not-define } }
              { \l__projlib_math_symbol_type_tl }
          }
          {
            \exp_args:Nno \use:n
              {
                \exp_args:Nc \NewDocumentCommand { \l__projlib_math_symbol_type_tl } { m }
              }
              {
                \l__projlib_math_symbol_style_tl { ##1 }
              }
          }
      }
    \clist_map_inline:nn { #2 }
      {
        \str_if_in:nnTF { ##1 } { = }
          {
            \seq_set_split:Nnn \l_tmpa_seq { = } { ##1 }
            \clist_if_empty:NTF \l__projlib_math_symbol_prefix_clist
              {
                \__projlib_math_define_symbol:ee { \seq_item:Nn \l_tmpa_seq { 1 } } { \seq_item:Nn \l_tmpa_seq { 2 } }
              }
              {
                \clist_map_inline:Nn \l__projlib_math_symbol_prefix_clist
                  {
                    \__projlib_math_define_symbol:ee { ####1 \seq_item:Nn \l_tmpa_seq { 1 } } { \seq_item:Nn \l_tmpa_seq { 2 } }
                  }
              }
          }
          {
            \clist_if_empty:NTF \l__projlib_math_symbol_prefix_clist
              {
                \__projlib_math_define_symbol:ee { ##1 } { ##1 }
              }
              {
                \clist_map_inline:Nn \l__projlib_math_symbol_prefix_clist
                  {
                    \__projlib_math_define_symbol:ee { ####1 ##1 } { ##1 }
                  }
              }
          }
      }
  }

\cs_new_protected:Nn \__projlib_math_define_symbol:nn
  % #1 = command name
  % #2 = the content
  {
    \cs_if_exist:cTF { #1 }
      {
        \msg_warning:nnn { projlib-math } { symbol-not-define } { #1 }
      }
      {
        \exp_args:Nno \use:n
          { \exp_args:Nc \NewDocumentCommand { #1 } {} }
          { \l__projlib_math_symbol_style_tl { #2 } }
      }
  }
\cs_generate_variant:Nn \__projlib_math_define_symbol:nn { ee }

\NewDocumentCommand \ProjLibDefineMathSymbol { s O{} m O{} }
  {
    \tl_if_blank:nTF { #2 }
      {
        \projlib_math_define_symbol:nnn { #1 } { #3 } { #4 }
      }
      {
        \projlib_math_define_symbol:nnn { #1 } { #3 } { #2 }
      }
  }
\ProvideCommandCopy \DefineMathSymbol \ProjLibDefineMathSymbol
\ProvideCommandCopy \DefineShortcut \ProjLibDefineMathSymbol

\cs_new:Nn \projlib_math_redefine_in_math_mode:Nn
  {
    \exp_args:Nc \NewCommandCopy { projlib_math_original_ \cs_to_str:N #1 : } #1
    \RenewDocumentCommand #1 { }
      {
        \mode_if_math:TF
          { #2 }
          { \use:c { projlib_math_original_ \cs_to_str:N #1 : } }
      }
  }

\NewDocumentCommand \ProjLibRedefineInMathMode { m m }
  {
    \projlib_math_redefine_in_math_mode:Nn #1 { #2 }
  }

\ProvideCommandCopy \RedefineInMathMode \ProjLibRedefineInMathMode

\cs_new:Nn \__projlib_math_list_of_symbols_entry:nnnn
  % #1 = column one width
  % #2 = column two width
  % #3 = symbol
  % #4 = description
  {
    \noindent
    \begin { tabular } { p{#1} p{#2} }
      \parbox [t] { #1 } { #3 } & \parbox [t] { #2 } { #4 }
    \end { tabular }
    \par
    \skip_vertical:n { -\parskip }
  }

\cs_new:Nn \projlib_math_list_of_symbols:nnn
  % #1 = column one width
  % #2 = column two width
  % #3 = key-val list
  {
    \keyval_parse:nnn
      { \use_none:n }
      { \__projlib_math_list_of_symbols_entry:nnnn { #1 } { #2 } }
      { #3 }
  }

\NewDocumentCommand \ProjLibListOfSymbols { O{0.17\textwidth} O{0.75\textwidth} m }
  {
    \projlib_math_list_of_symbols:nnn { #1 } { #2 } { #3 }
  }

\ProvideCommandCopy \ListOfSymbols \ProjLibListOfSymbols

\endinput
%%
%% End of file `projlib-math.sty'.
