Command with simple parsing

The idea is to make \foo open a group and set a selected character as math active inside the group, whose action is just \mathcal. If the argument is a single token, just apply \mathcal to it.

It's quite easy with expl3:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\foo}{m}
 {
  \szumilo_foo:n { #1 }
 }
\cs_new_protected:Nn \szumilo_foo:n
 {
  \tl_if_single:nTF { #1 }
   { \mathcal{#1} }
   { \szumilo_foo_multiple:n { #1 } }
 }
\cs_new_protected:Nn \szumilo_foo_multiple:n
 {
  \group_begin:
  \char_set_mathcode:nn { `* } { "8000 }
  #1
  \group_end:
 }
\char_set_active_eq:NN * \mathcal

\ExplSyntaxOff

\begin{document}

$\foo{*X}+\foo{X}+\foo{X^A}+\foo{*X^A_B}$

\end{document}

enter image description here

If you insist on using # it's a bit more difficult.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\foo}{m}
 {
  \szumilo_foo:n { #1 }
 }
\cs_new_protected:Nn \szumilo_foo:n
 {
  \tl_if_single:nTF { #1 }
   { \mathcal{#1} }
   { \szumilo_foo_multiple:n { #1 } }
 }
\cs_new_protected:Nn \szumilo_foo_multiple:n
 {
  \group_begin:
  \tl_set_rescan:Nnn \l_szumilo_foo_arg_tl { \char_set_catcode:nn { `\# } { 12 } } { #1 }
  \char_set_mathcode:nn { `\# } { "8000 }
  \tl_use:N \l_szumilo_foo_arg_tl
  \group_end:
 }
\cs_new:Nn \szumilo_foo_mathcal:NN { \mathcal{#2} }
\char_set_active_eq:nN { `\# } \szumilo_foo_mathcal:NN

\ExplSyntaxOff

\begin{document}

$\foo{#X}+\foo{X}+\foo{X^A}+\foo{#X^A_B}$

\end{document}

Besides the need of rescanning the argument for making # of category 12, we need to swallow one # (because these tokens get doubled when they have category 6).

Tags:

Macros