4

MWE:

\documentclass{article}
\usepackage{mathtools}
\begin{document}
\ExplSyntaxOn
\tl_new:N \g__mymodule_env_name_tl
\tl_new:N \g__mymodule_env_args_tl
% Defaults
\tl_set:Nn \g__mymodule_env_name_tl { matrix }
\keys_define:nn { mymodule/math } {
    ,env     .tl_set:N = \g__mymodule_env_name_tl
    ,env-args .tl_set:N = \g__mymodule_env_args_tl
}
\NewDocumentCommand{\mat}{ O{} m }{
    \keys_set:nn { mymodule/math } { #1 }
    \begin{\g__mymodule_env_name_tl}\g__mymodule_env_args_tl
        #2
    \end{\g__mymodule_env_name_tl}
}
\NewDocumentEnvironment{funnymatrix}{ s O{} m }{
    \begin{matrix}
    \text
    {
        (Star:~\bool_if:nTF { #1 } { T } { F })
        (Optional:~#2)
        (Mandatory:~#3)
    }
}{
    \end{matrix}
} 
\ExplSyntaxOff
\section{Current output}
Environment \verb|matrix|:
\[\mat{1}\]
Environment \verb|matrix*| with optional argument:
\[\mat[env=matrix*,env-args=[l]]{1}\]
Environment \verb|funnymatrix| with a star, mandatory and optional argument:
\[\mat[env=funnymatrix,env-args=*[optional]{mandatory}]{1}\]
\section{Desired output}
Environment \verb|matrix|:
\[\mat{1}\]
Environment \verb|matrix*| with optional argument:
\[\begin{matrix*}[l]
    1
\end{matrix*}\]
Environment \verb|funnymatrix| with a star, mandatory and optional argument:
\[\begin{funnymatrix}*[optional]{mandatory}
    1
\end{funnymatrix}\]
\end{document}

enter image description here

Edit

Skillmon and egreg's solutions work very nicely, but they both seem to give a fatal error when compiling \mat[env=NiceArray,env-args={cc|cc}[baseline=line-3]]{1 & 1 & 1 & 1} (with the package nicematrix). How can either solution be modified such that this works?

3
  • Is it clearer now? Commented 23 hours ago
  • I think in general it would be nice to have versions of the optional arg specs that do a \romannumeral-style expansion ahead before peeking for the optional [ (or the corresponding character). Commented 23 hours ago
  • @Grass: Your example \mat[env=NiceArray,env-args={cc|cc}[baseline=line-3]]{1 & 1 & 1 & 1}, has two problems: line-3 does not exist because your matrix has only one row and you should also add braces for the whole value : \mat[env=NiceArray,env-args={{cc|cc}[baseline=line-3]]{1 & 1 & 1 & 1}} to protect the inner-most = Commented 2 hours ago

2 Answers 2

4

Expand the macro before the environment searches for any trailing arguments.

As @egreg pointed out in his answer in the meantime you should pay attention to naming conventions. g indicates a globally changed variable but your usage is local, so your variables should be named l. Also you should either group the assignments to your key-variables or reset them to defaults.

\documentclass{article}

\usepackage{mathtools}

\ExplSyntaxOn
\tl_new:N \l__mymodule_env_name_tl
\tl_new:N \l__mymodule_env_args_tl
% Defaults
\tl_set:Nn \l__mymodule_env_name_tl { matrix }
\keys_define:nn { mymodule/math } {
    ,env     .tl_set:N = \l__mymodule_env_name_tl
    ,env-args .tl_set:N = \l__mymodule_env_args_tl
}
\NewDocumentCommand{\mat}{ O{} m }{
  \group_begin:
    \keys_set:nn { mymodule/math } { #1 }
    \use:e
      {
        \exp_not:n { \begin { \l__mymodule_env_name_tl } }
          \exp_not:V \l__mymodule_env_args_tl
      }
        #2
    \end { \l__mymodule_env_name_tl }
  \group_end:
}
\NewDocumentEnvironment{funnymatrix}{ s O{} m }{
    \begin{matrix}
    \text
    {
        (Star:~\bool_if:nTF { #1 } { T } { F })
        (Optional:~#2)
        (Mandatory:~#3)
    }
}{
    \end{matrix}
}
\ExplSyntaxOff

\begin{document}
\section{Current output}
Environment \verb|matrix|:
\[\mat{1}\]
Environment \verb|matrix*| with optional argument:
\[\mat[env=matrix*,env-args=[l]]{1}\]
Environment \verb|funnymatrix| with a star, mandatory and optional argument:
\[\mat[env=funnymatrix,env-args=*[optional]{mandatory}]{1}\]
\section{Desired output}
Environment \verb|matrix|:
\[\mat{1}\]
Environment \verb|matrix*| with optional argument:
\[\begin{matrix*}[l]
    1
\end{matrix*}\]
Environment \verb|funnymatrix| with a star, mandatory and optional argument:
\[\begin{funnymatrix}*[optional]{mandatory}
    1
\end{funnymatrix}\]
\end{document}

Advertisement: you could have much simpler code if you used a key=value system that doesn't use assignments (disclaimer: I'm the author of expkv-cs), at least for small things with few keys this works out pretty nicely:

\documentclass{article}

\usepackage{mathtools}
\usepackage{expkv-cs}

\NewDocumentCommand\mat{O{} m}{\matKV{#1}{#2}}
\ekvcSplitAndForward\matKV\matDO
  {
     env = matrix
    ,env-args = {}
  }
\newcommand\matDO[3]{\begin{#1}#2#3\end{#1}}

\NewDocumentEnvironment{funnymatrix}{ s O{} m }{%
    \begin{matrix}
      \text
        {%
          (Star: \IfBooleanTF{#1}{T}{F})
          (Optional: #2)
          (Mandatory: #3)
        }%
  }{%
    \end{matrix}%
  }

\begin{document}
\section{Current output}
Environment \verb|matrix|:
\[\mat{1}\]
Environment \verb|matrix*| with optional argument:
\[\mat[env=matrix*,env-args=[l]]{1}\]
Environment \verb|funnymatrix| with a star, mandatory and optional argument:
\[\mat[env=funnymatrix,env-args=*[optional]{mandatory}]{1}\]
\section{Desired output}
Environment \verb|matrix|:
\[\mat{1}\]
Environment \verb|matrix*| with optional argument:
\[\begin{matrix*}[l]
    1
\end{matrix*}\]
Environment \verb|funnymatrix| with a star, mandatory and optional argument:
\[\begin{funnymatrix}*[optional]{mandatory}
    1
\end{funnymatrix}\]
\end{document}
6
  • Woah, thanks! This seems like exactly what I want! I'll inspect it a bit tmr and accept the answer. Commented 23 hours ago
  • @Grass you should not set global variables locally. Commented 20 hours ago
  • Hm this doesn't seem to work in all cases: compiling \mat[env=NiceArray,env-args={cc|cc}[baseline=line-3]]{1 & 1 & 1 & 1} gives a fatal error. Commented 13 hours ago
  • @Grass You need env-args={{cc|cc}[baseline=line-3]} so as to hide the =. At least, with my solution this works. Commented 5 hours ago
  • @egreg same here with the L3 based one. With expkv-cs it works even without the extra braces unless you also use , in the argument to env-args. Commented 3 hours ago
3

Use variants!

Also, the construction should be grouped and the variables should have the \l prefix rather than \g.

\documentclass{article}
\usepackage{mathtools}

\ExplSyntaxOn

\keys_define:nn { grass_matrix/math }
  {
    env      .tl_set:N  = \l__grass_matrix_env_name_tl ,
    env-args .tl_set:N  = \l__grass_matrix_env_args_tl ,
    env      .initial:n = matrix,
  }

\NewDocumentCommand{\mat}{ O{} m }
  {
    \group_begin:
    \keys_set:nn { grass_matrix/math } {#1}
    \__grass_matrix_do:VVn \l__grass_matrix_env_name_tl \l__grass_matrix_env_args_tl {#2}
    \group_end:
  }

\cs_new_protected:Nn \__grass_matrix_do:nnn
 {
  \tl_if_blank:nTF {#2} { \begin{#1} } { \begin{#1}#2 } #3 \end{#1}
 }
\cs_generate_variant:Nn \__grass_matrix_do:nnn {VV}

\ExplSyntaxOff

\NewDocumentEnvironment{funnymatrix}{ s O{} m }{%
  \begin{matrix}
  \text{%
    (Star:~\IfBooleanTF { #1 } { T } { F })
    (Optional:~#2)
    (Mandatory:~#3)
  }
}{\end{matrix}}

\begin{document}

\section{Current output}

Environment \verb|matrix|:
\[\mat{1 \\ 11 \\ 111}\]

Environment \verb|matrix*| with optional argument:
\[\mat[env=matrix*,env-args=[l]]{1 \\ 11 \\ 111}\]

Environment \verb|funnymatrix| with a star, mandatory and optional argument:
\[\mat[env=funnymatrix,env-args=*[optional]{mandatory}]{1 \\ 11 \\ 111}\]

\section{Desired output}

Environment \verb|matrix|:
\[\mat{1 \\ 11 \\ 111}\]

Environment \verb|matrix*| with optional argument:
\[\begin{matrix*}[l]
    1 \\ 11 \\ 111
\end{matrix*}\]

Environment \verb|funnymatrix| with a star, mandatory and optional argument:
\[\begin{funnymatrix}*[optional]{mandatory}
    1 \\ 11 \\ 111
\end{funnymatrix}\]

\end{document}

output

Note that this wouldn't work if you plan to nest your \mat commands. For this case, change the main commands into

\keys_define:nn { grass_matrix/math }
  {
    env      .tl_set:N  = \l__grass_matrix_env_name_tl ,
    env-args .tl_set:N  = \l__grass_matrix_env_args_tl ,
  }

\NewDocumentCommand{\mat}{ O{} m }
  {
    \group_begin:
    \keys_set:nn { grass_matrix/math } {env=matrix,env-args=,#1}
    \__grass_matrix_do:VVn \l__grass_matrix_env_name_tl \l__grass_matrix_env_args_tl {#2}
    \group_end:
  }

so as to always reinitialize at a fixed state.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.