マクロ + フィードバックとしてグループ化をエスケープする

マクロ + フィードバックとしてグループ化をエスケープする

現在、LaTeX を使用したプログラミングをより深く理解するために、LaTeX3 を試しています。そのために、簡単な設定システムを作成しました。

動作は次のように行われます。

  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. 内部: \NewStringSettingexpl3 文字列 ( g_my_author_str) を作成し、必要に応じて値を設定し、3 つのマクロ ( \ClearAuthor\SetAuthor{<Content>}、 )を作成します\GetAuthor

これで、文字列 author のコンテンツをクリア、設定、取得できるようになりました。

問題: キーと値のペアに使用します。グループ内で設定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}

関連情報