5

For example, I have created multiple commands as

\newcommand{\A}{\mathcal A}
\newcommand{\B}{\mathcal B}
\newcommand{\C}{\mathcal C}

Is it possible to combine all those commands as a single one, like the following?

\newcommand{\*}{\mathcal *}

3 Answers 3

4

Not exactly the desired (but very imprecise) syntax offered by the OP, but something that might work for you. Note this will not check if \A, \B, or \C already exist, and will instead overwrite any extant definition.

\documentclass{article}
\usepackage{listofitems}
\newcommand\makemathcal[1]{
  \readlist\mylist{#1}%
  \foreachitem\z\in\mylist[]{%
    \expandafter\gdef\csname\z\expandafter\endcsname
      \expandafter{\expandafter\mathcal\expandafter{\z}}%
  }%
}
\begin{document}
\makemathcal{A,B,C}

$\A \ne \B > \C$

\end{document}

enter image description here

Perhaps a slightly improved (yet decidedly more dangerous) syntax would be to take advantage of the pgffor list specification:

\documentclass{article}
\usepackage{pgffor}
\newcommand\makemathcal[1]{
  \foreach\z in{#1}{%
    \expandafter\gdef\csname\z\expandafter\endcsname
      \expandafter{\expandafter\mathcal\expandafter{\z}}%
  }%
}
\begin{document}
\makemathcal{A,...,Z}

$\A \ne \B > \Z$

\end{document}

enter image description here

13
  • haha, thanks. This is a workaround.
    – stackname
    Apr 27, 2021 at 20:13
  • @whatsname One problem with your desired syntax is it is all inclusive, so that \a, \l, \i, etc would all be REdefined, since they exist. So, somehow, you need to limit the application, which I do by specifying an enumerated list to cover the extent. Apr 27, 2021 at 20:15
  • @whatsname Please see the addendum to my answer. Apr 27, 2021 at 20:20
  • 2
    @whatsname it's a really bad idea to over-write standard commands such as \O and \H Apr 27, 2021 at 20:46
  • 2
    Øver use of this will go bőőm Apr 27, 2021 at 20:49
4

The easiest way to do it is using

#1

as general entry.

Look at my code:


\documentclass{article}

\newcommand{\calll}[1]{\mathcal{#1}}

    \begin{document}

    $\calll{A}$

    $\calll{B}$

    $\calll{C}$

\end{document}

Enter image description here

In this way, you can solve your problem in a very simple and elegant way.

2
  • Thanks. But if I write $\calll{A}$, then it is the same as writing $\mathcal{A}$. :)
    – stackname
    Apr 27, 2021 at 20:16
  • 2
    Except in this case, \calll{A} is only two keystrokes less than \mathcal{A}, and a bit more obtuse. Apr 27, 2021 at 20:17
4

There is no “wildcard” feature, but it's possible to emulate it.

\documentclass{article}
\usepackage{amssymb}
%\usepackage{xparse} % uncomment if running LaTeX prior to 2020-10-01

\ExplSyntaxOn
\NewDocumentCommand{\makelettercommands}{mmm}
 {% #1 = template
  % #2 = wrapper (for instance \mathcal)
  % #3 = list of ranges
  \whatsname_mlc:nnn { #1 } { #2 } { #3 }
 }

\seq_new:N \l__whatsname_mlc_range_seq
\seq_new:N \l__whatsname_mlc_list_seq
\cs_generate_variant:Nn \int_step_inline:nnn { ee }

\cs_new_protected:Nn \whatsname_mlc:nnn
 {
  % set a scratch function to the template
  \cs_set:Nn \__whatsname_mlc_name:n { #1 }
  % map the list of ranges (or single letters)
  \clist_map_inline:nn { #3 }
   {
    \__whatsname_mlc_do:nnn { ##1 } { #1 } { #2 }
   }
 }

\cs_new_protected:Nn \__whatsname_mlc_do:nnn
 {% split at a possible -
  \seq_clear:N \l__whatsname_mlc_list_seq
  \seq_set_split:Nnn \l__whatsname_mlc_range_seq { - } { #1 }
  \int_compare:nTF { \seq_count:N \l__whatsname_mlc_range_seq = 1 }
   {% no range
    \seq_put_right:Nn \l__whatsname_mlc_list_seq { #1 }
   }
   {% range
    \int_step_inline:een
     { `\seq_item:Nn \l__whatsname_mlc_range_seq { 1 } } % first item is start of range
     { `\seq_item:Nn \l__whatsname_mlc_range_seq { 2 } } % second item is end of range
     { \seq_put_right:Nx \l__whatsname_mlc_list_seq { \char_generate:nn { ##1 } { 11 } } }
   }
  \cs_set_protected:Nn \__whatsname_mlc_def:n
   {
    \cs_new_protected:cpn { \__whatsname_mlc_name:n { ##1 } } { #3 { ##1 } }
   }
  \seq_map_function:NN \l__whatsname_mlc_list_seq \__whatsname_mlc_def:n
 }

% just for a check, show the commands
\NewDocumentCommand{\showcs}{m}
 {
  \texttt{ \token_to_str:N #1 ~->~ \cs_replacement_spec:N #1 }
 }

\ExplSyntaxOff

\makelettercommands{c#1}{\mathcal}{A-C,E}
\makelettercommands{#1}{\mathcal}{D}
\makelettercommands{#1#1}{\mathbb}{C,H,N,Q,R,X-Z}
\makelettercommands{#1frak}{\mathfrak}{a-z}

\begin{document}

$\cA+\cC+\cE+\D+\ZZ+\YY-\afrak$

\showcs\cA

\showcs\ZZ

\showcs\zfrak

\end{document}

I can't recommend defining \A to \mathcal{A}, better using something a little more complex that carries some semantics. For instance \cA and so on.

In the example I do \NN and so on for the most common number sets; but note that \AA is already defined. In the \mathbb example, I use Y-Z to show the usage of mixed specs (single letters and ranges).

As you see, in the first argument to \makelettercommands we have #1 acting as a wildcard for the letters specified in the third argument.

enter image description here

3
  • Thanks a lot. Using this template, I can easily create many self-defined commands. Also, it took me some time to understand your code. :)
    – stackname
    Apr 30, 2021 at 19:58
  • @whatsname Note that \usepackage{xparse} is only needed if you run an outdated LaTeX released prior to 2020-10-01
    – egreg
    Apr 30, 2021 at 20:52
  • You are right. I do run an old version.
    – stackname
    May 1, 2021 at 0:09

You must log in to answer this question.

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