7

I've made lots of use of the answer here, which shows how to switch the starred and nonstarred versions of a paired delimiter command (causing the regular version to automatically size the delimiters).

\DeclarePairedDelimiter\abs{\lvert}{\rvert}

\makeatletter
\let\oldabs\abs
\def\abs{\@ifstar{\oldabs}{\oldabs*}}
\makeatother

But now in the pre header that I include in nearly every document, I've got several of these commands stacked up, and for each of them I've got another two lines switching the versions.

Is there good/nice way to alter \DeclarePairedDelimiter itself, so that it switches the two to begin with? (Which also means, would this break any dependencies?)

  • Why would you want it? – egreg Nov 15 '15 at 19:12
  • Would this redefinition not causing troubles with the optional argument of the non-starred variant? – user31729 Nov 15 '15 at 19:18
  • @egreg: I've been looking for something like this too. I usually define several delimiters such as \paren, and I tend to use ( and ) for parentheses that shouldn't be resized, \paren for those that should, and (for example) \paren*[\bigg] for when they need to be manually resized. Given that I sometimes use up to seven delimiters, a shortcut would be nice. – Arun Debray Nov 15 '15 at 19:19
  • @ChristianHupfer I'm thinking the starred version would then accept the optional argument as Arun says. I edited the question to clarify that it wouldn't be 'good' if this breaks some dependency in some popular package. – Travis Bemrose Nov 15 '15 at 19:40
5

It's easy: just abstract the redefinition.

