朋友们,我正在尝试移植我的旧密码到 LaTeX3 实现。感谢 egreg、Joseph 和 David,我取得了很大的进步!但后来,我陷入了困境。
从上面的链接,我正在移植我的歌本项目。如你所知,我的歌曲有多个索引,我过去常常事先对它们进行硬编码。如果不添加更多条件,代码就无法扩展。
我的想法是:有一个列表(逗号分隔的列表,或者用 L3 术语来说,一个clist
)保存索引名称,另一个列表保存缩写名称。如果我想将单词作为缩写添加Hello world
到索引中F
,我会在缩写列表中搜索我的项目的位置,然后检查其名称对应项。
从现在起,这个词指数将用于引用标识数组元素的整数指针,而不是我们在排版中拥有的信息列表。
和往常一样,egreg 拯救了我,并帮我编写了一个 L3 代码来查找 a 中的项目clist
并返回其索引i
。该代码具有以下方法:
i > 0
: 中第一次出现该项目clist
。需要注意的是clist
的索引以 开头1
。i = 0
:列表中未找到该项目。
我正在努力使用此查找代码中的值来从其他列表中获取项目\clist_item:Nn
。让我们看一些代码:
% arara: pdflatex: { shell: on }
% arara: pdflatex
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{xparse}
\usepackage{imakeidx}
\ExplSyntaxOn
\clist_new:N \l_vozes_extensions_clist
\clist_new:N \l_vozes_abbreviations_clist
\int_new:N \l_vozes_index_step_int
\bool_new:N \l_vozes_index_found_bool
\cs_new:Npn \vozes_getitemindex:Nn #1 #2
{
\int_zero:N \l_vozes_index_step_int
\bool_set_false:N \l_vozes_index_found_bool
\clist_map_inline:Nn #1
{
\int_incr:N \l_vozes_index_step_int
\tl_if_eq:nnT { #2 } { ##1 }
{ \clist_map_break:n { \bool_set_true:N \l_vozes_index_found_bool } }
}
\bool_if:NTF{ \l_vozes_index_found_bool }{ \int_to_arabic:n { \l_vozes_index_step_int } }{ 0 }
}
\cs_new:Npn \vozes_newthematicindex:nnnn #1 #2 #3 #4
{
\clist_put_right:Nn \l_vozes_extensions_clist { #1 }
\clist_put_right:Nn \l_vozes_abbreviations_clist { #3 }
\makeindex[name=#1,title=#2,columns=#4]
}
\NewDocumentCommand{\newthematicindex}{ m m m m }{
\vozes_newthematicindex:nnnn { #1 }{ #2 }{ #3 }{ #4 }
}
\NewDocumentCommand{\thematicindex}{ m m }{
%\clist_item:Nn \l_vozes_extensions_clist {
% \vozes_getitemindex:Nn \l_vozes_abbreviations_clist { #1 }
%}
\index[ \clist_item:Nn \l_vozes_extensions_clist { 1 } ]{ #2 }
}
\NewDocumentCommand{\printthematicindex}{ m }{
%\clist_item:Nn \l_vozes_extensions_clist {
% \vozes_getitemindex:Nn \l_vozes_abbreviations_clist { #1 }
%}
\printindex[ \clist_item:Nn \l_vozes_extensions_clist { 1 } ]
}
\ExplSyntaxOff
\newthematicindex{ifoo}{The list of Foo}{F}{2}
\newthematicindex{ibar}{Bar is cool}{B}{2}
\newthematicindex{ifb}{Foo and Bar}{FB}{2}
\begin{document}
Hello.
\thematicindex{F}{Hello Foo}
\thematicindex{B}{Hello Bar}
\thematicindex{FB}{Hello Foobar}
\printthematicindex{F}
\printthematicindex{B}
\printthematicindex{FB}
\end{document}
当然,这段代码不起作用。:)
有问题的部分在注释部分:
%\clist_item:Nn \l_vozes_extensions_clist {
% \vozes_getitemindex:Nn \l_vozes_abbreviations_clist { #1 }
%}
我对整数值一头雾水。:(
说到这,我想知道如何将命令的返回保存到变量中,我应该使用\def
吗?
最后一个问题:混合使用 L2 和 L3 是好的做法吗?\ExplSyntaxOff
每次我有 L2 代码时都应该这样做吗,或者没有任何副作用?
任何启示都值得赞赏。:)
答案1
\clist_item:Nn
期望第二个参数中有一个数字指定,但它\vozes_getitemindex:Nn
没有提供,因为它是一组用于提供整数的指令。
这里有一种方法:计算整数并将其输入到\clist_item:Nn
。但是,存在不可扩展的故障\clist_item:Nn
;因此序列似乎是更好的选择。
% arara: pdflatex: { shell: on }
% arara: pdflatex
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{xparse}
\usepackage{imakeidx}
\ExplSyntaxOn
\seq_new:N \g_vozes_extensions_seq
\seq_new:N \g_vozes_abbreviations_seq
\int_new:N \l_vozes_index_step_int
\bool_new:N \l_vozes_index_found_bool
\cs_new_protected:Npn \vozes_getitemindex:Nn #1 #2
{
\int_zero:N \l_vozes_index_step_int
\bool_set_false:N \l_vozes_index_found_bool
\seq_map_inline:Nn #1
{
\int_incr:N \l_vozes_index_step_int
\tl_if_eq:nnT { #2 } { ##1 }
{ \seq_map_break:n { \bool_set_true:N \l_vozes_index_found_bool } }
}
\bool_if:NF{ \l_vozes_index_found_bool }{ \int_zero:N \l_vozes_index_step_int }
}
\cs_new_protected:Npn \vozes_newthematicindex:nnnn #1 #2 #3 #4
{
\seq_gput_right:Nn \g_vozes_extensions_seq { #1 }
\seq_gput_right:Nn \g_vozes_abbreviations_seq { #3 }
\makeindex[name=#1,title=#2,columns=#4]
}
\NewDocumentCommand{\getitemindex}{mm}
{
\vozes_getitemindex:Nn #1 { #2 }
\int_to_arabic:n { \l_vozes_index_step_int }
}
\NewDocumentCommand{\newthematicindex}{ m m m m }{
\vozes_newthematicindex:nnnn { #1 }{ #2 }{ #3 }{ #4 }
}
\NewDocumentCommand{\thematicindex}{ m m }{
\vozes_getitemindex:Nn \g_vozes_abbreviations_seq { #1 }
\index[ \seq_item:Nn \g_vozes_extensions_seq { \l_vozes_index_step_int } ] { #2 }
}
\NewDocumentCommand{\printthematicindex}{ m }{
\vozes_getitemindex:Nn \g_vozes_abbreviations_seq { #1 }
\printindex[ \seq_item:Nn \g_vozes_extensions_seq { \l_vozes_index_step_int } ]
}
\ExplSyntaxOff
\newthematicindex{ifoo}{The list of Foo}{F}{2}
\newthematicindex{ibar}{Bar is cool}{B}{2}
\newthematicindex{ifb}{Foo and Bar}{FB}{2}
\begin{document}
Hello.
\thematicindex{F}{Hello Foo}
\thematicindex{B}{Hello Bar}
\thematicindex{FB}{Hello Foobar}
\printthematicindex{F}
\printthematicindex{B}
\printthematicindex{FB}
\end{document}
使用属性列表的更有效的实现:
% arara: pdflatex
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{xparse}
\usepackage{imakeidx}
\ExplSyntaxOn
\prop_new:N \g_vozes_abbreviations_prop
\cs_new_protected:Npn \vozes_newthematicindex:nnnn #1 #2 #3 #4
{
\prop_gput:Nnn \g_vozes_abbreviations_prop { #3 } { #1 }
\makeindex[name=#1,title=#2,columns=#4]
}
\NewDocumentCommand{\newthematicindex}{ m m m m }
{
\vozes_newthematicindex:nnnn { #1 }{ #2 }{ #3 }{ #4 }
}
\NewDocumentCommand{\thematicindex}{ m m }
{
\index[ \prop_get:Nn \g_vozes_abbreviations_prop { #1 } ] { #2 }
}
\NewDocumentCommand{\printthematicindex}{ m }
{
\printindex[ \prop_get:Nn \g_vozes_abbreviations_prop { #1 } ]
}
\ExplSyntaxOff
\newthematicindex{ifoo}{The list of Foo}{F}{2}
\newthematicindex{ibar}{Bar is cool}{B}{2}
\newthematicindex{ifb}{Foo and Bar}{FB}{2}
\begin{document}
Hello.
\thematicindex{F}{Hello Foo}
\thematicindex{B}{Hello Bar}
\thematicindex{FB}{Hello Foobar}
\printthematicindex{F}
\printthematicindex{B}
\printthematicindex{FB}
\end{document}