Nuevo comando para cada letra

Sep 26 2020

Estoy usando comandos personalizados para facilitar tanto la escritura como la lectura de ecuaciones LaTeX, como:

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

Sin embargo, esto ocupa 130 líneas de código en el encabezado del archivo (que, afortunadamente, no escribí a mano, hice un programa para hacerlo, por lo que estoy bastante seguro de que hay una solución a mi problema). ..

TeXStudio me permite encerrarlo entre %BEGIN_FOLDy %END_FOLDcomentarios, que me permiten colapsar todo este lío. Sin embargo, tengo dos preocupaciones:

  1. La cosa %BEGIN_FOLDy %END_FOLDno se colapsa de forma predeterminada, se vuelve a expandir al volver a abrir el archivo. Además, no estoy seguro de que esta no sea una función exclusiva de TeXStudio.

  2. ¿Afecta el tiempo de compilación? No sé cómo maneja el compilador los \newcommands, pero si tiene que volver a definirlos y recompilarlos todos cada vez, estoy seguro de que hay margen de mejora.

Por lo tanto, estoy preguntando lo siguiente:

¿Hay alguna forma de compactar cada bloque de 26 comandos en un solo comando?

En fin , me gustaría no tener que hacer algo como \bb{A}, \ms{A}, etc. , es decir, que no sólo quiero un alias para estos comandos. Lo que estoy dispuesto a lograr es deshacerme de estas llaves, por dos razones:

  1. Como he estado usando estos comandos durante algunos años, la memoria muscular será problemática.

  2. Escribir Alt Gr+ 4, Alt Gr+ +, ir Left, escribir la letra y volver a escribir Rightlleva bastante tiempo: esta es la razón por la que originalmente hice estos comandos.

No soy un gurú de LaTeX como algunos de ustedes que ya me ayudaron muchísimo, y tal vez simplemente me perdí algo al tratar de encontrar otro enfoque que mi "fuerza bruta" 130 líneas ... ¡Gracias por sus amables respuestas!

Respuestas

3 egreg Sep 26 2020 at 03:16

Mucho menos de 130 líneas de código.

La idea es hacer un bucle en el rango dado; Yo uso las constantes alfabéticas, entonces, por ejemplo, Acorresponde a 63, pero no es necesario saberlo. El índice de bucle se indica por ##1y tomará a su vez el número ASCII de las letras; con la ayuda de \char_generate:nnpodemos generar el caracter correspondiente. La definición es “expandida”, por lo que no es necesario expandir el comando, que se obtiene prefijándolo con \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

El comando \DEFINEbbANDmcANDmsANDmfLOOPestá destinado a procesar un argumento no delimitado que consta exactamente de un token. Comprueba si el significado del primer token de su argumento es igual al significado del \relaxprimitivo.
Si es así, se traga la siguiente acción vía \@gobble.
Si no es así, asume que el argumento es un token de un solo carácter que denota una ⟨letra⟩ y realiza la siguiente acción a través de \@firstofone:

  • definir la macro para expandir a\bb⟨letter⟩\bb\mathbb{⟨letter⟩}
  • definir la macro para expandir a\mc⟨letter⟩\bb\mathcal{⟨letter⟩}
  • definir la macro para expandir a\ms⟨letter⟩\bb\mathscr{⟨letter⟩}
  • definir la macro para expandir a\mf⟨letter⟩\bb\mathfrakr{⟨letter⟩}
  • llamarse a sí mismo de nuevo.

El concepto de una macro que se vuelve a llamar a sí misma para aplicar la misma acción a otro argumento se llama recursividad de cola.

(Para definir las macros, he implementado una pequeña macro auxiliar \CmdNameque funciona de la siguiente manera:

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

Ejemplos:

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

Lo uso \CmdNamecuando no estoy de humor para escribir \expandaftery \csname..\endcsnamemuy a menudo. ;-))

\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 lo desea, puede aplicar la recursividad de cola con una 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}