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@body
to invoke\@MatrixWithParen
which 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@body
in a macro and use\AfterEndEnvironment
to 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\aftergroup
and\AtEndEnvironment
also did not work:This non-solution has additional issues if there is more than one
bmatrix
environemnt, 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@body
so 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[]
(whichpmatrix
can 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#1
to be parameter to\@MatrixWithParen
and not simply a subscript added outside of the macro (i.e.,\@MatrixWithParen
must 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}
xparse
you 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>}
\collect@body
does; it should be followed by a macro with a single parameter, which is passed the body of the environment.\collect@body
and 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?\end{bmatrix}
. Or place the arguments after\begin{bmatrix}
.\begin{foo}
only. Why not just use an optional argument to a custom environment?