我想创建一个不使用 xparse 包的智能括号命令。
\p(1) prints (1)
\p[1] [1]
\p{1} {1}
\p(1|2) (1|2)
我试过这个代码,但它不适用于括号。
另外,我不知道该怎么做(1|2)
。
\documentclass{article}
\makeatletter
\def\p
{
\@ifnextchar(
{\@parenthesis}
{
\ifx\@let@token[
\expandafter\@bracket
\else
\expandafter\@brace
\fi
}
}
\def\@parenthesis(#1){\left( #1 \right)}
\def\@bracket[#1]{\left[ #1 \right]}
\def\@brace#1{\left{ #1 \right}}
\makeatother
\begin{document}
$\p(1)$
$\p[1]$
$\p{1}$
$\p(1|2)$
\end{document}
我这样做的动机是为了获得更具表现力的语法。
答案1
这似乎有效:
更新:请参见下面的不同实现,它执行
\left
和操作并且与 中间\right
兼容。\middle
第二次更新:
mathcodes
没有 catcodes 的所有限制。基于此,mathcodes
我提出了一种比前一种方法更强大的方法:它允许(看似)非常复杂的嵌套。我梦想有textcodes
……重点是mathcodes
不要冻结。这非常有用。
编辑:经过一些额外的工作后,正确恢复了mathcodes
。我保证不会再编辑……
\documentclass{article}
\makeatletter
\def\p{\afterassignment\p@aux\let\next=}
\def\p@aux{\ifx\next\bgroup\lbrace\bgroup\aftergroup\rbrace\else
\expandafter\next\fi}
\makeatother
\begin{document}
$\p(1)$
$\p[1]$
$\p{1}$
$\p(1|2)$
\end{document}
使用自动\left
和\right
。我还应该做中间的事情吗?
更新:在结束行添加了缺失的 ̀%
并思考了\middle
导致我出现一些问题的 e-TeX 问题......
(请参阅下文了解最后的方法:
\middle
这是一个相当大的挑战)
\documentclass{article}
\usepackage{amsmath}
\makeatletter
\def\p{\afterassignment\p@aux\let\next=}
\def\p@aux{\ifx\next\bgroup
\left\lbrace\bgroup\aftergroup\right\aftergroup\rbrace
\else
\ifx\next(%
\left(\bgroup\catcode`\)=\tw@
\aftergroup\right\aftergroup)%
\else
\ifx\next[%
\left[\bgroup\catcode`\]=\tw@
\aftergroup\right\aftergroup]%
\else\next
\fi\fi
\fi}
\makeatother
\begin{document}\thispagestyle{empty}
$\p(1) \p(\dfrac{1}{2})$
$\p[1] \p[\dfrac{1}{2}]$
$\p{1} \p{\dfrac{1}{2}}$
$\p(1|2) \p(\dfrac{1}{2}|3)$
\end{document}
eTeX
\middle
完全改变方法 以满足要求。请注意,以下内容适用于后面的任意分隔符\middle
\documentclass{article}
\usepackage{amsmath} % for \dfrac
\makeatletter
\def\p{\afterassignment\p@aux\let\next=}
\newtoks\p@toks
\def\@ybrace{\expandafter\left\expandafter\lbrace\the\p@toks\right\rbrace}
%% \def\@yparen{\expandafter\left\expandafter(\the\p@toks\right)\endgroup}
\def\@yparen{\expandafter\endgroup\expandafter\left\expandafter(\the\p@toks\right)}
%% \def\@ybrack{\expandafter\left\expandafter[\the\p@toks\right]\endgroup}
\def\@ybrack{\expandafter\endgroup\expandafter\left\expandafter[\the\p@toks\right]}
\def\p@aux{\ifx\next\bgroup
\def\p@tmp{\p@toks=\bgroup}%
\afterassignment\@ybrace
\else
\ifx\next(%
\begingroup\catcode`\)=\tw@
\def\p@tmp{\p@toks=\bgroup}%
\afterassignment\@yparen
\else
\ifx\next[%
\begingroup\catcode`\]=\tw@
\def\p@tmp{\p@toks=\bgroup}%
\afterassignment\@ybrack
\else
\let\p@tmp\next
\fi\fi\fi
\p@tmp}
\makeatother
\begin{document}\thispagestyle{empty}
$\p(1) \p(\dfrac{1}{2}) \p(\dfrac{1}{2}\middle|3)$
$\p[1] \p[\dfrac{1}{2}] \p[\dfrac{1}{2}\middle|3]$
$\p{1} \p{1\middle|2} \p{\dfrac{1}{2}\middle|3}$
\end{document}
$\p{1} \p{1\middle>2} \p{\dfrac{1}{2}\middle<3}$
现在是基于 的方法mathcodes
。也许我必须重新考虑括号的情况,这里的括号处理方式与之前的方法相同。我只对它们使用标记列表。标记列表是 ,因此\middle
尝试某种技术时会遇到困难\aftergroup
。
也正因为\middle
如此,我必须明确恢复mathcodes
和)
,而]
不是将其信任给源于使用\left
和 的组\right
。问题是\middle
关闭此组,然后打开第二个组。
编辑: 和 有问题$ \p( ( A ) )$
,我已编辑宏,以便mathcodes
正确重置。我无法使用\left
和创建的组,\right
因为\middle
。
\documentclass{article}
\makeatletter
\def\p{\afterassignment\p@aux\let\next=}
\newtoks\p@toks
\def\@ybrace{\expandafter\left\expandafter\lbrace\the\p@toks\right\rbrace}
% To get correct nesting I added the \restore@paren and \restore@brack macros
\def\p@aux{\ifx\next\bgroup
\def\p@tmp{\p@toks=\bgroup}%
\afterassignment\@ybrace
\else
\ifx\next(%
\ifnum\mathcode`)="8000
\let\restore@paren\relax
\def\p@tmp{\left(}%
\else
\edef\restore@paren{\mathcode`)=\the\mathcode`)\relax}%
\begingroup
\lccode`\~=`)
\lowercase{%
\endgroup
\def~{\right)\restore@paren}}%
\def\p@tmp{\mathcode`)="8000 \left(}%
\fi
\else
\ifx\next[%
\ifnum\mathcode`]="8000
\let\restore@brack\relax
\def\p@tmp{\left[}%
\else
\edef\restore@brack{\mathcode`]=\the\mathcode`]\relax}%
\begingroup
\lccode`\~=`]
\lowercase{%
\endgroup
\def~{\right]\restore@brack}}%
\def\p@tmp{\mathcode`]="8000 \left[}%
\fi
\else
\let\p@tmp\next
\fi\fi\fi
\p@tmp}
\makeatother
\begin{document}\thispagestyle{empty}
\delimitershortfall=-1pt
\[\p(\frac{1}{2}\p{\p{3^T:4}}\p[\p(A_B^C)]\p(\big]\middle>\big[)\middle\Vert\p[\frac{1}{2}])\]
\[\p{\p(\p[A_B^C\middle< \p{X^Y}])\middle\vert\p[\p(A_B^C\middle> \p(X^Y))]} \]
\end{document}
\[\the\mathcode`) \ \the\mathcode`] \p( \p{ \p[ \p( \p{ \p[ A ]})]})
\the\mathcode`)\ \the\mathcode`] \]
答案2
这将实现你想要的效果:
\documentclass{article}
\usepackage{amsmath} % just for \dfrac in the example
\makeatletter
\def\p{\@ifnextchar(\neb@p@parens{\@ifnextchar[\neb@p@bracket\neb@p@brace}}
\def\neb@p@brace#1{\left\{#1\right\}}
\def\neb@p@bracket[#1]{\left[#1\right]}
\def\neb@p@parens(#1){\neb@p@checkbar#1||\@nil}
\def\neb@p@checkbar#1|#2|#3\@nil{%
\if\relax\detokenize{#2}\relax
\left(#1\right)
\else
\left(#1\;\middle|\;#2\right)
\fi}
\makeatother
\begin{document}
$\p(1) \p(\dfrac{1}{2})$
$\p[1] \p[\dfrac{1}{2}]$
$\p{1} \p{\dfrac{1}{2}}$
$\p(1|2) \p(\dfrac{1}{2}|3)$
\end{document}
话虽如此,我不建议使用这些容易出错的“灵活”命令:不同的构造应该用不同的命令来实现。