Escapar de agrupación como macro + comentarios

Escapar de agrupación como macro + comentarios

Actualmente estoy probando latex3 para obtener una comprensión más profunda de la programación con látex. Para ello he creado un sistema de configuración sencillo.

Funciona de la siguiente manera:

  1. Creas una configuración a través de\NewSetting[type = <type>, init = <init-value>]{<Name>}
  2. Según su tipo, llama a su macro de configuración correspondiente: por ejemplo, para una configuración de cadena llamará \NewStringSetting[<init-value>]{<Name>}.
  3. \NewStringSettingcreará la cadena, establecerá el valor inicial de la cadena y creará todas las macros necesarias para usar la cadena, por ejemplo Clear<Name>, Set<Name>y Get<Name>.

Ejemplo |Una configuración de cadena para el autor:

  1. Creo una configuración llamando\NewSetting[type = string, init = Dave]{Author}
  2. Interno: \NewSettingllamadas\NewStringSetting[Dave]{Author}
  3. Interno: \NewStringSettingcrea una cadena expl3 ( g_my_author_str), establece, si es necesario, un valor y crea 3 macros \ClearAuthor: \SetAuthor{<Content>}y \GetAuthor.

Ahora puedo borrar, configurar y obtener el contenido del autor de la cadena.

Problema: lo uso xkeyvalpara pares clave-valor. \NewSettingSe configuran \setkeysdentro de un grupo, por lo que se reinician después de abandonar el grupo (consulteEl comentario de David Carlisle). Pero todas las macros creadas ( \ClearAuthory \SetAuthor{<Content>}) \GetAuthorno están definidas después de abandonar el grupo. Una solución sería deshacerse del grupo, pero los pares clave-valor no se restablecerán según lo previsto. Entonces no es realmente una solución. Entonces me topé conLa solución de @wipetreenviar las macros fuera del grupo; manteniendo así las macros mientras todas las claves se reinician al final del grupo. Parece una solución funcional.

Pregunta: Todavía soy bastante nuevo en LaTeX, especialmente en latex3. Estoy bastante satisfecho con el resultado hasta ahora (después de todo, funciona), pero me gustaría saber qué piensas. Me gustaría saber si hay una manera más fácil y qué podría mejorar.

La mayor dificultad que tuve fue la expansión. ¿Hay buenas referencias (por ejemplo, Youtube, publicaciones en foros, etc.)? (especialmente aquellos que también abordan latex3 y sus primitivas como \exp_last_unbraced...)

suma sumarum:

  1. ¿Cómo se podría mejorar el código (especialmente con respecto al problema que describí)?
  2. ¿Hay alguna buena referencia que explique latex3 (conozco el manual de LaTeX3)?
  3. ¿Existe alguna regla general para lograr una expansión correcta sin prueba y error?

Código de configuración de cadena:

\documentclass{book}

\usepackage{expl3} % Only needed for IDE-autocomplete (aka IntelliSense)
\usepackage{xkeyval}

\makeatletter
\ExplSyntaxOn

% By egreg https://tex.stackexchange.com/a/63233/293060
\NewExpandableDocumentCommand{\IfNoValueOrEmptyTF}{m m m}{%
    \IfNoValueTF{#1}{#2}{%
        \tl_if_empty:nTF{#1}{#2}{#3}%
    }%
}%

% By wipet https://tex.stackexchange.com/a/690710/293060
\def\keepaftergroup#1{%
   \global \expandafter\let \csname x:\string#1\endcsname =#1
   \aftergroup\let
   \aftergroup#1%
   \expandafter\aftergroup \csname x:\string#1\endcsname
   
}

\define@key[DAVE]{settings}{type}{\def\DAVE@Settings@Type{#1}}
\define@key[DAVE]{settings}{init}{\def\DAVE@Settings@Init{#1}}

\NewDocumentCommand{\NewSetting}{o m}{%
    \begingroup
        \setkeys[DAVE]{settings}{#1}%
        \cs_if_exist:NTF\DAVE@Settings@Type{%
            \str_case:NnF{\DAVE@Settings@Type}{%
                {string}{\begingroup\edef\x{\endgroup\noexpand\NewStringSetting[\cs_if_exist:NT\DAVE@Settings@Init{\DAVE@Settings@Init}]{#2}}\keepaftergroup\x} % <--- Wont work without \keepaftergroup, only if \begingroup + \endgroup removed (but then keys wont reset)
                %{bool}{...}
            }{%
                \ClassError{SETTINGS}{Unknown~settings~type~for~setting~'#2'}{}
            }
        }{%
            \ClassError{SETTINGS}{Cannot~create~setting~'#2'~due~to~missing~setting~type}{}
        }
    \endgroup
    \x % <--- Calling
}

\NewDocumentCommand{\NewStringSetting}{o m}{%
    \str_if_exist:cTF{g_DAVE_#2_str}{%
        \ClassError{SETTINGS}{String~with~the~name~'#2'~already~exist}{}
    }{%
        \str_gclear_new:c{g_DAVE_#2_str}
        \IfValueT{#1}{%
            \str_gset:cn{g_DAVE_#2_str}{#1}
        }
        \expandafter\NewExpandableDocumentCommand\expandafter{\csname Clear#2\endcsname}{}{%
            \str_gclear:c{g_DAVE_#1_str}
        }
        \expandafter\NewExpandableDocumentCommand\expandafter{\csname Set#2\endcsname}{m}{%
            \IfNoValueOrEmptyTF{##1}{%
                \ClassWarning{SETTINGS}{Could~not~set~value~for~setting~'#2'~due~to~the~passed~value~being~of~type~'NoValue'~or~empty}%
            }{%
                \str_gset:cn{g_DAVE_#2_str}{##1}%
            }%
        }
        \expandafter\NewExpandableDocumentCommand\expandafter{\csname Get#2\endcsname}{}{%
            \str_use:c{g_DAVE_#2_str}
        }
    }
}

\ExplSyntaxOff
\makeatother

\NewSetting[type = string]{Forum}
\NewSetting[type = string, init = Dave]{Author}

\SetForum{StackExchange}

\begin{document}
    Hello \TeX-\GetForum \space it's \GetAuthor
\end{document}

información relacionada