Nouvelle commande pour chaque lettre

Sep 26 2020

J'utilise des commandes personnalisées pour faciliter à la fois l'écriture et la lecture d'équations LaTeX, telles que:

\newcommand{\bbA}{\mathbb{A}}
\newcommand{\bbB}{\mathbb{B}}
\newcommand{\bbC}{\mathbb{C}}
% etc...
\newcommand{\mcA}{\mathcal{A}}
\newcommand{\mcB}{\mathcal{B}}
\newcommand{\mcC}{\mathcal{C}}
% etc...
\newcommand{\msA}{\mathscr{A}}
\newcommand{\msB}{\mathscr{B}}
\newcommand{\msC}{\mathscr{C}}
% etc...
\newcommand{\mfA}{\mathfrak{A}}
\newcommand{\mfB}{\mathfrak{B}}
\newcommand{\mfC}{\mathfrak{C}}
% etc...
\newcommand{\mfa}{\mathfrak{a}}
\newcommand{\mfb}{\mathfrak{b}}
\newcommand{\mfc}{\mathfrak{c}}
% etc...

Cependant, cela prend 130 lignes de code dans l'en-tête du fichier (que, heureusement, je n'ai pas écrit à la main, j'ai créé un programme pour le faire, c'est pourquoi je suis assez sûr qu'il y a une solution à mon problème). ..

TeXStudio me permet de le mettre entre %BEGIN_FOLDet des %END_FOLDcommentaires, qui me permettent de réduire tout ce désordre. Cependant, j'ai deux préoccupations:

  1. La %BEGIN_FOLDet %END_FOLDchose ne s'effondre pas par défaut, il s'élargi en arrière sur la réouverture du dossier. De plus, je ne suis pas sûr que ce ne soit pas une fonctionnalité uniquement TeXStudio.

  2. Cela affecte-t-il le temps de compilation? Je ne sais pas comment le compilateur gère les \newcommands, mais s'il doit les redéfinir et les recompiler tous à chaque fois, je suis sûr qu'il y a place à amélioration.

Ainsi, je demande ce qui suit:

Existe-t-il un moyen de compacter chaque bloc de 26 commandes en une seule commande?

Enfin , je voudrais ne pas avoir à faire quelque chose comme \bb{A}, \ms{A}, etc , qui est, je ne veux pas seulement un alias à ces commandes. Ce que je suis prêt à réaliser, c'est de me débarrasser de ces accolades, pour deux raisons:

  1. Comme j'utilise ces commandes depuis quelques années maintenant, la mémoire musculaire va être problématique.

  2. Taper Alt Gr+ 4, Alt Gr+ +, aller Left, taper la lettre et Rightrecommencer prend un certain temps: c'est la raison pour laquelle j'ai initialement fait ces commandes.

Je ne suis pas un gourou LaTeX comme certains d'entre vous qui m'ont déjà aidé énormément, et peut-être que j'ai juste raté quelque chose en essayant de trouver une autre approche que mes 130 lignes "force brute" ... Merci pour vos aimables réponses!

Réponses

3 egreg Sep 26 2020 at 03:16

Beaucoup moins de 130 lignes de code.

L'idée est de faire une boucle dans la plage donnée; J'utilise les constantes alphabétiques, donc, par exemple, Acorrespond à 63, mais il n'est pas nécessaire de le connaître. L'index de boucle est désigné par ##1et prendra à son tour le numéro ASCII des lettres; avec l'aide de \char_generate:nnnous pouvons générer le caractère correspondant. La définition est «développée», nous n'avons donc pas besoin de développer la commande, qui est obtenue en la préfixant avec \exp_not:N.

