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

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}
  • 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 '15 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

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.