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:
- Creas una configuración a través de
\NewSetting[type = <type>, init = <init-value>]{<Name>}
- 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>}
. \NewStringSetting
creará la cadena, establecerá el valor inicial de la cadena y creará todas las macros necesarias para usar la cadena, por ejemploClear<Name>
,Set<Name>
yGet<Name>
.
Ejemplo |Una configuración de cadena para el autor:
- Creo una configuración llamando
\NewSetting[type = string, init = Dave]{Author}
- Interno:
\NewSetting
llamadas\NewStringSetting[Dave]{Author}
- Interno:
\NewStringSetting
crea 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 xkeyval
para pares clave-valor. \NewSetting
Se configuran \setkeys
dentro de un grupo, por lo que se reinician después de abandonar el grupo (consulteEl comentario de David Carlisle). Pero todas las macros creadas ( \ClearAuthor
y \SetAuthor{<Content>}
) \GetAuthor
no 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:
- ¿Cómo se podría mejorar el código (especialmente con respecto al problema que describí)?
- ¿Hay alguna buena referencia que explique latex3 (conozco el manual de LaTeX3)?
- ¿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}