6

I would like to write a command \foo that takes a math-mode expression and renders it with some selected symbols (say denoted by #) printed in \mathcal. For example, \foo{#X^A_B} should expand to \mathcal{X}^A_B.

As a side question, it would be convenient if the command had the following behaviour. If the input consists of multiple symbols, then it is parsed as described above. However, if the input consists of only a single symbol, then this symbol should be converted to \mathcal even if it is not preceded by #. E.g. \foo{X} and \foo{#X} should both expand to \mathcal{X} while \foo{X^A} should expand to X^A.

What is the simplest way to accomplish this? I do not insist on this particular syntax. Any reasonably compact syntax will do.

  • To be more explicit, you'd like that \foo{X^A_B} does \mathcal{X}^A_B? What characters should be subject to the transformation? And isn't it better to type \mc{X}^A_B? – egreg Sep 28 '15 at 11:56
  • And what should other symbols be? What's the replacement then? – user31729 Sep 28 '15 at 11:56
  • @egreg, no \foo{X^A_B} should be just X^A_B since X was not labelled by #. I don't want a shortcut like \mc{X} since \foo is really a longer name that carries some meaning that I want to retain to make the code more readable. – Karol Szumiło Sep 28 '15 at 11:59
  • @KarolSzumiło Please make more precise what you mean by “regardless of the presence of #”. – egreg Sep 28 '15 at 12:03
  • @egreg, I edited the question to clarify. – Karol Szumiło Sep 28 '15 at 12:07
5

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).

  • This looks exactly like what I wanted. I used # only as an example so this is not a big deal. Could I choose other symbols in the place of * without making it more complicated? Or maybe I should ask: what are the symbols that I cannot use without modifying this approach? – Karol Szumiło Sep 28 '15 at 12:28
  • @KarolSzumiło You can use all characters that are neither letters nor special characters (* + - ? ! ; : , . ` @) but not '. Of course the selected marker must not appear in other roles in the argument. I added also the trick for using #. – egreg Sep 28 '15 at 12:31
0

Here is a simple way, using listofitems parsing:

\documentclass{article}
\usepackage{listofitems}
\newcommand\foo[1]{\fooaux#1\fooend}
\def\fooaux#1#2\fooend{
  \ifx\relax#2\relax\mathcal{#1}\else
    \setsepchar{"}
    \readlist\mylist{#1#2}
    \foreachitem\i\in\mylist{
      \ifnum\icnt=1\else\expandafter\expandafter\expandafter\mathcal\expandafter\fi
      \i
    }
  \fi
}
\begin{document}
$\foo{X}\quad\foo{"X}\quad\foo{X^A}$

$\foo{"X}+\foo{X}+\foo{X^A}+\foo{"X^A_B}$
\end{document}

enter image description here

And an even simpler way with \catcodes, producing the same result.

\documentclass{article}
\catcode`"=\active %
\def"{\mathcal}
\newcommand\foo{\catcode`"=\active\fooz}
\newcommand\fooz[1]{\foozz#1\fooend}
\def\foozz#1#2\fooend{\ifx\relax#2\relax\mathcal{#1}\else#1#2\fi}
\catcode`"=12 %
\begin{document}
$\foo{X}\quad\foo{"X}\quad\foo{X^A}$

$\foo{"X}+\foo{X}+\foo{X^A}+\foo{"X^A_B}$
\end{document}

Since the OP wasn't tied to a particular syntax, I changed the special character from # to ".

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.