3

I would like to define a macro \des that has one argument and adds a subscript to it i.e. \des{a} should correspond to a_{des}. So far the solution is obvious, however the macro should also accept arguments that already contain sub/superscripts and merge the subscripts, if necessary, using a comma. In practice I would like \des{a_{foo1}^{foo2}} to give the same result as a_{foo1, des}^{foo2}.

I am aware of this answer and this, however I am not able to adapt them to my case. Moreover the command \des can also appear in, e.g., figure captions and this seems to create problems, possibly related to hyperref and/or argument expansion.

Thank you very much for your help.

2 Answers 2

2

With expl3

  • We check if there's _ inside the argument of \des;
  • if there is no _ inside, we just append _{\textnormal{des}} to the argument of \des; and
  • if there's indeed at least one _, we substitute it by a macro (\riccardo_dessb:n) which in turn, when expanded, takes one argument (the original subscript) and transforms into _{<original subscript>,\textnormal{des}} (basically _{<whatever>} gets transformed to _{<whatever>,\textnormal{des}}).

Here's the proper code

\documentclass{scrartcl}

\usepackage{xparse,mathtools}

\NewDocumentCommand\des{m}{\csname riccardo_des:nn\endcsname{#1}{_}}
\ExplSyntaxOn
\cs_new_protected:Npn \riccardo_des:nn #1 #2
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_if_in:NnTF \l_tmpa_tl { #2 }
   { \tl_replace_all:Nnn \l_tmpa_tl { #2 } { \riccardo_dessb:n } }
   { \tl_put_right:Nn \l_tmpa_tl { \sb { \textnormal{des} } } }
  \tl_use:N \l_tmpa_tl
 }
\cs_new_protected:Npn \riccardo_dessb:n #1
 { \sb { #1 , \textnormal{des} } }
\ExplSyntaxOff

\begin{document}
$\des{a}$ and $\des{a_{b}^{c}}$
\end{document}

enter image description here

Addition

If you prefer a clear syntax like \des{a}_{b}^{c} rather than \des{a_{b}^{c}}, here's a solution using some code I posted a few weeks ago. It may look cumbersome, but the actual definition is much shorter.

\documentclass{scrartcl}

\usepackage{xparse,mathtools}

% begin addition for new arguments
\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 }
\ExplSyntaxOff
% end

\NewDocumentCommand\des{ma}
  {#1\IfValueTF{#2}{_{#2,\textnormal{des}}}{_{\textnormal{des}}}}

\begin{document}
$\des{a}$ and $\des{a}_{b}^{c}$
\end{document}
1
  • Thanks for the answer. The first solution seems to be enough and it looks far easier. Could you just comment a little bit on what it is exactly going on so that I can maybe customize it in the future if I need?
    – riccardo
    Jul 30, 2015 at 11:45
1

In order to cope with all the possibilities, you can use regular expressions. The only assumption I make is that no space follows _, but this could be accommodated as well.

The name of the functions should be self-explaining. For the syntax of regular expressions, consult texdoc l3regex.

\documentclass{article}
\usepackage{xparse,l3regex}

\ExplSyntaxOn
\NewDocumentCommand{\des}{m}
 {
  \riccardo_des:n { #1 }
 }

\tl_new:N \l_riccardo_des_arg_tl

\cs_new_protected:Nn \riccardo_des:n
 {
  \regex_match:nnTF { \_ } { #1 }
   {
    \riccardo_des_sub:n { #1 }
   }
   {
    \riccardo_des_nosub:n { #1 }
   }
 }

% syntactic sugar
\cs_new_protected:Nn \riccardo_des_replace:nnn
 {
  \tl_set:Nn \l_riccardo_des_arg_tl { #3 }
  \regex_replace_once:nnN { #1 } { #2 } \l_riccardo_des_arg_tl
  \tl_use:N \l_riccardo_des_arg_tl
 }

\cs_new_protected:Nn \riccardo_des_nosub:n
 {
  \riccardo_des_replace:nnn { ([^\^]*) } { \1\cD\_\cB\{\c{destext}\cE\} } { #1 }
 }

\cs_new_protected:Nn \riccardo_des_sub:n
 {
  \regex_match:nnTF { \_\{ } { #1 }
   {
    \riccardo_des_sub_braced:n { #1 }
   }
   {
    \riccardo_des_sub_unbraced:n { #1 }
   }
 }

\cs_new_protected:Nn \riccardo_des_sub_unbraced:n
 {
  \riccardo_des_replace:nnn { \_(.) } { \cD\_\cB\{\1,\c{destext}\cE\} } { #1 }
 }

\cs_new_protected:Nn \riccardo_des_sub_braced:n
 {
  \riccardo_des_replace:nnn { \_\{(.*?)\} } { \cD\_\cB\{\1,\c{destext}\cE\} } { #1 }
 }

\ExplSyntaxOff

\newcommand{\destext}{\mathrm{des}}

\begin{document}

$\des{a}+\des{a^{}}+\des{a^2}$

$\des{a_1}+\des{a_1^2}+\des{a^2_1}$

$\des{a_{1}}+\des{a_{1}^2}+\des{a^2_{1}}$

$\des{a_{1}}+\des{a_{1}^{2}}+\des{a^{2}_{1}}$

\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .