我想为我的文档建立一个关键字/标签/标记/标记系统。将有一个允许关键字的硬编码列表,并且所有定理/示例/练习将(可选)用其中一个关键字标记。编译文档应检查是否使用了有效的关键字作为标记并(如果需要)打印它。
我正在尝试使用包来实现arrayjob
。我的所有标签都将存储在一个名为的数组中tagtoken
,命令\tagit
将执行实际标记工作。我尝试使用来自 tex.stackexchange 各种问题的零碎代码来破解代码。但是我对 并不真正了解expl3
。
这是我的 MWE
\documentclass{article}
\usepackage{arrayjob,expl3,xparse,pgffor}
\newtheorem{theorem}{Theorem}
\newarray\tagtoken
\readarray{tagtoken}{RAG&TAG&BAG} % should be case insensitive
\newarray\tokenlist
\ExplSyntaxOn
\NewDocumentCommand{\tagit}{m}
{
\tl_set:Nn \l_tmpa_tl {\tl_lower_case:n{#1}}
\regex_replace_all:nnN {,} {&} \l_tmpa_tl
\regex_replace_all:nnN {\s+} {} \l_tmpa_tl
\readarray{tokenlist}{\l_tmpa_tl} % does not work
\regex_replace_all:nnN {&} {, } \l_tmpa_tl % just for displaying
\newline Keywords = \tl_use:N \tl_upper_case:n{\l_tmpa_tl}
}
\ExplSyntaxOff
\begin{document}
\begin{theorem}
Dummy theorem \tagit{g,h , k, rag, TAG} % should throw an error and stop compilation till invalid tokens are purged.
\end{theorem}
%\foreach\x in {1,...,3} {\noindent tagtoken(\x) = \tagtoken(\x)\hfil\\}
one = \tokenlist(1) % no output
\begin{theorem}
two \tagit{rag,TaG} % no error
\end{theorem}
\begin{theorem}
three \tagit{rag, RAg} % should produce a warning for repeated tags
\end{theorem}
\end{document}
我该如何让它工作?抱歉,我问了一个货物崇拜的问题。
答案1
使用没有意义arrayjob
,因为expl3
提供了更好的功能。
\documentclass{article}
\usepackage{xparse}
\newtheorem{theorem}{Theorem}
\ExplSyntaxOn
\NewDocumentCommand{\definetags}{m}
{
\clist_gset:Nn \g_magguu_tags_clist { #1 }
}
\NewDocumentCommand{\tagit}{m}
{
\magguu_tags_tagit:n { #1 }
}
%% variables
\clist_new:N \g_magguu_tags_clist
\seq_new:N \l__magguu_tags_seq
%% variants
\prg_generate_conditional_variant:Nnn \clist_if_in:Nn { Nx } { T,F,TF }
\prg_generate_conditional_variant:Nnn \seq_if_in:Nn { Nx } { T,F,TF }
%% messages
\msg_new:nnnn { magguu/tags } { invalid }
{
Invalid~tag~'#1'~on~line~\msg_line_number:
}
{
The~tag~'#1'~is~not~among~the~valid~tags. \\ Fix~it.
}
\msg_new:nnn { magguu/tags } { duplicate }
{
The~tag~'#1'~is~duplicate~on~line~\msg_line_number:
}
%% functions
\cs_new_protected:Nn \magguu_tags_tagit:n
{
\seq_clear:N \l__magguu_tags_seq
\clist_map_inline:nn { #1 }
{
\clist_if_in:NxTF \g_magguu_tags_clist { \tl_upper_case:n { ##1 } }
{ % the tag is valid
\seq_if_in:NxTF \l__magguu_tags_seq { \tl_upper_case:n { ##1 } }
{ % the tag is duplicate
\msg_warning:nnn { magguu/tags } { duplicate } { ##1 }
}
{ % add the tag
\seq_put_right:Nx \l__magguu_tags_seq { \tl_upper_case:n { ##1 } }
}
}
{ % invalid tag
\msg_error:nnn { magguu/tags }{ invalid } { ##1 }
}
}
\newline Keywords:\nobreakspace\seq_use:Nn \l__magguu_tags_seq { ,~ }
}
\ExplSyntaxOff
\definetags{RAG,TAG,BAG}
\begin{document}
\begin{theorem}
Dummy theorem \tagit{g,h , k, rag, TAG}
\end{theorem}
\begin{theorem}
two \tagit{rag,TaG} % no error
\end{theorem}
\begin{theorem}
three \tagit{rag, RAg} % should produce a warning for repeated tags
\end{theorem}
\end{document}
输出
控制台输出(错误和警告)
! Package magguu/tags Error: Invalid tag 'g' on line 69
For immediate help type H <return>.
...
l.69 Dummy theorem \tagit{g,h , k, rag, TAG}
? h
The tag 'g' is not among the valid tags.
Fix it.
?
! Package magguu/tags Error: Invalid tag 'h' on line 69
For immediate help type H <return>.
...
l.69 Dummy theorem \tagit{g,h , k, rag, TAG}
?
! Package magguu/tags Error: Invalid tag 'k' on line 69
For immediate help type H <return>.
...
l.69 Dummy theorem \tagit{g,h , k, rag, TAG}
?
Package magguu/tags Warning: The tag 'RAg' is duplicate on line 77
答案2
这可以通过包中的列表处理来实现etoolbox
。其思路是创建一个允许的标签列表,然后根据\tagit
该列表检查输入中的每个项目。
可以使用包含已使用标签的单独列表(每个新标签列表都会重置)来检查重复项。
可以使用内置\GenericError
和\GenericWarning
命令创建错误和警告。
可以通过创建小写允许标签列表并在对照列表检查之前将标签转换为小写来实现不区分大小写的检查。这需要一些奇怪的语法,请参阅https://tex.stackexchange.com/a/286386/。
在下面的代码中,首先进行重复检查,只有标签不是重复时才进行错误检查和实际标签打印。
梅威瑟:
\documentclass{article}
\usepackage{etoolbox}
\newtheorem{theorem}{Theorem}
\begin{document}
% create list of allowed tags
\forcsvlist{\listadd\allowedtags}{rag,tag,bag}
% macro for processing a single tag
\renewcommand*{\do}[1]{%
% put argument in lower case
\lowercase{\def\lcarg{#1}}%
% check if item is already used
\xifinlist{\lcarg}{\useditems}{\GenericWarning{xxx}{Warning: duplicated tag '#1'}}{%
% check if item is in list of allowed tags
\xifinlist{\lcarg}{\allowedtags}{\fbox{\normalfont #1} }{\GenericError{xxx}{tag not allowed: #1}{please remove tag}{further help}}}%
% add item to list of used items
\listeadd{\useditems}{\lcarg}%
}
% command for processing tag list
\newcommand{\tagit}[1]{%
% reset list of used items
\gdef\useditems{}
% execute \do for each item in the list
\docsvlist{#1}%
}
\begin{theorem}
Dummy theorem \tagit{g,h , k, rag, TAG, rag} % should throw an error and stop compilation till invalid tokens are purged.
%Dummy theorem \tagit{rag, TAG, RaG}
\end{theorem}
\end{document}
这会触发错误:
! tag not allowed: g.
please remove tag
Type H <return> for immediate help.
...
l.18 Dummy theorem \tagit{g,h , k, rag, TAG, rag}
% should throw an error an...
注释有问题的行并取消注释下一行会触发警告:
Warning: duplicated tag 'RaG' on input line 19.
生成的pdf:
当然,如果您想对标签做一些不同的事情(有条件打印、在文档的其他地方创建列表/索引等),那么您应该修改允许标签检查的第一个子句(部分\fbox
)。