I am trying to combine the solutions from
- How to properly use \collect@body within align environment
- Xparse t argument type (underscore with optional parameter)
to parse optional parameters following the end of an environment. There are only three possible cases with these options:
- A subscript:
_{subscript} - A superscript:
^{superscript} - Both subscript and superscript:
_{subscript}^{superscript}
The case of ^{subscript}_{superscript} is not required.
I would have thought that adding the optional parameters to the \@MatrixWithParen helper macro would have sufficed, but it seems that the options don't get to that macro.
Attempted Solutions:
Use
\collect@bodyto invoke\@MatrixWithParenwhich looks for optional parameters. Based on what egreg comments, this is not the way to go. The MWE yields what is on the left, and the desired result is on the right:Store the content from
\collect@bodyin a macro and use\AfterEndEnvironmentto invoke a macro to parse the optional parameters. This also seems that the optional parameters are not available to the macro specified to be executed by\AfterEndEnvironment. Similarly\aftergroupand\AtEndEnvironmentalso did not work:This non-solution has additional issues if there is more than one
bmatrixenvironemnt, but I think that could be solved with additional programming. Trying to keep this question focused on parsing optional parameters following anend{environment}.Another thought I had was to modify
\collect@bodyso that invokes a macro that allows for two optional parameters, but that is beyond my understanding.
Notes:
- This question is not how to get a matrix with
()instead of[](whichpmatrixcan easily do), as this is just a MWE designed to illustrate my actual use case with minimal additional code. That is, as per my other question, I need#1to be parameter to\@MatrixWithParenand not simply a subscript added outside of the macro (i.e.,\@MatrixWithParenmust be the one that invokes the actual subscript and superscript).
Related Question:
General Question:
- How to parse optional parameters following a specfic
\end{environment}?
1. Optional parameters parsed by macro invoked by \collect@body.
\documentclass{article}
\usepackage{mathtools}
\usepackage{xparse}
\usepackage{xcolor}
\makeatletter
\NewDocumentCommand{\@MatrixWithParen}{m k_ k^}{%
\left(
\begin{matrix}%
#1% content
\end{matrix}
\right)
%% These seem to have no effect
\IfValueT{#2}{_{\textcolor{red}{#2}}}%
\IfValueT{#3}{^{\textcolor{blue}{#3}}}%
}%
\RenewDocumentEnvironment{bmatrix}{}{%
{\ifnum0=`}\fi\collect@body\@MatrixWithParen%
}{%
\ifnum0=`{\fi}%
}%
\makeatother
\begin{document}
\begin{align*}
A &= \begin{bmatrix} %% Both subscript and superscript
a_{11} & a_{12} \\
a_{21} & a_{22} \\
\end{bmatrix}_{2 \times 2}^{-1}
\\
B &= \begin{bmatrix} %% Only superscript
1 & -1 \\
-1 & 1 \\
\end{bmatrix}^{2}
\\
C &= \begin{bmatrix} %% Only subscript
a & b \\
b & d \\
\end{bmatrix}_{2}
\end{align*}
\end{document}
2: Attempt to use \AfterEndEnvironment:
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\usepackage{xcolor}
\usepackage{etoolbox}
\makeatletter
\newcommand*{\@MatrixContents}{}%
\newcommand*{\@PostBMatrix}{\@PostBMatrixAux}%
\NewDocumentCommand{\@PostBMatrixAux}{k_k^}{%
\@MatrixContents
\IfValueT{#1}{_{\textcolor{red}{#1}}}%
\IfValueT{#2}{^{\textcolor{blue}{#2}}}%
}
\NewDocumentCommand{\@MatrixWithParen}{m}{%
\gdef\@MatrixContents{%
\left(
\begin{matrix}
#1% content
\end{matrix}
\right)
}%
%\aftergroup{\@PostBMatrix}%
%\AtEndEnvironment{bmatrix}{\@PostBMatrix}% Not sure why this has slightly
\AfterEndEnvironment{bmatrix}{\@PostBMatrix}% different spacing than this.
}%
\RenewDocumentEnvironment{bmatrix}{}{%
{\ifnum0=`}\fi\collect@body\@MatrixWithParen%
}{%
\ifnum0=`{\fi}%
}%
\makeatother
\begin{document}
\[
A = \begin{bmatrix}
a_{11} & a_{12} \\
a_{21} & a_{22} \\
\end{bmatrix}_{2 \times 2}^{-1}
\]
\end{document}






xparseyou can use the argument specifiers in the end part of\NewDocumentEnvironment, but not define arguments for\end{<name>}; the arguments can only be given to\begin{<name>}– egreg Jul 14 '16 at 22:57\collect@bodydoes; it should be followed by a macro with a single parameter, which is passed the body of the environment. – egreg Jul 14 '16 at 23:04\collect@bodyand then continue on in case there were additional parameters at the end of the environment. But, guess it does not work that way. So, what is the best way to be able to parse the parameters following a specific environment? – Peter Grill Jul 14 '16 at 23:14\end{bmatrix}. Or place the arguments after\begin{bmatrix}. – egreg Jul 14 '16 at 23:28\begin{foo}only. Why not just use an optional argument to a custom environment? – Joseph Wright Jul 15 '16 at 05:48bmatrixis to put these after the\end{bmatrix}environment, not after\begin{bmatrix}. – Peter Grill Jul 15 '16 at 07:01