\makeatletter
\newcommand{\WronglyDeclarePairedDelimiter}[3]{%
  \expandafter\DeclarePairedDelimiter\csname RIGHT\string#1\endcsname{#2}{#3}%
  \newcommand#1{%
    \@ifstar{\csname RIGHT\string#1\endcsname}
            {\csname RIGHT\string#1\endcsname*}%
  }%
}
\makeatother

After this, the declaration

\WronglyDeclarePairedDelimiter\abs{\lvert}{\rvert}

will define the command \abs to do the wrong thing you want.

When you'll realize why this is wrong, you'll just remove Wrongly and you'll be on the right way again. ;-)

A “better” procedure, that uses the same syntax as the original command (but \abs by itself will either use the automatic or the optional argument version), so you don't need the absurd \abs*[\big]{a}.

\documentclass{article}
\usepackage{mathtools}

\makeatletter
\newcommand{\WronglyDeclarePairedDelimiter}[3]{%
  \expandafter\DeclarePairedDelimiter\csname RIGHT\string#1\endcsname{#2}{#3}%
  \newcommand#1{%
    \@ifstar{\csname RIGHT\string#1\endcsname}
            {\@ifnextchar[{\csname RIGHT\string#1\endcsname}
                          {\csname RIGHT\string#1\endcsname*}%
            }%
  }%
}
\makeatother

\WronglyDeclarePairedDelimiter\abs{|}{|}

\begin{document}

$\abs{\dfrac{1}{2}}$

$\abs[\Big]{\dfrac{1}{2}}$

$\abs*{\dfrac{1}{2}}$

\end{document}
  • I appreciate your enthusiasm ("easy") :-) but it's not the 70s anymore and I find it horrific that I have to waste so much time learning (and using) a whole new programming language just because it's the traditional way to produce documents in my field, when software could easily take care of the details these days, and let me focus on the content. – Travis Bemrose Nov 16 '15 at 0:12
  • I'm trying to guess why it's wrong and if the "better" way handling the optional parameter fixes the wrongness (but my brain doesn't want any more TEX today). I tested it and both versions will accept the option now, though I can't see why. Is there a reason you switched to {|}? I thought the \lvert \rvert were supposed to handle some kind of spacing. – Travis Bemrose Nov 16 '15 at 0:12
  • 1
    @TravisBemrose There's no need to use \lvert and \rvert, because the \abs macro takes care of the spacing automatically. The main fact is that automatic resizing works only in fewer cases than you may expect, because it usually produces too large fences. Or not what you may want: for instance \left|\left|a\right|-\left|b\right|\right| will produce equal sized fences for the inner and the outer parts. Whereas \abs[\big]{\abs{a}-\abs{b}} will do the right thing (I mean, the correct \abs). – egreg Nov 16 '15 at 0:14
  • lol. Sometimes I'm not satisfied with the automatic sizing, but it's because it's too small and I override it with larger sizes. I'm guessing RIGHT gets interpreted as \right, but why is it followed with the new command's name #1, and why is there no LEFT? – Travis Bemrose Nov 16 '15 at 0:21
  • 1
    @TravisBemrose RIGHT is just a string for making sure we don't clobber any existing command. It could be FOO or whatever. It's just like using \oldabs, but safer. – egreg Nov 16 '15 at 0:24
3

A trial version, without warranties, by switching the two variants internally. (The code is 'stolen' from mathtools.sty ;-))

\documentclass{article}

\usepackage{xparse}
\usepackage{mathtools}


\makeatother
\ExplSyntaxOn
\renewcommand*\DeclarePairedDelimiter[3]{%
  \@ifdefinable{#1}{
    \MT_delim_default_inner_wrappers:n{#1}
    \@namedef{MT_delim_\MH_cs_to_str:N #1 _star:}##1
      %{\mathopen{}\mathclose\bgroup\left#2 ##1 \aftergroup\egroup\right #3}%
      { \@nameuse{MT_delim_\MH_cs_to_str:N #1 _star_wrapper:nnn}%
           {\left#2}{##1}{\right#3} }%
    \@xp\@xp\@xp
      \newcommand
        \@xp\csname MT_delim_\MH_cs_to_str:N #1 _nostar:\endcsname
        [2][\\@gobble]
        {
          %\mathopen{\@nameuse {\MH_cs_to_str:N ##1 l} #2} ##2
          %\mathclose{\@nameuse {\MH_cs_to_str:N ##1 r} #3}}
          \@nameuse{MT_delim_\MH_cs_to_str:N #1 _nostar_wrapper:nnn}%
             {\@nameuse {\MH_cs_to_str:N ##1 l} #2}
             {##2}
             {\@nameuse {\MH_cs_to_str:N ##1 r} #3}
        }
    \DeclareRobustCommand{#1}{
      \@ifstar
        {\@nameuse{MT_delim_\MH_cs_to_str:N #1 _nostar:}}
        {\@nameuse{MT_delim_\MH_cs_to_str:N #1 _star:}}
    }
  }
}
\ExplSyntaxOff
\makeatother

\DeclarePairedDelimiter\abs{\lvert}{\rvert}



\begin{document}
$\abs{-5}$

$\abs*[\Bigg]{-5}$
\end{document}
  • I guess, a pure expl3 answer would be nicer. This would look more coherent and save you all the \@xp stuff. – Henri Menke Nov 15 '15 at 19:22
  • @HenriMenke: Tell the designer of mathtools -- I 'stole' the code ;-) – user31729 Nov 15 '15 at 19:23
  • I suspected something like this (renewing the command and rewriting everything in an opposite manner) would work, but I'll leave the question open for a while since I'm hoping someone knows a more robust way to do it. (I.e. less likely to need a warranty, and less fragile - a stray key press while I have my pre header open won't make a change that's impossible for me to track down later when it breaks). :) – Travis Bemrose Nov 15 '15 at 19:47
  • @TravisBemrose: Patching is another possibility, but my solution was in a bit of a hurry ;-) – user31729 Nov 15 '15 at 21:50
0

To have this info in the same place and save others effort, following egreg's answer above, I got this working for the X version of \NewPairedDelimiterX. I kept his example below to make it easier to look back and forth between the two.

Declaration:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Tells DeclarePairedDelimiter to create functions that are automatically sized.
% Starred version is not automatically sized. Both version allow an overriding input.
% Auto sizing:  \abs{x}
% Override:     \abs[\big]{x}
% Not sized:    \abs*{x}
% Override:     \abs*[\big]{x}
%
% Defines two commands, for example: PAIREDabs, abs
% abs checks for a star or options and then calles the right version of PAIREDabs
\makeatletter
\newcommand{\NewPairedDelimiter}[3]{%
  \expandafter\DeclarePairedDelimiter\csname PAIRED\string#1\endcsname{#2}{#3}%
  \newcommand#1{%
    \@ifstar{\csname PAIRED\string#1\endcsname}
            {\@ifnextchar[{\csname PAIRED\string#1\endcsname}
                          {\csname PAIRED\string#1\endcsname*}%
            }%
  }%
}
\newcommand{\NewPairedDelimiterX}[4]{%
  \expandafter\DeclarePairedDelimiterX\csname PAIREDX\string#1\endcsname[2]{#2}{#3}{#4}%
  \newcommand#1{%
    \@ifstar{\csname PAIREDX\string#1\endcsname}
            {\@ifnextchar[{\csname PAIREDX\string#1\endcsname}
                          {\csname PAIREDX\string#1\endcsname*}%
            }%
  }%
}
\makeatother
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


Definition:

\NewPairedDelimiterX{\innerp}{\langle}{\rangle}{#1,#2}


Use:

$\innerp{ax}{y}$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.