在 \left \right 组外应用 \middle

在 \left \right 组外应用 \middle

背景:

我正在使用的解决方案创建一个大的“这样”符号检查\currentgrouptype=16以便能够确定我们是否位于一个\left ... \right组的中间,在这种情况下我们使用\middle|,否则使用|

\newcommand*{\suchthat}{\;\ifnum\currentgrouptype=16 \middle\fi|\;}

就我而言\left\right对被打开关闭内容 ( #2) 使用\suchthat

\newcommand{\@Brac}[3]{% #1,#3 = left/right bracket type
        \mathopen{\left#1\vphantom{#2}\@BracKern\right.}% left bracket
        #2%  content
        \mathclose{\left.\@BracKern\vphantom{#2}\right#3}% right bracket
}
\newcommand{\bracr}[1]{\@Brac{(}{#1}{)}}%   round brackets
\newcommand{\bracc}[1]{\@Brac{\{}{#1}{\}}}% curly brackets

原因在于\@Brac宏可以跨越换行符起作用,如 MWE 中所示。

问题:

如何修改\suchthat宏以便能够在宏\middle中应用何时\@Brac

失败的解决方案:

  1. 我尝试设置\currentgrouptype=16但无法编译:

    您不能在数学模式下使用“\currentgrouptype”。

    无论如何,这可能不是一个好主意。

  2. 我尝试定义自己的\newtoggle并将其用作开关:

    \newcommand*{\suchthat}{\;%
      \ifnum\currentgrouptype=16\middle|\else%
         \iftoggle{WithinBracMacro}{\middle|}{|}% 
      \fi%
      \;}%
    

    但结果是

    错误:缺少插入}。

    \suchthatOld下面的和中定义了两个版本\suchthatNew,如果取消注释第一个参数中的行,就会发现问题\iftoggle{WithinBracMacro}{}{}

我非常喜欢切换方法。

参考:

目前结果:

只有“问题”行需要改变:

在此处输入图片描述

代码:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{amsmath}
\usepackage{showframe}

% https://tex.stackexchange.com/questions/54023/how-to-compute-exact-width-added-by-left-right
\makeatletter
\newcommand{\@BracKern}{\kern-\nulldelimiterspace}%
\newtoggle{WithinBracMacro}%
\togglefalse{WithinBracMacro}% initialize
\newcommand{\@Brac}[3]{% #1,#3 = left/right bracket type
        \mathopen{\left#1\vphantom{#2}\@BracKern\right.}% left bracket
        \toggletrue{WithinBracMacro}%
        #2%  content
        \togglefalse{WithinBracMacro}%
        \mathclose{\left.\@BracKern\vphantom{#2}\right#3}% right bracket
}
\newcommand{\bracr}[1]{\@Brac{(}{#1}{)}}%   round brackets
\newcommand{\bracc}[1]{\@Brac{\{}{#1}{\}}}% curly brackets

%% https://tex.stackexchange.com/questions/45713/creating-a-large-such-that-symbol
\newcommand*{\suchthatDelimin}{}%
\newcommand*{\suchthatNew}{%
    \;%
    \ifnum\currentgrouptype=16\relax% we are in a \left...\right
        \renewcommand{\suchthatDelimin}{\middle|}%
    \else%
        \iftoggle{WithinBracMacro}{% we are in a \@Brac macro
            \renewcommand\suchthatDelimin{|}%  This works fine!
            %     (change to some other char to see)
            %
            % If uncomment any of following: "Error: Missing } inserted."
            %\def\suchthatDelimin{\middle|}% 
            %\global\def\suchthatDelimin{\middle|}%
            %\renewcommand{\suchthatDelimin}{\middle|}%
        }{% can't use \middle
            \renewcommand{\suchthatDelimin}{|}%
        }% 
    \fi%
    \suchthatDelimin%
    \;%
}%

\newcommand*{\suchthatOld}{%
    \;%
    \ifnum\currentgrouptype=16\relax% we are in a \left...\right
        \middle|%
    \else%
        \iftoggle{WithinBracMacro}{% we are in a \@Brac macro
            |% This works (change to some other char to see)
            % If uncomment followin: "Error: Missing } inserted."
            %\middle|%
        }{% can't use \middle
            |%
        }% 
    \fi%
    \;%
}%
\makeatother


\begin{document}
\noindent
Comparrison of using \verb|\suchthat| in 
\verb|\left\{ ...\right\}| and \verb|\bracc{}|:
\begin{align*}
    \left\{x \suchthatOld x \le \frac{1}{2} \right\}\quad&
    \left\{x \suchthatNew x \le \frac{1}{2} \right\}\quad
\text{This is fine}\\
    \bracc{x \suchthatOld x \le \frac{1}{2} }\quad&
    \bracc{x \suchthatNew x \le \frac{1}{2} }\quad
\text{Problem on this line only}
\end{align*}
%
\noindent
Ensure that we can compile \verb|\suchthat| without 
\verb|\left\{ ...\right\}|.
This should not resize the brackets:
\begin{align*}
    \{x \suchthatOld x \le \frac{1}{2} \}\quad
    \{x \suchthatNew x \le \frac{1}{2} \}
\end{align*}
%
As we can see in the following, the \verb|\bracr| wraps around lines: 
$\bracr{x^{-1} + x^{-2} + x^{-3} +x^{-4} + x^{-5} + \cdots }$.
\end{document}

答案1

\left\middle实际上\right构建了两个数学列表(每个列表中都有)。没有对应的和,\currentgrouptype=16就不能有,所以当你执行稍后的时,是不允许的。所以我们必须记住内容并排版一个列表。\middle\left\right\left(\right.\middle\left.\middle|\right.

\documentclass{article}
\usepackage{amsmath}

\makeatletter
\def\@BracContents{} % default
\newcommand{\@BracKern}{\kern-\nulldelimiterspace}
\newcommand{\@Brac}[3]{% #1,#3 = left/right bracket type
  \begingroup\def\@BracContents{#2}
  \mathopen{\left#1\vphantom{#2}\@BracKern\right.}% left bracket
  #2%  content
  \mathclose{\left.\@BracKern\vphantom{#2}\right#3}% right bracket
  \endgroup
}
\newcommand{\suchthat}{\nonscript\;{ % open a group
  \let\suchthat\@empty % neutralize \suchthat inside \@Braccontents
  \left.\@BracKern % fake \left
  \vphantom{\@BracContents} % set size
  \middle| % bar
  \right.\@BracKern % fake \right
  }\nonscript\; % end group
}
\newcommand{\bracr}[1]{\@Brac{(}{#1}{)}}%   round brackets
\newcommand{\bracc}[1]{\@Brac{\{}{#1}{\}}}% curly brackets

\makeatother

\begin{document}
\begin{gather*}
\left\{x\;\middle|\;x=\frac{1}{2}\right\}\\
\bracc{x\suchthat x=\frac{1}{2}}
\end{gather*}
\end{document}

如果你打算\suchthat在正常\left\right上下文中使用,你可以这样做

\newcommand{\suchthat}{%
  \nonscript\;
  \ifnum\currentgrouptype=16
    \middle|
  \else
    \@suchthat
  \fi
  \nonscript\;}

\newcommand{\@suchthat}{%
  { % open a group
  \let\suchthat\@empty % neutralize \suchthat inside \@Braccontents
  \left.\@BracKern % fake \left
  \vphantom{\@BracContents} % set size
  \middle| % bar
  \right.\@BracKern % fake \right
  } % end group
}

相关内容