![使用 l3 的用户定义标记别名](https://linux22.com/image/317897/%E4%BD%BF%E7%94%A8%20l3%20%E7%9A%84%E7%94%A8%E6%88%B7%E5%AE%9A%E4%B9%89%E6%A0%87%E8%AE%B0%E5%88%AB%E5%90%8D.png)
我想编写一个提供人文学科学术研究语义标记的软件包(大致遵循 TEI-XML)。在源代码中,用户可以使用宏,例如\term
用于外来词或\socalled
“引号”。
我想提供一组默认的排版命令,每个宏都会扩展为(\term
-> \emph
,\socalled
-> \enquote
)。我还想提供一个简单的键值接口,供用户重新配置这些(例如,满足出版商的规范)。而且,为了未来的稳健性和灵活性,我希望在 中expl3
或至少使用 来完成xparse
。(我必须承认我完全被 搞糊涂了,expl3
但我希望在这里学到一些东西。)
我已经获得了一条\setTagFormat
命令,该命令创建一个新命令,将标记标签别名到其排版宏。我如何使用诸如这样的键值接口来实现这一点l3keys
?
在当前版本(下面的 MWE)中,用户必须为每个标签输入命令\setTagFormat{\term}{\emph}
。因此,也许这样的界面会更好:
\setSemanticTagFormat{
\term = \emph
\q = \enquote
}
在另一种方法中,由于许多标签将被别名为相同的排版命令(基本上是斜体或引号),因此您可以朝另一个方向努力:
\setSemanticTagFormat{
\emph = \term, \mentioned, \foreign, \worktitle
\enquote = \q, \socalled, \parttitle
}
我还想到(回到纯 TeX)我可以这样做:
\let\term\emph
\let\q\enquote
这是一个有效但不理想的例子,xparse
但不是l3keys
:
\documentclass{article}
\usepackage{csquotes}
\usepackage{xparse}
\NewDocumentCommand\setTagFormat{m m}{%
\NewDocumentCommand #1{m}{#2{##1}}%
}
\setTagFormat{\term}{\emph}
\setTagFormat{\q}{\enquote}
\begin{document}
\term{Musica ficta} is the practice of adding accidentals where they are not notated.
The teacher told us, \q{Always sing F-sharp before a cadence on G!}
\end{document}
答案1
稍微简单一点\keyval_parse:NNn
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected:Nn \cashner_make_semantic:Nn
{
\tl_map_inline:nn {#2} % for every token in the second argument,
{ \NewDocumentCommand ##1 {} {#1} } % create the alias to the first
}
\NewDocumentCommand \NewSemanticMarkup { m }
% with keyval syntax,
% | / ignore single keys
% | | \ / and apply our function
% | | \ / / \ to our argument
{ \keyval_parse:NNn \use_none:n \cashner_make_semantic:Nn {#1} }
\ExplSyntaxOff
\usepackage{csquotes}
\NewSemanticMarkup {
\textit = \term,
\enquote = \scare \socalled
}
\begin{document}
hi
\term{hi}
\scare{hi}
\socalled{hi}
\end{document}
答案2
我会避免对应该等同于其他宏的宏进行分组,因为这将使改变含义变得更加困难:如果它们的数量很大,则很难在组中发现它们。
每个等价物一行似乎更好,并且更容易管理变化。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \SetSemanticMarkup { m }
{
\clist_map_inline:nn { #1 }
{
\SetEquivalent{ ##1 }
}
}
\NewDocumentCommand{\SetEquivalent}{ >{\SplitArgument{1}{=}} m }
{
\cashner_set_equivalent:nn #1
}
\cs_new_protected:Nn \cashner_set_equivalent:nn
{
\cs_new_eq:NN #1 #2
}
\ExplSyntaxOff
\usepackage{csquotes}
\SetSemanticMarkup {
\term = \textit,
\scare = \enquote,
\socalled = \enquote,
\q = \enquote,
}
\begin{document}
hi
\term{hi}
\scare{hi}
\socalled{hi}
\term{Musica ficta} is the practice of adding accidentals where they are not notated.
The teacher told us, \q{Always sing F-sharp before a cadence on G\@!}
\end{document}