\documentclass{article}
\usepackage{amsmath,amssymb}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\definealphabet}{mmmm}
 {% #1 = prefix, #2 = command, #3 = start, #4 = end
  \int_step_inline:nnn { `#3 } { `#4 }
   {
    \cs_new_protected:cpx { #1 \char_generate:nn { ##1 }{ 11 } }
     {
      \exp_not:N #2 { \char_generate:nn { ##1 } { 11 } }
     }
   }
 }

\ExplSyntaxOff

\definealphabet{bb}{\mathbb}{A}{Z}
\definealphabet{mc}{\mathcal}{A}{Z}
\definealphabet{mf}{\mathfrak}{A}{Z}
\definealphabet{mf}{\mathfrak}{a}{z}

\begin{document}

$\bbA+\mcB+\mfS+\mfz$

\end{document}

3 UlrichDiez Sep 26 2020 at 03:16

La commande \DEFINEbbANDmcANDmsANDmfLOOPest destinée à traiter un argument non limité qui consiste exactement en un jeton. Il vérifie si la signification du premier jeton de son argument est égale à la signification du \relax-primitif.
Si tel est le cas, il avale l'action suivante via \@gobble.
Si ce n'est pas le cas, il suppose que l'argument est un jeton de caractère unique désignant une « lettre» et effectue l'action suivante via \@firstofone:

  • définir la macro à développer\bb⟨letter⟩\bb\mathbb{⟨letter⟩}
  • définir la macro à développer\mc⟨letter⟩\bb\mathcal{⟨letter⟩}
  • définir la macro à développer\ms⟨letter⟩\bb\mathscr{⟨letter⟩}
  • définir la macro à développer\mf⟨letter⟩\bb\mathfrakr{⟨letter⟩}
  • s'appelle à nouveau.

Le concept d'une macro s'appelant à nouveau pour appliquer la même action à un autre argument est appelé récursion de queue.

(Pour définir les macros, j'ai implémenté une petite macro d'aide \CmdNamequi fonctionne comme suit:

\CmdName⟨stuff without braces⟩{macroname}→ ⟨stuff without braces⟩\macroname.

Exemples:

\CmdName\newcommand*{foobar}...→ \newcommand*\foobar....

J'utilise \CmdNamequand je ne suis pas d'humeur à taper \expandafteret \csname..\endcsnamesi souvent. ;-))

\documentclass{article}

\makeatletter
\@ifdefinable\CmdName{\long\def\CmdName#1#{\romannumeral0\innerCmdName{#1}}}%
\newcommand\innerCmdName[2]{\expandafter\exchange\expandafter{\csname #2\endcsname}{ #1}}%
\newcommand\exchange[2]{#2#1}%
\newcommand\DEFINEbbANDmcANDmsANDmfLOOP[1]{%
  \ifx\relax#1\expandafter\@gobble\else\expandafter\@firstofone\fi
  {%
    \CmdName\newcommand*{bb#1}{\mathbb{#1}}%
    \CmdName\newcommand*{mc#1}{\mathcal{#1}}%
    \CmdName\newcommand*{ms#1}{\mathscr{#1}}%
    \CmdName\newcommand*{mf#1}{\mathfrak{#1}}%
    \DEFINEbbANDmcANDmsANDmfLOOP
  }%
}%
\makeatother

% Now for each of the letters define \bb<letter>, \mc<letter>, \ms<letter> and \mf<letter>:

\DEFINEbbANDmcANDmsANDmfLOOP abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\relax

\begin{document}

\show\bba
\show\mca
\show\msa
\show\mfa

\show\bbb
\show\mcb
\show\msb
\show\mfb

%  . 
%  .
%  .
%  .

\show\bbY
\show\mcY
\show\msY
\show\mfY

\show\bbZ
\show\mcZ
\show\msZ
\show\mfZ

\end{document}

Si vous le souhaitez, vous pouvez appliquer une récursion de queue avec une macro \Definealphabet:

\documentclass{article}

\makeatletter
\newcommand\DEFINEALPHABETLOOP[3]{%
  \ifx\relax#3\expandafter\@gobble\else\expandafter\@firstofone\fi
  {\expandafter\newcommand\expandafter*\csname#1#3\endcsname{#2{#3}}%
   \DEFINEALPHABETLOOP{#1}{#2}}%
}%
\newcommand\Definealphabet[2]{%
  \DEFINEALPHABETLOOP{#1}{#2}abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\relax
}%
\makeatother


\Definealphabet{bb}{\mathbb}
\Definealphabet{mc}{\mathcal}
\Definealphabet{ms}{\mathscr}
\Definealphabet{mf}{\mathfrak}


\begin{document}

\show\bba
% ...
\show\bbz


\show\mca
% ...
\show\mcz


\show\msa
% ...
\show\msz


\show\mfa
% ...
\show\mfz


\end{document}