Группировка побегов как макрос + обратная связь

Группировка побегов как макрос + обратная связь

В настоящее время я пробую свои силы в 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}

Связанный контент