Atualmente, estou testando o latex3 para obter uma compreensão mais profunda da programação com látex. Para isso criei um sistema de configurações simples.
Funciona da seguinte maneira:
- Você cria uma configuração via
\NewSetting[type = <type>, init = <init-value>]{<Name>}
- Com base no seu tipo, ele chama a macro de configuração correspondente: por exemplo, para uma configuração de string, ele chamará
\NewStringSetting[<init-value>]{<Name>}
. \NewStringSetting
criará a string, definirá o valor inicial da string e criará todas as macros necessárias para usar a string, por exemploClear<Name>
,Set<Name>
eGet<Name>
.
Exemplo |Uma configuração de string para o autor:
- Eu crio uma configuração ligando
\NewSetting[type = string, init = Dave]{Author}
- interno:
\NewSetting
chamadas\NewStringSetting[Dave]{Author}
- interno:
\NewStringSetting
cria uma string expl3 (g_my_author_str
), define um valor se necessário e cria 3 macros:\ClearAuthor
,\SetAuthor{<Content>}
e\GetAuthor
.
Agora posso limpar, definir e obter o conteúdo do autor da string.
Problema: eu uso xkeyval
para pares de valores-chave. Eles são configurados \NewSetting
dentro \setkeys
de um grupo e são redefinidos após sair do grupo (vejaComentário de David Carlisle). Mas todas as macros criadas ( \ClearAuthor
, \SetAuthor{<Content>}
e \GetAuthor
) ficam indefinidas após sair do grupo. Uma solução seria livrar-se do grupo, mas os pares de valores-chave não serão redefinidos conforme o esperado. Portanto, não é realmente uma solução. Então eu tropeceiA solução do @wipetencaminhar as macros para fora do grupo; mantendo assim as macros enquanto todas as teclas são redefinidas no final do grupo. Parece uma solução funcional.
Pergunta: Ainda sou muito novo no LaTeX, especialmente no latex3. Estou bastante satisfeito com o resultado até agora (afinal funciona), mas gostaria de saber o que você acha. Gostaria de saber se existe uma maneira mais fácil e o que posso melhorar.
A maior dificuldade que tive foi a expansão. Existem boas referências (por exemplo, Youtube, postagens em fóruns, etc.)? (especialmente aqueles que também abordam latex3 e suas primitivas como \exp_last_unbraced
...)
Summa summarum:
- como o código poderia ser melhorado (especialmente no que diz respeito ao problema que descrevi)?
- existem boas referências explicando o latex3 (eu conheço o manual do LaTeX3)?
- existe alguma regra prática para acertar a expansão sem tentativa e erro
Código de configuração de string:
\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}