以宏 + 反馈的方式退出分组

以宏 + 反馈的方式退出分组

我目前正在尝试 latex3,以便更深入地了解使用 latex 进行编程。为此,我创建了一个简单的设置系统。

其工作原理如下:

  1. 您可以通过以下方式创建设置\NewSetting[type = <type>, init = <init-value>]{<Name>}
  2. 根据其类型,它调用其相应的设置宏:例如,对于字符串设置,它将调用\NewStringSetting[<init-value>]{<Name>}
  3. \NewStringSetting将创建字符串,设置字符串的初始值并创建使用该字符串所需的所有宏,例如Clear<Name>和。Set<Name>Get<Name>

示例 |作者的字符串设置:

  1. 我通过调用创建一个设置\NewSetting[type = string, init = Dave]{Author}
  2. 内部的\NewSetting调用\NewStringSetting[Dave]{Author}
  3. 内部的\NewStringSetting创建一个 expl3 字符串(g_my_author_str),如果需要则设置一个值并创建 3 个宏:\ClearAuthor\SetAuthor{<Content>}\GetAuthor

现在我可以清除、设置和获取字符串作者的内容。

问题:我用于xkeyval键值对。它们\NewSetting通过\setkeys组内设置,因此离开组后会重置(请参阅大卫·卡莱尔的评论)。但是,离开组后,所有创建的宏(\ClearAuthor\SetAuthor{<Content>}\GetAuthor)都未定义。一个解决方案是删除该组,但键值对不会按预期重置。所以这不是真正的解决方案。然后我偶然发现了@wipet 的解决方案将宏转发出组;这样保留宏,同时所有键仍然在组末尾重置。看起来是个可行的解决方案。

问题:我对 LaTeX 还不太熟悉,尤其是 latex3。到目前为止,我对结果相当满意(毕竟它有效),但我想知道您的想法。我想知道是否有更简单的方法以及我可以改进什么。

我遇到的最大困难是扩展。 有没有什么好的参考资料(例如 Youtube、论坛帖子等)?(尤其是那些也涉及 latex3 及其原语的参考资料,例如\exp_last_unbraced...)

概要

  1. 代码如何改进(特别是针对我所描述的问题)?
  2. 有没有什么好的参考资料解释 latex3 (我知道 LaTeX3 的手册)?
  3. 是否有一些经验法则可以让你无需反复试验就能正确进行扩展

字符串设置代码

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

相关内容