目的
我想要一个将表达式括在括号中的函数\left
,\right
其中括号的形状作为参数给出,例如
\brackets[(][]]{\frac{1}{2}} % should return \left(\frac{1}{2}\right]
我还希望该函数能够检测左括号的形状并提供匹配的右括号,除非另有说明。
背景
如果你想要了解详细信息,我实际上已经做了这样一个功能,它看起来像这样:
\usepackage{amsmath,xargs,xifthen}
\newcommandx{\brackets}[3][1=r, 2=default]{
\ifthenelse{\equal{#1}{r}}{ % r for round bracket
\ifthenelse{\equal{#2}{default}}{\left(#3\right)}{}
\ifthenelse{\equal{#2}{r}}{\left(#3\right)}{}
\ifthenelse{\equal{#2}{s}}{\left(#3\right]}{}
\ifthenelse{\equal{#2}{c}}{\left(#3\right\}}{}
\ifthenelse{\equal{#2}{v}}{\left(#3\right|}{}
\ifthenelse{\equal{#2}{}}{\left(#3\right.}{}
}{}
\ifthenelse{\equal{#1}{s}}{ % s for square bracket
\ifthenelse{\equal{#2}{default}}{\left[#3\right]}{}
\ifthenelse{\equal{#2}{r}}{\left[#3\right)}{}
\ifthenelse{\equal{#2}{s}}{\left[#3\right]}{}
\ifthenelse{\equal{#2}{c}}{\left[#3\right\}}{}
\ifthenelse{\equal{#2}{v}}{\left[#3\right|}{}
\ifthenelse{\equal{#2}{}}{\left[#3\right.}{}
}{}
\ifthenelse{\equal{#1}{c}}{ % c for curly brace
\ifthenelse{\equal{#2}{default}}{\left\{#3\right\}}{}
\ifthenelse{\equal{#2}{r}}{\left\{#3\right)}{}
\ifthenelse{\equal{#2}{s}}{\left\{#3\right]}{}
\ifthenelse{\equal{#2}{c}}{\left\{#3\right\}}{}
\ifthenelse{\equal{#2}{v}}{\left\{#3\right|}{}
\ifthenelse{\equal{#2}{}}{\left\{#3\right.}{}
}{}
\ifthenelse{\equal{#1}{v}}{ % v for vertical bar
\ifthenelse{\equal{#2}{default}}{\left|#3\right|}{}
\ifthenelse{\equal{#2}{r}}{\left|#3\right)}{}
\ifthenelse{\equal{#2}{s}}{\left|#3\right]}{}
\ifthenelse{\equal{#2}{c}}{\left|#3\right\}}{}
\ifthenelse{\equal{#2}{v}}{\left|#3\right|}{}
\ifthenelse{\equal{#2}{}}{\left|#3\right.}{}
}{}
\ifthenelse{\equal{#1}{}}{
\ifthenelse{\equal{#2}{default}}{#3}{}
\ifthenelse{\equal{#2}{r}}{\left.#3\right)}{}
\ifthenelse{\equal{#2}{s}}{\left.#3\right]}{}
\ifthenelse{\equal{#2}{c}}{\left.#3\right\}}{}
\ifthenelse{\equal{#2}{v}}{\left.#3\right|}{}
\ifthenelse{\equal{#2}{}}{\left.#3\right.}{}
}{}
}
我想这可以短得多。
问题
当我尝试编写一个辅助函数来检测左括号并提供匹配的右括号时,我似乎遇到了困难:
\newcommand{\partner}[1]{%
\ifthenelse{\equal{#1}{.}}{.}{}%
\ifthenelse{\equal{#1}{(}}{)}{}%
\ifthenelse{\equal{#1}{)}}{(}{}%
\ifthenelse{\equal{#1}{[}}{]}{}%
\ifthenelse{\equal{#1}{]}}{[}{}%
\ifthenelse{\equal{#1}{\{}}{\}}{}%
\ifthenelse{\equal{#1}{\}}}{\{}{}%
}
\left
/\right
和之间的互动似乎有些尴尬ifthenelse
。
问题的最小示例
\documentclass{article}
\usepackage{amsmath,xifthen}
\newcommand{\funcA}{
)
}
\newcommand{\funcB}{
\ifthenelse{1=1}{)}{}
}
\begin{document}
\begin{align*}
\csname left\endcsname(\frac{1}{2}\csname right\endcsname\funcA \\ % works
\csname left\endcsname(\frac{1}{2}\csname right\endcsname\funcB % doesn't work
\end{align*}
\end{document}
答案1
只是为了学术兴趣,因为
- 您不应滥用
\left
,\right
原因如下; - 打字
(a+b)
比 容易得多\brackets{a+b}
。
我使用了 所使用的分隔符的标准缩写amsmath
。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\brackets}{O{p}O{#1}m}
{
\left
\str_case:nnF { #1 } { {p}{(} {b}{[} {B}{\{} {v}{|} {V}{\|} {.}{.} } {.}
#3
\right
\str_case:nnF { #2 } { {p}{)} {b}{]} {B}{\}} {v}{|} {V}{\|} {.}{.} } {.}
}
\ExplSyntaxOff
\begin{document}
$\brackets{a+b}$
$\brackets[b]{a+b}$
$\brackets[b][p]{a+b}$
$\brackets[B]{a+b}$
$\brackets[v]{a+b}$
$\brackets[V]{a+b}$
$\brackets[?]{a+b}$
\end{document}
该命令有两个可选参数:第一个参数默认为p
(括号,圆括号);第二个参数默认为“与第一个可选参数相同”。
如果其中一个或两个都不属于定义的缩写,则返回空分隔符(\brackets[.]{a+b}
顺便说一下,您也可以使用)。
如果不匹配,还可能会添加警告/错误消息。
有什么问题\ifthenelse
?\left
和\right
进行宏扩展以找到合适的分隔符(非负字符\delcode
或原始的\delimiter
),但\ifthenelse
并不简单地返回真或假分支,因为它不能通过纯扩展和赋值来工作。
相反,\str_case:nnF
通过纯粹的扩展来工作。
答案2
这可能不是您所要求的,但在这里,\brackets
要么不带参数,给出默认()
括号,要么在后面提供两个标记\brackets
。此外,在两个括号标记之前和之后允许有可选空格。
正如 Don 在评论中指出的那样,可选参数的问题在于可选参数内的括号很棘手。
\documentclass{article}
\def\brackets{\futurelet\z\brakA}
\def\brakA{\ifx\bgroup\z\expandafter\brakC
\else\expandafter\brakB\fi}
\def\brakB#1#2{\brakD{#1}{#2}}
\def\brakC{\brakD{(}{)}}
\newcommand\brakD[3]{\left#1#3\right#2}
\begin{document}\noindent
$\brackets {\frac{x}{2}}$\\
$\brackets [) {\frac{x}{2}}$\\
$\brackets \{\} {\frac{x}{2}}$\\
$\brackets (\} {\frac{x}{2}}$\\
$\brackets (. {\frac{x}{2}}$\\
\end{document}
补充
这是一个更复杂的版本,它还允许提供单个分隔符,其中隐含了第二个(缺失的)分隔符。与以前一样,两个括号标记之前和之后允许有可选空格,但在本例中,它们之间不允许有空格。
\documentclass{article}
\usepackage{etoolbox}
\csdef{brak[}{]}
\csdef{brak(}{)}
\csdef{brak\string\{}{\}}
\csdef{brak.}{.}
\def\brackets{\futurelet\z\brakA}
\def\brakA{\ifx\bgroup\z\expandafter\brakC
\else\expandafter\brakB\fi}
\def\brakB#1{\def\zz{#1}\futurelet\zzz\brakD}
\def\brakC{\brakF()}
\makeatletter
\def\brakD{%
\edef\zzzz{\csname brak\expandafter\string\zz\endcsname}%
\ifx\bgroup\zzz\def\next{\zzzz}\else
\ifx\@sptoken\zzz\def\next{\zzzz}\else
\def\next{}\fi\fi\expandafter\brakE\next}
\makeatother
\def\brakE#1{\brakF\zz#1}
\newcommand\brakF[3]{\left#1#3\right#2}
\begin{document}\noindent
No Delimiter\\
$\brackets {\frac{x}{2}}$\\
One Delimiter:\\
$\brackets ( {\frac{x}{2}}$\\
$\brackets [ {\frac{x}{2}}$\\
$\brackets \{ {\frac{x}{2}}$\\
$\brackets . {\frac{x}{2}}$\\
Two Delimiters:\\
$\brackets [) {\frac{x}{2}}$\\
$\brackets \{) {\frac{x}{2}}$\\
$\brackets (\} {\frac{x}{2}}$\\
$\brackets (. {\frac{x}{2}}$\\
\end{document}