3

The command \DeclarePairedDelimiter (from the mathtools package) allows to use the delimiter size commands \big,\Big,\bigg,\Bigg, and allows to define custom paired delimiters. For example, the macro\DeclarePairedDelimiter{\Paren}{\lparen}{\rparen} (which uses the mathtools commands \lparen and \rparen) allows to write expressions like \Paren[\Bigg]{x}, whose output is the letter "x" enclosed by the biggest parentheses (not a very interesting example of "custom" paired delimiters, of course).

However, sometimes one might want to invoke the custom opening and closing delimiters with independent commands: for example, I prefer this whenever the content between the delimiters is too long, like

\customleftdelimiter A very long math expression \customrightdelimiter

instead of

\customdelimiter{A very long long math expression}

In the mathtools user manual (version 2022/06/29), p. 28, one reads:

Note 2: If you want to define your own manual scaler macros, it is important that you besides \foo also define \fool and \foor. When a scaler is specified, in say \abs[\big]{〈arg〉}, we actually use \bigl and \bigr.

The problem is that no instructions are given to do this. Perhaps a DeclareOpeningDelimiter command exists, but it is not described in the mathtools documentation.

Question

How to define the \fool and \foor commands, in the spirit of the mathtools package?

Note: This is a rephrasing of a previous question I asked, which I deleted because it was mixed with another issue (I will ask a separate question about that).

2 Answers2

3

Here's a version that respects the nesting levels.

\documentclass{article}
\usepackage{mathtools}

\ExplSyntaxOn

\NewDocumentCommand{\definegenericpaired}{mmm} {% #1 = name, #2 = left delimiter, #3 = right delimiter \chibchas_lr_new:nnn { #1 } { #2 } { #3 } }

\int_new:N \g__chibchas_lr_nestlevel_int

\cs_new_protected:Nn \chibchas_lr_new:nnn { \ExpandArgs{c}\NewDocumentCommand{#1l}{so} { % store the star or the optional argument \tl_gclear_new:c { g__chibchas_lr_\int_to_arabic:n { \g__chibchas_lr_nestlevel_int }tl } \IfBooleanTF{##1} { \tl_gset:cn { g__chibchas_lr\int_to_arabic:n { \g__chibchas_lr_nestlevel_int }tl } { \right } } { \IfNoValueF{##2} { \tl_gset:cn { g__chibchas_lr\int_to_arabic:n { \g__chibchas_lr_nestlevel_int }tl } { \use:c { \cs_to_str:N ##2 r } } } } % increase the nest level \int_gincr:N \g__chibchas_lr_nestlevel_int % deliver the left delimiter \IfBooleanTF{##1} { \left } { \IfNoValueF{##2} { \use:c { \cs_to_str:N ##2 l } } } #2 } \ExpandArgs{c}\NewDocumentCommand{#1r}{} { % decrease the nest level \int_gdecr:N \g__chibchas_lr_nestlevel_int % deliver the right delimiter \tl_use:c { g__chibchas_lr\int_to_arabic:n { \g__chibchas_lr_nestlevel_int }_tl } #3 } }

\ExplSyntaxOff

\definegenericpaired{foo}{(}{)} \definegenericpaired{baz}{[}{]}

\begin{document}

[ \fool* \frac{1}{2} + \bazl[\Big] x + \fool y \foor - z \bazr - 1 \foor ]

\end{document}

For each left delimiter, the requested size is saved in a global token list variable, so it can be used at the matching right delimiter. If you forget some, you're doomed…

enter image description here

egreg
  • 1,121,712
1

You can use \customldel and \customrdel to define left and right delimiters. The left delimiter can take a parameter like \big in order to scale the delimiter and whatever right delimiter it is paired with.

You need to match up left and right delimiters (ie. every custom left delimiter must be paired with a custom right delimiter), but you can use the predefined \lempty and \rempty custom delimiters for null delimiters (\lempty can also be used to set the scale of whatever right delimiter it is paired with).

\documentclass{article}

\def\noscale#1{\ifx.#1 \else#1\fi}

\makeatletter \def\mstrip{\expandafter@gobble\string} \let\customscale=\noscale \def\customldel#1#2{% \expandafter\def\csname \mstrip#1@help\endcsname[##1]{% \begingroup% \edef\customscale{\expandafter\noexpand\csname \mstrip##1r\endcsname}% \csname \mstrip##1l\endcsname{#2}% }% \def#1{@ifnextchar[ {\csname \mstrip#1@help\endcsname}% {\begingroup\let\customscale=\noscale#2}}% }

\def\customrdel#1#2{% \def#1{\customscale{#2}\endgroup}% } \makeatother

\begin{document}

\customldel{\lempty}. \customrdel{\rempty}. \customldel{\lcparen}( \customrdel{\rcparen})

[ \lempty[\bigg]\lcparen[\big] a\lcparen b\rempty c \rcparen\rcparen ] [ \bigl( a(b c \bigr) \biggr) ]

\end{document}

display custom delimiters

This works by storing the current amount of scale in a register \customscale, which is reverted after a custom right delimiter. \noscale is used in the case that there is no scaling, and it checks for the null delimiter (.) and prints if not.

Slurp
  • 876
  • You could of course use \newcommand with optional arguments instead of \def, but this was intended to be a plain TeX answer, I just didn't feel like defining @ifnextchar – Slurp Mar 25 '23 at 21:14