\NeedsTeXFormat{LaTeX2e}[2020-10-01]
\RequirePackage{l3keys2e}
\ProvidesExplPackage
  {projlib-math}
  {2022/02/26} {}
  {Efficient math setup}

\keys_define:nn { projlib-math }
  {
    , unknown     .code:n     = {}
  }
\ProcessKeysOptions { projlib-math }

\RequirePackage { mathtools }
\RequirePackage { mathrsfs }
\PassOptionsToPackage { warnings-off = { mathtools-colon, mathtools-overbracket } } { unicode-math }
\@ifpackageloaded { 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 \DefineOperator { 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 }
      }
  }


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

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

\keys_define:nn { projlib-math-shortcut }
  {
    , prefix       .clist_set:N  = \l__projlib_math_shortcut_prefix_clist
    , type         .tl_set:N     = \l__projlib_math_shortcut_type_tl
    , style        .tl_set:N     = \l__projlib_math_shortcut_style_tl
    , unknown      .code:n       = {}
  }

\cs_new_protected:Nn \projlib_math_define_shortcut:nnn
  % #1 = bool for star or empty
  % (currently the starred version is the same as normal version)
  % #2 = list of shortcuts
  % #3 = the option
  {
    \clist_clear:N \l__projlib_math_shortcut_prefix_clist
    \tl_clear:N \l__projlib_math_shortcut_type_tl
    \tl_clear:N \l__projlib_math_shortcut_style_tl
    \keys_set:nn { projlib-math-shortcut } { #3 }
    \tl_if_empty:NF \l__projlib_math_shortcut_type_tl
      {
        \cs_if_exist:cTF { \l__projlib_math_shortcut_type_tl }
          {
            \exp_args:Nne \use:n
              { \msg_warning:nnn  { projlib-math } { shortcut-type-not-define } }
              { \l__projlib_math_shortcut_type_tl }
          }
          {
            \exp_args:Nno \use:n
              {
                \exp_args:Nc \NewDocumentCommand { \l__projlib_math_shortcut_type_tl } { m }
              }
              {
                \l__projlib_math_shortcut_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_shortcut_prefix_clist
              {
                \__projlib_math_define_shortcut:ee { \seq_item:Nn \l_tmpa_seq { 1 } } { \seq_item:Nn \l_tmpa_seq { 2 } }
              }
              {
                \clist_map_inline:Nn \l__projlib_math_shortcut_prefix_clist
                  {
                    \__projlib_math_define_shortcut:ee { ####1 \seq_item:Nn \l_tmpa_seq { 1 } } { \seq_item:Nn \l_tmpa_seq { 2 } }
                  }
              }
          }
          {
            \clist_if_empty:NTF \l__projlib_math_shortcut_prefix_clist
              {
                \__projlib_math_define_shortcut:ee { ##1 } { ##1 }
              }
              {
                \clist_map_inline:Nn \l__projlib_math_shortcut_prefix_clist
                  {
                    \__projlib_math_define_shortcut:ee { ####1 ##1 } { ##1 }
                  }
              }
          }
      }
  }

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

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

%===============================
% -- Some possible operators --
%===============================
% \DefineOperator { ord, card, car, disc }  [ style = \mathsf ]
% \DefineOperator { id, Id, Ker, Image = Im } [ style = \mathsf ]
% \DefineOperator { Orb, Stab, Fix } [ style = \mathsf ]
% \DefineOperator { Hom, Aut, End, Mat } [ style = \mathsf ]
% \DefineOperator { Spec, Spm, Ann } [ style = \mathsf ]
% \DefineOperator*{ Lim, Max, Min } [ style = \mathsf ]

%===============================
% -- Some possible shortcuts --
%===============================
% \DefineShortcut [ type = category, style = \mathbf ]
%   {
%     Set, Grp, Ring, Top
%   }
% \DefineShortcut [ style = \mathbb ]
%   {
%     N, Z, Q, R, C, F, A
%   }
% \DefineShortcut [ prefix = bb, style = \mathbb ]
%   {
%     A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
%   }
% \DefineShortcut [ prefix = { mf, frak }, style = \mathfrak ]
%   {
%     A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
%     a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
%   }
% \DefineShortcut [ prefix = { mc, cal }, style = \mathcal ]
%   {
%     A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
%   }
% \DefineShortcut [ prefix = { ms, scr }, style = \mathscr ]
%   {
%     A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
%   }

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