4

I was looking for a way of grabbing sub and superscripts as optional arguments to a command in xparse. That is, \foo_{a}^{b} would receive a as an optional argument and b as another optional argument. The nice thing of this is that we could have control over one of the primitive things of TeX that we have zero control right now.

6

Well, I asked on the LaTeX-L list, but then decided to give it a try, copying here and there from the package, I ended with this (if this has no errors, I will send a message to the list, but here at least I can edit and correct typos).

This code adds a new type of argument k and K (Why k? I don't really know, if you have a better suggestion you can tell me. For now grab, remove, token, etc. are taken, so I decided token —I didn't want to use the famous extra x from every xpackage—). First one must be followed by the token to check (exactly like t arguments) and K must be followed by the token and the default argument, e.g., K*{<default>}. I tried to follow what I saw as standards in xparse (except the “don't gobble spaces looking for a trailing optional argument”). Ah, and there's no expandable one, because I didn't need it right now, so I just skipped that.

This argument type checks if a token exists, and, if it's there, removes it and takes the next argument (single token, or braced argument). For instance

  • \NewDocumentCommand\foo{mk*} would grab \foo{a} (#1 = a, #2 = -NoValue-), and
  • \foo{a}*{b} (#1 = a, #2 = b)

In particular, I wanted this for sub and superscripts, so I created two “shorthands” a = k_ and b = k^ (and the similar A and B).

Here's the code with a few examples.

\documentclass{scrartcl}
\usepackage{mathtools,amssymb,xparse}

\ExplSyntaxOn
\cs_new_protected:Npn \__xparse_count_type_k:w #1
 {
  \__xparse_single_token_check:n { #1 }
  \quark_if_recursion_tail_stop_do:Nn #1 { \__xparse_bad_arg_spec:wn }
  \__xparse_count_mandatory:N
 }
\cs_new_protected:Npn \__xparse_count_type_K:w #1 #2
 {
  \__xparse_single_token_check:n { #1 }
  \quark_if_recursion_tail_stop_do:nn { #2 } { \__xparse_bad_arg_spec:wn }
  \__xparse_count_mandatory:N
 }
\cs_new_protected:Npn \__xparse_add_type_k:w #1
 { \exp_args:NNo \__xparse_add_type_K:w #1 { \c__xparse_no_value_tl } }
\cs_new_protected:Npn \__xparse_add_type_K:w #1 #2
 {
  \__xparse_flush_m_args:
  \__xparse_add_grabber_optional:N K
  \tl_put_right:Nn \l__xparse_signature_tl { #1 { #2 } }
  \__xparse_prepare_signature:N
 }
\cs_new_protected:Npn \__xparse_add_expandable_type_k:w #1
 {
  \exp_args:NNo \__xparse_add_expandable_type_K:w #1 { \c__xparse_no_value_tl }
 }
\cs_new_protected_nopar:Npn \__xparse_add_expandable_type_K:w #1 #2
 {
  \__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type } { K }
  \__xparse_add_expandable_type_m:w % May be create this?
 }
\cs_new_protected:Npn \__xparse_grab_K:w #1 #2 #3 \l__xparse_args_tl
 {
  \__xparse_grab_K_aux:NnnNn #1 { #2 } { #3 } \cs_set_protected_nopar:Npn
   { _ignore_spaces }
 }
\cs_new_protected:Npn \__xparse_grab_K_long:w #1 #2 #3 \l__xparse_args_tl
 {
  \__xparse_grab_K_aux:NnnNn #1 { #2 } { #3 } \cs_set_protected:Npn
   { _ignore_spaces }
 }
\cs_new_protected:Npn \__xparse_grab_K_trailing:w #1 #2 #3 \l__xparse_args_tl
 {
  \__xparse_grab_K_aux:NnnNn #1 { #2 } { #3 } \cs_set_protected_nopar:Npn
   { _ignore_spaces }
 }
\cs_new_protected:Npn \__xparse_grab_K_long_trailing:w #1 #2 #3 \l__xparse_args_tl
 {
  \__xparse_grab_K_aux:NnnNn #1 { #2 } { #3 } \cs_set_protected:Npn
   { _ignore_spaces }
 }
\cs_new_protected:Npn \__xparse_grab_K_aux:NnnNn #1 #2 #3 #4 #5
 {
  \exp_after:wN #4 \l__xparse_fn_tl ##1
   {
    \__xparse_add_arg:n { ##1 }
    #3 \l__xparse_args_tl
   }    
  \use:c { peek_meaning_remove #5 :NTF } #1
   { \l__xparse_fn_tl }
   {
    \__xparse_add_arg:n { #2 }
    #3 \l__xparse_args_tl
   }
 }

\prop_put:Nnn \c__xparse_shorthands_prop { a } { k \sb }
\prop_put:Nnn \c__xparse_shorthands_prop { b } { k \sp }
\prop_put:Nnn \c__xparse_shorthands_prop { A } { K \sb }
\prop_put:Nnn \c__xparse_shorthands_prop { B } { K \sp }

\prop_put:Nnn \c__xparse_shorthands_prop { 1 } { m                 }
\prop_put:Nnn \c__xparse_shorthands_prop { 2 } { m m               }
\prop_put:Nnn \c__xparse_shorthands_prop { 3 } { m m m             }
\prop_put:Nnn \c__xparse_shorthands_prop { 4 } { m m m m           }
\prop_put:Nnn \c__xparse_shorthands_prop { 5 } { m m m m m         }
\prop_put:Nnn \c__xparse_shorthands_prop { 6 } { m m m m m m       }
\prop_put:Nnn \c__xparse_shorthands_prop { 7 } { m m m m m m m     }
\prop_put:Nnn \c__xparse_shorthands_prop { 8 } { m m m m m m m m   }
\prop_put:Nnn \c__xparse_shorthands_prop { 9 } { m m m m m m m m m }
\ExplSyntaxOff

\NewDocumentCommand\foo{ O{bigg} 3 a b }
 {
  \csname#1l\endcsname(
    #2 \csname#1m\endcsname| \frac{#3}{#4}
  \csname#1r\endcsname)
  \IfValueT{#5}{_{\mkern-5mu \mathrm{#5}}}
  \IfValueT{#6}{^{\mkern-5mu \{#6\}}}
 }
\NewDocumentCommand\baz{ a b }
 {\iiiint\limits\IfValueT{#1}{_{#1}}\IfValueT{#2}{^{\quad#2}}}
\NewDocumentCommand\lint{ A{a} B{b} }{\underline{\int_{#1}^{#2}}}
\NewDocumentCommand\uint{ A{a} B{b} }{\overline{\int_{#1}^{#2}}}

\begin{document}
\[
  \foo{X}{Y}{Z}_{min}^{bc} \quad
  \lint f(t) \, dt \quad
  \uint_{a(s)}^{b(s)} f(t) \, dt \quad
  \iiiint\limits_{aaa}^{bbb} \xi \quad
  \baz_{aaa}^{bbb} \zeta
\]
\end{document}

enter image description here

May be in the future I try to create something like t{*,-,+,!} so that a command takes one token if it's there from the list \foo*, \foo-, \foo+ or \foo! without the need ot t* t- t+ t!.

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.