function with optional arguments

A key-value approach with keys n, m, d, s. If one of them is set, then the subscript appears. Then, default values are used for n (1), m (p) and s (W) if the key is not given.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{amsmath}

\usepackage{kvoptions}
\SetupKeyvalOptions{family=norm, prefix=norm@}
\DeclareStringOption{n}
\DeclareStringOption{m}
\DeclareStringOption{d}
\DeclareStringOption{s}

\makeatletter
\newcommand*{\norm}[2][]{%
  \begingroup
    \kvsetkeys{norm}{#1}%
    \left\lVert#2\right\rVert
    \ifnum0\ifx\norm@m\@empty\else1\fi
           \ifx\norm@n\@empty\else1\fi
           \ifx\norm@d\@empty\else1\fi
           \ifx\norm@s\@empty\else1\fi
           >0 %
      _{%
        \ifx\norm@s\@empty W\else\norm@s\fi
        ^{%
          \ifx\norm@n\@empty 1\else\norm@n\fi,%
          \ifx\norm@m\@empty p\else\norm@m\fi
        }%
        \ifx\norm@d\@empty
        \else
          (\norm@d)%
        \fi
      }%
    \fi
  \endgroup
}
\makeatother

\begin{document}
\def\test#1\\{%
  \texttt{\detokenize{#1}} & $#1$ \\%
}
\begin{tabular}{ll}
  \test\norm{u}\\
  \test\norm[n=1]{u}\\
  \test\norm[n=n]{u}\\
  \test\norm[m=p]{u}\\
  \test\norm[m=m]{u}\\
  \test\norm[n=n, m=m]{u}\\
  \test\norm[d=\Omega]{u}\\
  \test\norm[n=1, m=p, d=\Omega, s=W]{u}\\
  \test\norm[n=n, m=m, d=d, s=s]{u}\\
\end{tabular}
\end{document}

Result

  • The \DeclareStringOption{foo} defines macro \norm@foo. It is \@empty, if the key is not used in the optional argument.

  • \kvsetkeys{norm}{#1} (also \setkeys can be used) is called inside a group to preserve the initial settings of the parameter macros \norm@....

  • I tried to get a useful algorithm and the default values from the definitions of the commands \norms and friends.


A listofitems approach to obtain the key values. Thanks to Heiko for the test tabular.

\documentclass{article}
\usepackage{listofitems,amsmath}
\newcommand{\normplain}[1]{\left\lVert #1 \right\rVert}
\newcommand\norm[2][\relax]{\normplain{#2}\ifx\relax#1\relax\else\normaux{#1}\fi}
\newcommand\normaux[1]{%
  \def\nnormdata{1}% DEFAULT
  \def\mnormdata{p}% DEFAULT
  \def\dnormdata{\relax}% DEFAULT
  \def\snormdata{W}% DEFAULT
  \setsepchar{,/=}%
  \readlist*\normdata{#1}%
  \foreachitem\x\in\normdata[]{%
    \expandafter\edef\csname\normdata[\xcnt,1]normdata\endcsname{\normdata[\xcnt,2]}%
  }%
  _{\snormdata^{\nnormdata,\mnormdata}\expandafter\ifx\dnormdata\relax\else(\dnormdata)\fi}
}
\begin{document}
\def\test#1\\{%
  \texttt{\detokenize{#1}} & $#1$ \\%
}
\begin{tabular}{ll}
  \test\norm{u}\\
  \test\norm[n=1]{u}\\
  \test\norm[n=n]{u}\\
  \test\norm[m=p]{u}\\
  \test\norm[m=m]{u}\\
  \test\norm[n=n, m=m]{u}\\
  \test\norm[d=\Omega]{u}\\
  \test\norm[n=1, m=p, d=\Omega, s=W]{u}\\
  \test\norm[n=n, m=m, d=d, s=s]{u}\\
\end{tabular}
\end{document}

enter image description here


A flexible key-value interface, also with choice of size (avoid automatic \left and right):

\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\norm}{O{}m}
 {
  \group_begin:
  \keys_set:nn { cesareborgia/norm } { #1 }
  \cesareborgia_norm:n { #2 }
  \group_end:
 }

\keys_define:nn { cesareborgia/norm }
 {
  s .tl_set:N = \l_cesareborgia_norm_spc_tl,
  n .tl_set:N = \l_cesareborgia_norm_exp_tl,
  d .tl_set:N = \l_cesareborgia_norm_dom_tl,
  m .tl_set:N = \l_cesareborgia_norm_mlt_tl,
  size .tl_set:N = \l_cesareborgia_norm_size_tl,
 }

\cs_new_protected:Nn \cesareborgia_norm:n
 {
  \__cesareborgia_norm_lsize:V \l_cesareborgia_norm_size_tl
  #1
  \__cesareborgia_norm_rsize:V \l_cesareborgia_norm_size_tl
  \tl_if_empty:NF \l_cesareborgia_norm_spc_tl
   {
    \sb
     {
      \l_cesareborgia_norm_spc_tl
      \tl_if_empty:NF \l_cesareborgia_norm_exp_tl
       {
        \sp
         {
          \l_cesareborgia_norm_exp_tl
          \tl_if_empty:NF \l_cesareborgia_norm_mlt_tl
           {
            ,\l_cesareborgia_norm_mlt_tl
           }
         }
        \tl_if_empty:NF \l_cesareborgia_norm_dom_tl
         {
          (\l_cesareborgia_norm_dom_tl)
         }
       }
     }
   }
 }
\cs_new_protected:Nn \__cesareborgia_norm_lsize:n
 {
  \str_case:nnF { #1 }
   {
    {*}{\left}
    {}{}
   }
   { \use:c { #1l } }
  \|
 }
\cs_generate_variant:Nn \__cesareborgia_norm_lsize:n { V }
\cs_new_protected:Nn \__cesareborgia_norm_rsize:n
 {
  \str_case:nnF { #1 }
   {
    {*}{\right}
    {}{}
   }
   { \use:c { #1r } }
  \|
 }
\cs_generate_variant:Nn \__cesareborgia_norm_rsize:n { V }
\ExplSyntaxOff

\begin{document}

\begin{gather}
 \norm[n=1,m=p,d=\Omega,s=W]{u}+
 \norm[n=1,m=p,d=\Omega,s=W,size=Big]{u}+
 \norm[n=1,m=p,d=\Omega,s=W,size=*]{\dfrac{u}{2}}
\\
 \norm[n=1,m=p,s=W]{u}+
 \norm[size=big,n=1,m=p,s=W]{u}+
 \norm[size=*,n=1,m=p,s=W]{\dfrac{u}{2}}
\\
 \norm[n=1,s=W]{u}+
 \norm[n=1,s=W,size=bigg]{u}+
 \norm[n=1,s=W,size=*]{\dfrac{u}{2}}
\\
 \norm[n=1,s=W,d=\Omega]{u}+
 \norm[n=1,s=W,d=\Omega,size=Bigg]{u}+
 \norm[n=1,s=W,d=\Omega,size=*]{\dfrac{u}{2}}
\\
 \norm[s=W]{u}+
 \norm[s=W,size=big]{u}+
 \norm[s=W,size=*]{\dfrac{u}{2}}
\\
 \norm{u}+
 \norm[size=Bigg]{u}+
 \norm[size=*]{\dfrac{u}{2}}
\end{gather}

\end{document}

enter image description here

Tags:

Macros